2019独角兽企业重金招聘Python工程师标准>>>

说明

控件基于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

源码下载 点击查看

更多文章 点击查看

转载于:https://my.oschina.net/u/2447911/blog/1606124

ios 卡片切换效果相关推荐

  1. Swift 版本很好的卡片切换效果基于ZLSwipeableView(类似于[陌陌点点][探探])

    这是我在简书的文章. http://www.jianshu.com/p/734962c9bbed

  2. 用vue写卡片切换效果

    <template><div><div class="app"><div id="tabs"><div&g ...

  3. SwiftUI iOS 开源组件之银行卡切换效果 (教程含源码)

    实战需求 SwiftUI iOS 开源组件之银行卡切换效果 本文价值与收获 看完本文后,您将能够作出下面的界面 看完本文您将掌握的技能 计算组件大小 GeometryReader { geometry ...

  4. Android卡片滑动切换动画,Android原生ViewPager控件实现卡片翻动效果

    本文实例为大家分享了Android控件ViewPager实现卡片翻动效果的具体代码,供大家参考,具体内容如下 先放一张效果图: 想要实现这样的效果其实并不是太难,需要对ViewPager的一些细节属性 ...

  5. jQuery实现图片卡片层叠式切换效果

    本功能的开发,主要看到一个网站有这个功能,但是是flash做的,当时就吐血了,于是就自己研究用jquery来做一下,功能比较简单,没用进行美化,代码没有经过优化的,如果哪位高手可以优化修改下也不错!好 ...

  6. UIVIewController自定义切换效果-b

    之前介绍动画时提过UIView的转场动画,但是开发中我们碰到更多的viewController的切换,ios中常见的viewcontroller切换有四种:模态视图,导航栏控制器,UITabBarCo ...

  7. html大风效果,使用jquery.windy制作风吹卡片的效果 | jQuery教程

    通过使用Windy和CSS 3D transforms.transitions,你能够做出一种卡片被风吹飞的图片切换效果. 有一些可用参数可以使你定义风吹的范围.速度(CSS transitions) ...

  8. 动画特效十五:网易新闻之头部导航切换效果

    本人录制技术视频地址:https://edu.csdn.net/lecturer/1899 欢迎观看. 这一节继续和大家探讨iOS中的动画效果,由于网易新闻中的动画效果比较多,所以我分两个章节进行介绍 ...

  9. 3种风吹图片jquery堆叠图片切换效果插件

    dreamweaver免费视频教程: http://www.51rgb.com/mproductzh.aspx?classid=31 加讨论群390180913 入群即可参加周一至周五免费公开课并获得 ...

  10. vue实现卡片滚动效果

    vue实现卡片滚动左右切换效果 HTML: //最外层盒子 <div class="box_1">//内层盒子<div class="box_2&quo ...

最新文章

  1. 老大批评我不要为了“分库分表”而“分库分表”
  2. 2017202110104-高级软件工程2017第8次作业—个人总结
  3. Docker的windows家庭版安装
  4. android 遍历所有view,Android 算法:遍历ViewGroup找出所有子View
  5. 4怎么放大字体_win8.1系统如何放大所有字体?
  6. 织梦(安装,模板,基本标签)
  7. mysql修改binlog 位置_查看mysql 的binlog日志存放的位置(转)
  8. 牛客网暑期ACM多校训练营(第三场): E. Sort String(KMP)
  9. bat 启动 不弹出对话框_跳过网易启动器用Steam启动逆水寒
  10. 用C语言写的爬虫项目
  11. ipython安装问题_iPython的安装及问题解决
  12. Java学习路线-1:编程入门
  13. pyqt5-事件机制
  14. web服务器的选择 讨论
  15. BeanCopier对象复制学习
  16. 红米note2位置服务器,红米Note2
  17. Java实例15 - 求最大公约数 gcd 辗转相除 欧几里德算法
  18. 2021-Twins: Revisiting the Design of Spatial Attention
  19. RK3399平台开发系列讲解(SPI子系统)4.16、SPI子系统之spidev驱动分析
  20. excel数据汇总工具怎么使用?

热门文章

  1. 这样的书 我改怎么起名呢?
  2. 《我也能做CTO之程序员职业规划》之七:大学生职业规划技巧
  3. 什么是次梯度(次导数)
  4. vmware屏幕不能适应窗口
  5. 力扣-973. 最接近原点的 K 个点
  6. Harmony OS — ProgressBar垂直、水平进度条
  7. 7-6 逆序的三位数 (10 分)
  8. L1-038 新世界 (5 分)—团体程序设计天梯赛
  9. JavaScript从入门到放弃之补充篇
  10. ES6小实验-复习字符串