溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

iOS自定義View如何實(shí)現(xiàn)卡片滑動(dòng)

發(fā)布時(shí)間:2021-05-24 11:22:31 來源:億速云 閱讀:164 作者:小新 欄目:移動(dòng)開發(fā)

這篇文章給大家分享的是有關(guān)iOS自定義View如何實(shí)現(xiàn)卡片滑動(dòng)的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

說明

控件基于UIView封裝完成,采用UIPanGestureRecognizer監(jiān)聽自身的觸摸事件,以此處理各種滑動(dòng)動(dòng)畫操作。
內(nèi)容之間可以循環(huán)切換,采用類似tableView加載機(jī)制,達(dá)到復(fù)用效果

效果

iOS自定義View如何實(shí)現(xiàn)卡片滑動(dòng)

代碼實(shí)現(xiàn)

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

@protocol SMSwipeDelegate <NSObject>

@required
//獲取顯示數(shù)據(jù)內(nèi)容
-(UITableViewCell*)SMSwipeGetView:(SMSwipeView*)swipe withIndex:(int)index;
//獲取數(shù)據(jù)源總量
-(NSInteger)SMSwipeGetTotaleNum:(SMSwipeView*)swipe;
@end

@interface SMSwipeView : UIView

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

//層疊透明方式顯示 默認(rèn)NO
@property(nonatomic,assign)BOOL isStackCard;
//加載方法
-(void)reloadData;
//根據(jù)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;
//當(dāng)前view距離父view的頂部的值
const int TOP_MARGTIN=16;

@interface SMSwipeView()
//已經(jīng)劃動(dòng)到邊界外的一個(gè)view
@property(nonatomic,weak)UITableViewCell * viewRemove;
//放當(dāng)前顯示的子View的數(shù)組
@property(nonatomic,strong)NSMutableArray * cacheViews;
//view總共的數(shù)量
@property(nonatomic,assign)int totalNum;
//當(dāng)前的下標(biāo)
@property(nonatomic,assign)int nowIndex;
//觸摸開始的坐標(biāo)
@property(nonatomic,assign)CGPoint pointStart;
//上一次觸摸的坐標(biāo)
@property(nonatomic,assign)CGPoint pointLast;
//最后一次觸摸的坐標(biāo)
@property(nonatomic,assign)CGPoint pointEnd;
//正在顯示的cell
@property(nonatomic,weak)UITableViewCell * nowCell;
//下一個(gè)cell
@property(nonatomic,weak)UITableViewCell * nextCell;
//第三個(gè)cell
@property(nonatomic,weak)UITableViewCell * thirdCell;
//自身的寬度
@property(nonatomic,assign)int w;
//自身的高度
@property(nonatomic,assign)int h;
//是否是第一次執(zhí)行
@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;
}

//進(jìn)行一些自身的初始化和設(shè)置
-(void)initSelf{
 self.clipsToBounds=YES;
 self.cacheViews=[[NSMutableArray alloc]init];
 //手勢(shì)識(shí)別
 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];
 }
}

//重新加載數(shù)據(jù)方法,會(huì)再首次執(zhí)行l(wèi)ayoutSubviews的時(shí)候調(diào)用
-(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觸摸的相關(guān)手勢(shì)處理
-(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,復(fù)用機(jī)制
 *
 * @param identifier id標(biāo)志
 *
 * @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;
}

//滑動(dòng)到下一個(gè)界面
-(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);
 }];
 }];
}

//滑動(dòng)到上一個(gè)界面
-(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

感謝各位的閱讀!關(guān)于“iOS自定義View如何實(shí)現(xiàn)卡片滑動(dòng)”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI