iOS 探探首頁(yè)的卡片切換效果

效果圖:

tantan.gif

最近公司要求寫一個(gè)類似于探探的項(xiàng)目诀姚,在網(wǎng)上找了半天也沒有找到合適的dome,所以就自己寫了一個(gè)dome玷禽,希望能夠幫到大家

步驟:
1.實(shí)現(xiàn)左右滑動(dòng)
2.實(shí)現(xiàn)刪除或者還原
3.實(shí)現(xiàn)左右旋轉(zhuǎn)
4.實(shí)現(xiàn)卡片的替換
5.實(shí)現(xiàn)實(shí)現(xiàn)卡片的跟隨

首先自定義view實(shí)現(xiàn)1赫段、2呀打、3功能

這里用到了UIView的類別的方法

//UIView類別里的方法
-(void)addPanAction:(SEL)action{
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:action];
    [self addGestureRecognizer:pan];
}

自定義UIView

moreView.h

@protocol moreViewdelegate <NSObject>

//移動(dòng)的距離
-(void)moreVolue:(CGFloat)volue;
//視圖是否被移除
-(void)moreisRemove:(BOOL)isRemove;

@optional

@end

@interface moreView : UIView{
    CGPoint point;//保存點(diǎn)擊初始位置
    CGRect rect;//保存視圖初始位置
}

//喜歡
@property (nonatomic, weak) UILabel * xh;
//不喜歡
@property (nonatomic, weak) UILabel * bxh;
//協(xié)議
@property(weak ,nonatomic)id<moreViewdelegate>delegates;

兩個(gè)協(xié)議方法是后面實(shí)現(xiàn)4、5需要用到的方法
兩個(gè)UIlabel是在視圖上面的子控件(看需求添加)
point成員變量是保存初始點(diǎn)擊的位置(用于實(shí)現(xiàn)讓圖片跟隨手指滑動(dòng))
rect成員變量是保存視圖的初始位置(用于還原到原來的位置)

華麗的分割線==================================

moreView.m

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
//        self.backgroundColor = [UIColor whiteColor];
        
        //布局UI
        [self LayoutUI];
        
        
        //添加拖動(dòng)按鈕
        self.userInteractionEnabled = NO;

        //這里是一個(gè)UIView的類別添加滑動(dòng)的方法
        [self addPanAction:@selector(panAction:)];
    }
    return self;
}

-(void)panAction:(UIPanGestureRecognizer *)pan{
    UIView * view = (UIView *)pan.view;
    
    if (pan.state == UIGestureRecognizerStateBegan) {
        
        //存儲(chǔ)準(zhǔn)備開始滑動(dòng)的坐標(biāo)
        
        point = [pan locationInView: [view superview] ];
        
        rect = view.frame;
        
        
    }else if (pan.state == UIGestureRecognizerStateChanged){
        //監(jiān)聽滑動(dòng)的距離并改變view的位置
        
        CGRect rects = rect;
        
        CGFloat x = [pan locationInView:[view superview]].x - point.x;
        
        CGFloat y = [pan locationInView:[view superview]].y - point.y;
        
        rects.origin = CGPointMake(rect.origin.x + x, rect.origin.y + y);
        
        view.frame = rects;
        
        //判斷是否劃出制定區(qū)域
        
        if (view.center.x > YBJ_ScreenW || view.center.x < 0 || view.center.y > YBJ_ScreenH || view.center.y < 0){
            if (view.center.x > YBJ_ScreenW) {
                self.xh.alpha = 1;
            }
            if (view.center.x < 0) {
                self.bxh.alpha = 1;
            }
            return;
        }
        
        //監(jiān)聽滑動(dòng)的比例控制動(dòng)畫以及喜歡
        
        CGFloat xx = (view.center.x-(view.width/2))/(view.width/2);
        
        if (xx<0) {
            self.bxh.alpha = fabs(xx);
        }else{
            self.xh.alpha = fabs(xx);
        }
        
        [self viewAnimationfloat:(xx * 0.05)];
        
        [self.delegates moreVolue:xx];
        
        
    }else if (pan.state == UIGestureRecognizerStateEnded || pan.state == UIGestureRecognizerStateFailed){
        
        
        //判斷是松手時(shí)是否劃出制定區(qū)域
        if (view.center.x > YBJ_ScreenW || view.center.x < 0 || view.center.y > YBJ_ScreenH || view.center.y < 0) {
            [self removeFromSuperview];
            [self.delegates moreisRemove:YES];
        }else{
            
            [self.delegates moreisRemove:NO];
            [UIView animateWithDuration:0.2 animations:^{
                self.xh.alpha = 0;
                self.bxh.alpha = 0;
                view.frame = self->rect;
                [self viewAnimationfloat:0];
            }];
        }
    }
}

//CABasicAnimation動(dòng)畫
-(void)viewAnimationfloat:(CGFloat)f{
    
    //根據(jù)z軸旋轉(zhuǎn)
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    animation.toValue = [NSNumber numberWithFloat: M_PI * f];
    animation.duration = 0.2f;
    animation.autoreverses = NO;
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    animation.repeatCount = 0;
    [self.layer addAnimation:animation forKey:nil];
    
}

1糯笙、LayoutUI這個(gè)方法是用于UI布局子控件用的聚磺。
2、因?yàn)橹荒芤苿?dòng)一張視圖所以我們先將view的用戶交互關(guān)掉炬丸。
3、在panAction:方法中先獲取到自身(用于對(duì)自身做相應(yīng)的處理)蜒蕾。
4稠炬、state剛點(diǎn)擊下來我們就存儲(chǔ)point 和 rect。
5咪啡、state開始滑動(dòng)時(shí)需要通過point實(shí)現(xiàn)圖片跟隨首启。
6、設(shè)置指定范圍用于控制喜歡和不喜歡控件(如果超出范圍就return)撤摸。
7毅桃、沒有超出范圍就通過滑動(dòng)的比例控制喜歡喝不喜歡的透明度
8、并且讓view有左右旋轉(zhuǎn)的功能准夷。
9钥飞、viewAnimationfloat:這個(gè)方法是通過比例決定旋轉(zhuǎn)的角度。
10衫嵌、并且通過moreVolue:這個(gè)協(xié)議方法傳遞移動(dòng)的比例(用于5的處理)读宙。
11、state松手時(shí)可通過制定的區(qū)域來決定還原還是刪除楔绞。
12结闸、當(dāng)滑動(dòng)區(qū)域超過制定范圍就刪除該視圖(這里可以添加一個(gè)往左移動(dòng)的動(dòng)畫)。
13酒朵、并且通過moreisRemove:這個(gè)協(xié)議方法傳遞是否劃出制定范圍(用于4的處理)桦锄。
14、沒有超過就還原到初始狀態(tài)蔫耽。
15结耀、并且通過moreisRemove:這個(gè)協(xié)議方法傳遞是否劃出制定范圍(用于4的處理)。

華麗的分割線==============================

調(diào)用moreView實(shí)現(xiàn)4匙铡、5功能

Frame(x,y,width,height)這個(gè)宏是本人用于適配的(請(qǐng)自行改為自己的CGRectMake)

moreView調(diào)用

moreViewController.m

#import "moreViewController.h"

#import "moreView.h"

#define baseFrame Frame(38,Height_NavBar + YBJ_ScreenW6(25),300,425)

#define Frame1 Frame(0,0,300,400)

#define Frame2 Frame(3,8,300-6,400)

#define Frame3 Frame(6,16,300-12,400)

#define Frame4 Frame(9,24,300-18,400)


@interface moreViewController ()<moreViewdelegate>
//背景視圖
@property (weak , nonatomic)UIView * baseView;
//數(shù)據(jù)數(shù)組
@property (strong ,nonatomic)NSMutableArray * dataArr;
//more數(shù)組(視圖)
@property (strong ,nonatomic)NSMutableArray * moreArr;
//位置數(shù)組(ps:因?yàn)槲恢貌荒艽娴綌?shù)組需要轉(zhuǎn)換饼记,就沒有用到)
@property (strong ,nonatomic)NSMutableArray * FrameArr;

@end

@implementation moreViewController

-(NSMutableArray *)dataArr{
    if (!_dataArr) {
        _dataArr = [NSMutableArray new];
        [_dataArr addObject:[UIColor redColor]];
        [_dataArr addObject:[UIColor orangeColor]];
        [_dataArr addObject:[UIColor grayColor]];
        [_dataArr addObject:[UIColor brownColor]];
        [_dataArr addObject:[UIColor greenColor]];
        [_dataArr addObject:[UIColor purpleColor]];
        [_dataArr addObject:[UIColor redColor]];
        [_dataArr addObject:[UIColor orangeColor]];
        [_dataArr addObject:[UIColor grayColor]];
        [_dataArr addObject:[UIColor brownColor]];
        [_dataArr addObject:[UIColor greenColor]];
        [_dataArr addObject:[UIColor purpleColor]];
    }
    return _dataArr;
}

-(NSMutableArray *)moreArr{
    if (!_moreArr) {
        _moreArr = [NSMutableArray new];
    }
    return _moreArr;
}

-(NSMutableArray *)FrameArr{
    if (!_FrameArr) {
        _FrameArr = [NSMutableArray new];
        
    }
    return _FrameArr;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    //創(chuàng)建父視圖
    
    [self setBaseView];
//    [self addChildView];
}

/**
 創(chuàng)建父視圖
 */

-(void)setBaseView{
    
    UIView * baseView = [[UIView alloc]initWithFrame:baseFrame];
    [self.view addSubview:baseView];
    baseView.backgroundColor = [UIColor whiteColor];
    _baseView = baseView;
    
    for (int i = 0; i < 5 ; i++) {
        
        [self addChildView:i];
    }
}

/**
 添加子試圖
 */

-(void)addChildView:(NSInteger)i{
    
    if (self.dataArr.count == 0) {
        return;
    }
    
    moreView * more = [[moreView alloc]initWithFrame:CGRectMake(0+YBJ_ScreenW6(3*i), 0+8*i, YBJ_ScreenW6(300-(6*i)), YBJ_ScreenW6(400))];
    
    more.backgroundColor = self.dataArr[0];
    
    if (i == 0) {
        more.userInteractionEnabled = YES;
    }
    
    more.tag = i+10;
    
    switch (i) {
        case 0:
            more.frame = Frame1;
            break;
        case 1:
            more.frame = Frame2;
            break;
        case 2:
            more.frame = Frame3;
            break;
        case 3:
            more.frame = Frame4;
            break;
            
        default:
            more.frame = Frame4;
            break;
    }
    
    
    more.delegates = self;
    
    [self.baseView addSubview:more];
    
    [self.baseView sendSubviewToBack:more];
    
    [self.moreArr addObject:more];
    
    [self.dataArr removeObjectAtIndex:0];
    
}
/**
 moredelegates代理
 */
-(void)moreVolue:(CGFloat)volue{
    
    NSLog(@"%f",volue);
    
    for (UIView * tepView in self.moreArr) {
        
        moreView * more = (moreView *)tepView;
        
        CGRect rect = CGRectZero;
        
        switch (more.tag-10) {
            case 0:
                
                break;
            case 1:
                rect = Frame2;
                rect.origin.x -= YBJ_ScreenW6(3*fabs(volue));
                rect.origin.y -= YBJ_ScreenW6(8*fabs(volue));
                rect.size.width += YBJ_ScreenW6(6*fabs(volue));
                more.frame = rect;
                break;
            case 2:
                rect = Frame3;
                rect.origin.x -= YBJ_ScreenW6(3*fabs(volue));
                rect.origin.y -= YBJ_ScreenW6(8*fabs(volue));
                rect.size.width += YBJ_ScreenW6(6*fabs(volue));
                more.frame = rect;
                break;
            case 3:
                rect = Frame4;
                rect.origin.x -= YBJ_ScreenW6(3*fabs(volue));
                rect.origin.y -= YBJ_ScreenW6(8*fabs(volue));
                rect.size.width += YBJ_ScreenW6(6*fabs(volue));
                more.frame = rect;
                break;
                
            default:
                
                break;
        }
        
        
        
    }
    
}

-(void)moreisRemove:(BOOL)isRemove{
    if (isRemove) {
        
        [self.moreArr removeObjectAtIndex:0];
        
        
        if (self.moreArr.count == 0) {
            NSLog(@"沒有了!");
        }
        
        for (UIView * tepView in self.moreArr) {
            
            moreView * more = (moreView *)tepView;
        
            more.tag -= 1;
            
            if (more.tag-10 == 0) {
                more.userInteractionEnabled = YES;
            }
            
        }
        [self addChildView:4];
        
    }else{
        for (UIView * tepView in self.moreArr) {
            
            moreView * more = (moreView *)tepView;
            
            switch (more.tag - 10) {
                case 0:
                    
                    break;
                case 1:
                    more.frame = Frame2;
                    break;
                case 2:
                    more.frame = Frame3;
                    break;
                case 3:
                    more.frame = Frame4;
                    break;
                    
                default:
                    break;
            }
        }
    }
}

1慰枕、上面一些宏定義分別為:背景具则、第一個(gè)、第二個(gè)具帮、第三個(gè)博肋、第四個(gè)~視圖的位置(請(qǐng)自行更改)低斋。
2、上面一些屬性分別為:背景視圖匪凡、數(shù)據(jù)數(shù)組(這里添加了幾條顏色數(shù)據(jù))膊畴、more數(shù)組(視圖)、位置數(shù)組(ps:因?yàn)槲恢貌荒艽娴綌?shù)組需要轉(zhuǎn)換病游,就沒有用到)唇跨。
3、setBaseView是創(chuàng)建父視圖(用于做moreView的容器衬衬,設(shè)置屬性是劃完后能夠remove买猖,并且重新加載視圖)。
4滋尉、利用for循環(huán)來創(chuàng)建moreView(這里用了5個(gè)玉控,因?yàn)橛兴膫€(gè)view的位置,所以留最后留一張墊底)狮惜。
5高诺、addChildView:這個(gè)方法是利用傳遞的i來設(shè)定tag值,并且設(shè)置位置碾篡,用moreArr存儲(chǔ)moreView虱而,sendSubviewToBack:這個(gè)方法將新添加的moreView放到最下面,然后刪除dataArr中的第一個(gè)數(shù)據(jù)(當(dāng)dataArr為空的時(shí)候就return)开泽。
6薛窥、moreViewdelegate簽訂協(xié)議(分別為:moreisRemove: 和 moreVolue: )。
7眼姐、moreVolue: 通過這個(gè)協(xié)議方法實(shí)現(xiàn)5的效果诅迷,便利moreArr取出moreView,改變其frame實(shí)現(xiàn)跟隨效果众旗。
8罢杉、moreisRemove: 通過這個(gè)協(xié)議4的效果。
isRemove為真:
moreArr刪除第一個(gè)元素贡歧,便利moreArr取出moreView滩租,改變其tag,讓tag值-1利朵,并且把第一個(gè)view改為可交互狀態(tài)律想,再用addChildView:這個(gè)方法在底部添加一個(gè)moreView(當(dāng)moreArr為空時(shí)就可以刪除背景視圖執(zhí)行下一環(huán)節(jié)了)
isRemove為假:
便利moreArr取出moreView通過tag將其還原。

end

ps:因?yàn)閙oreView在滑動(dòng)的后有還原操作绍弟,所以不需要還原技即。

喜歡的小伙伴們可以點(diǎn)個(gè)??加個(gè)關(guān)注!U燎病而叼!

有問題的小伙伴私信我身笤!GitHub/YBJTantan

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市葵陵,隨后出現(xiàn)的幾起案子液荸,更是在濱河造成了極大的恐慌,老刑警劉巖脱篙,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娇钱,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡绊困,警方通過查閱死者的電腦和手機(jī)文搂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來考抄,“玉大人,你說我怎么就攤上這事蔗彤〈罚” “怎么了?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵然遏,是天一觀的道長(zhǎng)贫途。 經(jīng)常有香客問我,道長(zhǎng)待侵,這世上最難降的妖魔是什么丢早? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮秧倾,結(jié)果婚禮上怨酝,老公的妹妹穿的比我還像新娘。我一直安慰自己那先,他們只是感情好农猬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著售淡,像睡著了一般斤葱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上揖闸,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天揍堕,我揣著相機(jī)與錄音,去河邊找鬼汤纸。 笑死衩茸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的贮泞。 我是一名探鬼主播递瑰,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼祟牲,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了抖部?” 一聲冷哼從身側(cè)響起说贝,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎慎颗,沒想到半個(gè)月后乡恕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡俯萎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年傲宜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夫啊。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡函卒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出撇眯,到底是詐尸還是另有隱情报嵌,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布熊榛,位于F島的核電站锚国,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏玄坦。R本人自食惡果不足惜血筑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望煎楣。 院中可真熱鬧豺总,春花似錦、人聲如沸择懂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)休蟹。三九已至沸枯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赂弓,已是汗流浹背绑榴。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留盈魁,地道東北人翔怎。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親赤套。 傳聞我的和親對(duì)象是個(gè)殘疾皇子飘痛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1、通過CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_X自主閱讀 15,982評(píng)論 3 119
  • 026自我陶醉式的吹噓是沒有聽眾的 老是自我陶醉式的吹噓容握、曬幸福宣脉。在優(yōu)秀的人眼里,這只等于"淺薄"剔氏,身邊的人只會(huì)對(duì)...
    Muscle_4329閱讀 252評(píng)論 0 0
  • 雅思寫作怎樣體現(xiàn)邏輯性塑猖?聽力最好的鍛煉方式是什么?閱讀怎么做谈跛?說的部分怎么說羊苟? ?呈現(xiàn)邏輯性的寫作 通過段與段之間...
    東日晨閱讀 209評(píng)論 0 0
  • 今天順利考完了英語(yǔ)A級(jí),心情有一種釋放的小感覺感憾,不過頭等戲還在前方蜡励,因?yàn)橄轮艿挠?jì)算機(jī)二級(jí)、普通話也很快奔駕而來阻桅。 ...
    慢就是快的追夢(mèng)女孩閱讀 508評(píng)論 3 3