效果圖:
最近公司要求寫一個(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)的后有還原操作绍弟,所以不需要還原技即。