本文实例为大家分享了iOS自定义View实现卡片滑动效果的具体代码,供大家参考,具体内容如下

说明

控件基于UIView封装完成,采用UIPanGestureRecognizer监听自身的触摸事件,以此处理各种滑动动画操作。
内容之间可以循环切换,采用类似tableView加载机制,达到复用效果

效果

代码实现

#import <UIKit/UIKit.h>
@class SMSwipeView;

@protocol SMSwipeDelegate <NSObject>

@required
//获取显示数据内容
-(UITableViewCell*)SMSwipeGetView:(SMSwipeView*)swipe withIndex:(int)index;
//获取数据源总量
-(NSInteger)SMSwipeGetTotaleNum:(SMSwipeView*)swipe;
@end

@interface SMSwipeView : UIView

@property(nonatomic,weak)id<SMSwipeDelegate> delegate;

//层叠透明方式显示 默认NO
@property(nonatomic,assign)BOOL isStackCard;
//加载方法
-(void)reloadData;
//根据id获取缓存的cell
-(UITableViewCell*)dequeueReusableUIViewWithIdentifier:(NSString*)identifier;

@end
#import "SMSwipeView.h"

#define degreeTOradians(x) (M_PI * (x)/180)
//childView距离父View左右的距离
const int LEFT_RIGHT_MARGIN=10;
//当前view距离父view的顶部的值
const int TOP_MARGTIN=16;

@interface SMSwipeView()
//已经划动到边界外的一个view
@property(nonatomic,weak)UITableViewCell * viewRemove;
//放当前显示的子View的数组
@property(nonatomic,strong)NSMutableArray * cacheViews;
//view总共的数量
@property(nonatomic,assign)int totalNum;
//当前的下标
@property(nonatomic,assign)int nowIndex;
//触摸开始的坐标
@property(nonatomic,assign)CGPoint pointStart;
//上一次触摸的坐标
@property(nonatomic,assign)CGPoint pointLast;
//最后一次触摸的坐标
@property(nonatomic,assign)CGPoint pointEnd;
//正在显示的cell
@property(nonatomic,weak)UITableViewCell * nowCell;
//下一个cell
@property(nonatomic,weak)UITableViewCell * nextCell;
//第三个cell
@property(nonatomic,weak)UITableViewCell * thirdCell;
//自身的宽度
@property(nonatomic,assign)int w;
//自身的高度
@property(nonatomic,assign)int h;
//是否是第一次执行
@property(nonatomic,assign)BOOL isFirstLayoutSub;

@end

@implementation SMSwipeView

//从xib中加载该类
-(void)awakeFromNib{
 [super awakeFromNib];
 [self initSelf];
}
//直接用方法初始化
-(instancetype)initWithFrame:(CGRect)frame{
 self=[super initWithFrame:frame];
 [self initSelf];
 return self;
}

//进行一些自身的初始化和设置
-(void)initSelf{
 self.clipsToBounds=YES;
 self.cacheViews=[[NSMutableArray alloc]init];
 //手势识别
 UIPanGestureRecognizer * pan=[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
 [self addGestureRecognizer:pan];
}

//布局subview的方法
-(void)layoutSubviews{
 if(!self.isFirstLayoutSub){
 self.isFirstLayoutSub=YES;
 self.w=self.bounds.size.width;
 self.h=self.bounds.size.height;
 [self reloadData];
 }
}

//重新加载数据方法,会再首次执行layoutSubviews的时候调用
-(void)reloadData{
 if (!self.delegate||![self.delegate respondsToSelector:@selector(SMSwipeGetView:withIndex:)]||![self.delegate respondsToSelector:@selector(SMSwipeGetTotaleNum:)]) {
 return;
 }
 self.totalNum=(int)[self.delegate SMSwipeGetTotaleNum:self];
 self.viewRemove=nil;
 UITableViewCell * nowCell=[self.delegate SMSwipeGetView:self withIndex:self.nowIndex];

 UITableViewCell * nextCell=[self.delegate SMSwipeGetView:self withIndex:self.nowIndex 1<self.totalNum?self.nowIndex 1:0];

 UITableViewCell * thirdCell=[self.delegate SMSwipeGetView:self withIndex:self.nowIndex 2<self.totalNum?self.nowIndex 2:self.nowIndex 2-self.totalNum];


 if (self.isStackCard) {
 [thirdCell setAlpha:0.3f];
 [nextCell setAlpha:0.5f];
 [nowCell setAlpha:1];
 }

 [thirdCell removeFromSuperview];
 thirdCell.layer.anchorPoint=CGPointMake(1, 1);
 thirdCell.frame=CGRectMake(LEFT_RIGHT_MARGIN*2, 0, self.w-2*2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
 [self addSubview:thirdCell];
 self.thirdCell=thirdCell;

 [nextCell removeFromSuperview];
 nextCell.layer.anchorPoint=CGPointMake(1, 1);
 nextCell.frame=CGRectMake(LEFT_RIGHT_MARGIN, TOP_MARGTIN/2*1, self.w-2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);

 [self addSubview:nextCell];
 self.nextCell=nextCell;

 [nowCell removeFromSuperview];
 nowCell.layer.anchorPoint=CGPointMake(1, 1);
 nowCell.frame=CGRectMake(0, TOP_MARGTIN, self.w, self.h-TOP_MARGTIN);
 [self addSubview:nowCell];
 self.nowCell=nowCell;


}



#pragma mark swipe触摸的相关手势处理
-(void)swipe:(UISwipeGestureRecognizer*)sender{
 NSLog(@"swipe");
}

-(void)pan:(UIPanGestureRecognizer*)sender{
 CGPoint translation = [sender translationInView: self];
 //CGPoint speed=[sender velocityInView:self];//获取速度
 if (sender.state==UIGestureRecognizerStateBegan) {
 //NSLog(@"begin");
 self.pointStart=translation;
 self.pointLast=translation;
 }

 if (sender.state==UIGestureRecognizerStateChanged) {
 //NSLog(@"change");
 // CGFloat xMove=translation.x-self.pointLast.x;
 // CGFloat yMove=translation.y-self.pointLast.y;
 // self.pointLast=translation;
 //
 // CGPoint center=self.nowCell.center;
 // self.nowCell.center=CGPointMake(center.x xMove, center.y yMove);

 CGFloat xTotalMove=translation.x-self.pointStart.x;
 // if (xTotalMove<0) {
 //  self.nowCell.transform = CGAffineTransformMakeRotation(degreeTOradians(90*xTotalMove/self.w));
 //  self.nextCell.transform= CGAffineTransformMakeRotation(degreeTOradians(90*xTotalMove/self.w/2));
 // }else{
 //  self.nowCell.transform = CGAffineTransformMakeRotation(degreeTOradians(0));
 //  self.nextCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
 // }

 }

 if (sender.state==UIGestureRecognizerStateEnded) {
 //NSLog(@"end");
 CGFloat xTotalMove=translation.x-self.pointStart.x;
 if (xTotalMove<0) {
  [self swipeEnd];
 }else{
  [self swipeGoBack];
 }

 }
 // NSLog(@"%@%f%@%f",@"x:",speed.x,@"y:",speed.y);
 //NSLog(@"%@%f%@%f",@"x:",translation.x,@"y:",translation.y);
}

/**
 * @author StoneMover, 16-12-29 14:12:33
 *
 * @brief 获取为显示的cell,复用机制
 *
 * @param identifier id标志
 *
 * @return 返回的cell,如果缓存中没有则返回空
 */
-(UITableViewCell*)dequeueReusableUIViewWithIdentifier:(NSString *)identifier{

 for (UITableViewCell * cell in self.cacheViews) {
 if ([identifier isEqualToString:cell.reuseIdentifier]) {
  [self.cacheViews removeObject:cell];
  return cell;
 }
 }

 return nil;
}

//滑动到下一个界面
-(void)swipeEnd{
 [UIView animateWithDuration:0.3 animations:^{
 self.nextCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
 }];

 //self.nowCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
 CGPoint center=self.nowCell.center;
 [UIView animateWithDuration:0.3 animations:^{
 self.nowCell.center=CGPointMake(center.x-self.w, center.y);
 self.nowCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
 // [self.nowCell setAlpha:0.0];
 } completion:^(BOOL finished) {
 self.nowIndex  ;
 self.nowIndex=self.nowIndex<self.totalNum?self.nowIndex:0;
 if (self.viewRemove&&[self isNeedAddToCache:self.viewRemove]) {
  [self.cacheViews addObject:self.viewRemove];
  [self.viewRemove removeFromSuperview];
 }
 self.viewRemove=self.nowCell;
 //self.viewRemove.layer.anchorPoint=CGPointMake(0, 0);
 //self.viewRemove.transform=CGAffineTransformMakeRotation(degreeTOradians(-35));


 self.nowCell=self.nextCell;
 self.nextCell=self.thirdCell;


 UITableViewCell * thirdCell=[self.delegate SMSwipeGetView:self withIndex:self.nowIndex 2<self.totalNum?(int)self.nowIndex 2:(int)self.nowIndex 2-(int)self.totalNum];

 [thirdCell removeFromSuperview];

 thirdCell.layer.anchorPoint=CGPointMake(1, 1);
 thirdCell.frame=CGRectMake(LEFT_RIGHT_MARGIN*2, 0, self.w-2*2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
 self.thirdCell=thirdCell;


 if (self.isStackCard) {
  [self.thirdCell setAlpha:0.3f];
  [self.nextCell setAlpha:0.5f];
  [self.nowCell setAlpha:1];
 }

 [self insertSubview:thirdCell belowSubview:self.nextCell];

 [UIView animateWithDuration:0.2 animations:^{
  self.nowCell.frame=CGRectMake(0, TOP_MARGTIN, self.w, self.h-TOP_MARGTIN);
  self.nextCell.frame=CGRectMake(LEFT_RIGHT_MARGIN, TOP_MARGTIN/2*1, self.w-2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
 }];
 }];
}

//滑动到上一个界面
-(void)swipeGoBack{

 if (!self.viewRemove) {
 NSLog(@"!viewRemove");
 return;
 }

 if (self.nowIndex==0) {
 NSLog(@"!viewRemove index");
 return;
 }

 CGPoint center=self.viewRemove.center;

 self.nowIndex--;

 // if ([self isNeedAddToCache:self.thirdCell]) {
 // [self.cacheViews addObject:self.thirdCell];
 // }
 [self.thirdCell removeFromSuperview];


 self.thirdCell=self.nextCell;
 self.nextCell=self.nowCell;
 self.nowCell=self.viewRemove;

 if (self.nowIndex==0) {
 self.viewRemove=nil;

 }else{
 UITableViewCell * cell=[self.delegate SMSwipeGetView:self withIndex:(int)self.nowIndex-1];
 [cell removeFromSuperview];
 [self insertSubview:cell aboveSubview:self.nowCell];
 cell.layer.anchorPoint=CGPointMake(1, 1);
 cell.frame=self.viewRemove.frame;
 self.viewRemove=cell;
 }

 [UIView animateWithDuration:.5 animations:^{
 self.nowCell.center=CGPointMake(center.x self.w, center.y);
 self.nowCell.transform= CGAffineTransformMakeRotation(degreeTOradians(0));
 self.nextCell.frame=CGRectMake(LEFT_RIGHT_MARGIN, TOP_MARGTIN/2*1, self.w-2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
 self.thirdCell.frame=CGRectMake(LEFT_RIGHT_MARGIN*2, 0, self.w-2*2*LEFT_RIGHT_MARGIN, self.h-TOP_MARGTIN);
 }];
}

//是否需要加入到缓存中去
-(BOOL)isNeedAddToCache:(UITableViewCell*)cell{
 for (UITableViewCell * cellIn in self.cacheViews) {
 if ([cellIn.reuseIdentifier isEqualToString:cell.reuseIdentifier]) {

  return NO;
 }
 }
 return YES;
}

@end

源码下载 点击查看

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持Devmax。

iOS自定义View实现卡片滑动的更多相关文章

  1. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  2. iOS实现拖拽View跟随手指浮动效果

    这篇文章主要为大家详细介绍了iOS实现拖拽View跟随手指浮动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  4. ios – Testflight无法安装应用程序

    我有几个测试人员注册了testflight并连接了他们的设备……他们有不同的ios型号……但是所有这些都有同样的问题.当他们从“safari”或“testflight”应用程序本身单击应用程序的安装按钮时……达到约90%并出现错误消息…

  5. ibm-mobilefirst – 在iOS 7.1上获取“无法安装应用程序,因为证书无效”错误

    当我的客户端将他们的设备更新到iOS7.1,然后尝试从AppCenter更新我们的应用程序时,我收到了上述错误.经过一番搜索,我找到了一个类似问题的帖子here.但是后来因为我在客户端使用AppCenter更新应用程序的环境中,我无法使用USB插件并为他们安装应用程序.在发布支持之前,是否有通过AppCenter进行下载的解决方法?

  6. ios – 视图的简单拖放?

    我正在学习iOS,但我找不到如何向UIView添加拖放行为.我试过了:它说“UIView没有可见的接口声明选择器addTarget”此外,我尝试添加平移手势识别器,但不确定这是否是我需要的它被称为,但不知道如何获得事件的坐标.在iOS中注册移动事件回调/拖放操作的标准简单方法是什么?

  7. ios – 什么控制iTunes中iPhone应用程序支持的语言列表?

    什么控制iPhone应用程序的iTunes页面中支持的语言?

  8. ios – 获得APNs响应BadDeviceToken或Unregistered的可能原因是什么?

    我知道设备令牌在某些时候是有效的.用户如何使其设备令牌变坏?从关于“未注册”的文档:Thedevicetokenisinactiveforthespecifiedtopic.这是否意味着应用程序已被删除?.您应该看到四种分发方法:如果您选择AppStore或Enterprise,您将在后面的对话框中看到Xcode将APNS权利更改为生产:如果选择AdHoc或Development,则aps-environment下的文本将是开发,然后应与后端的配置匹配.

  9. ios – 当我关闭应用程序时,我从调试器获得消息:由于信号15而终止

    我怎么能解决这个问题,我不知道这个链接MypreviousproblemaboutCoredata对我的问题有影响吗?当我cmd应用程序的Q时,将出现此消息.Messagefromdebugger:Terminatedduetosignal15如果谁知道我以前的问题的解决方案,请告诉我.解决方法>来自调试器的消息:每当用户通过CMD-Q(退出)或STOP手动终止应用程序(无论是在iOS模拟器中还是

  10. ios – NSUbiquityIdentityDidChangeNotification和SIGKILL

    当应用程序被发送到后台时,我们会删除观察者吗?我遇到的问题是,当UbiquityToken发生变化时,应用程序终止,因为用户已经更改了iCloud设置.你们如何设法订阅这个通知,如果你不这样做,你会做什么来跟踪当前登录的iCloud用户?

随机推荐

  1. iOS实现拖拽View跟随手指浮动效果

    这篇文章主要为大家详细介绍了iOS实现拖拽View跟随手指浮动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. iOS – genstrings:无法连接到输出目录en.lproj

    使用我桌面上的项目文件夹,我启动终端输入:cd然后将我的项目文件夹拖到终端,它给了我路径.然后我将这行代码粘贴到终端中找.-name*.m|xargsgenstrings-oen.lproj我在终端中收到此错误消息:genstrings:无法连接到输出目录en.lproj它多次打印这行,然后说我的项目是一个目录的路径?没有.strings文件.对我做错了什么的想法?

  3. iOS 7 UIButtonBarItem图像没有色调

    如何确保按钮图标采用全局色调?解决方法只是想将其转换为根注释,以便为“回答”复选标记提供更好的上下文,并提供更好的格式.我能想出这个!

  4. ios – 在自定义相机层的AVFoundation中自动对焦和自动曝光

    为AVFoundation定制图层相机创建精确的自动对焦和曝光的最佳方法是什么?

  5. ios – Xcode找不到Alamofire,错误:没有这样的模块’Alamofire’

    我正在尝试按照github(https://github.com/Alamofire/Alamofire#cocoapods)指令将Alamofire包含在我的Swift项目中.我创建了一个新项目,导航到项目目录并运行此命令sudogeminstallcocoapods.然后我面临以下错误:搜索后我设法通过运行此命令安装cocoapodssudogeminstall-n/usr/local/bin

  6. ios – 在没有iPhone6s或更新的情况下测试ARKit

    我在决定下载Xcode9之前.我想玩新的框架–ARKit.我知道要用ARKit运行app我需要一个带有A9芯片或更新版本的设备.不幸的是我有一个较旧的.我的问题是已经下载了新Xcode的人.在我的情况下有可能运行ARKit应用程序吗?那个或其他任何模拟器?任何想法或我将不得不购买新设备?解决方法任何iOS11设备都可以使用ARKit,但是具有高质量AR体验的全球跟踪功能需要使用A9或更高版本处理器的设备.使用iOS11测试版更新您的设备是必要的.

  7. 将iOS应用移植到Android

    我们制作了一个具有2000个目标c类的退出大型iOS应用程序.我想知道有一个最佳实践指南将其移植到Android?此外,由于我们的应用程序大量使用UINavigation和UIView控制器,我想知道在Android上有类似的模型和实现.谢谢到目前为止,guenter解决方法老实说,我认为你正在计划的只是制作难以维护的糟糕代码.我意识到这听起来像很多工作,但从长远来看它会更容易,我只是将应用程序的概念“移植”到android并从头开始编写.

  8. ios – 在Swift中覆盖Objective C类方法

    我是Swift的初学者,我正在尝试在Swift项目中使用JSONModel.我想从JSONModel覆盖方法keyMapper,但我没有找到如何覆盖模型类中的Objective-C类方法.该方法的签名是:我怎样才能做到这一点?解决方法您可以像覆盖实例方法一样执行此操作,但使用class关键字除外:

  9. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

  10. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

返回
顶部