欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

iOS自定义View实现卡片滑动

程序员文章站 2022-06-30 10:11:56
本文实例为大家分享了ios自定义view实现卡片滑动效果的具体代码,供大家参考,具体内容如下说明控件基于uiview封装完成,采用uipangesturerecognizer监听自身的触摸事件,以此处...

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

说明

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

效果

iOS自定义View实现卡片滑动

代码实现

#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

源码下载 点击查看

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

相关标签: iOS view 滑动