仿抖音評論手勢拖拽 iOS


 

 

 

通過觀察可以發現抖音的評論視圖是從底部彈出的,包括頂部視圖和UITableView視圖,

1.經過分析可以知道評論視圖最底部是一個透明的UIView,並且添加了手勢UIPanGestureRecognizer。

2.當UITableView滑動到最頂部時,下拉白色背景視圖可以滑動消失

3.當UITableView滑動時,白色背景視圖不滑動

4.當手指點擊或者拖動上面的空白區域或關閉按鈕,視圖消失

下面來說說具體的實現:

 

1.初始化視圖並添加手勢,需要遵循代理 UIGestureRecognizerDelegate

@property (nonatomic, strong) UIView *bgView;//白色背景視圖

 

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.initOriginY = 100;
        self.needReplaceY = 120;
        self.backgroundColor = [UIColor clearColor];
        
        self.bgView = [[UIView alloc] initWithFrame:CGRectMake(0, self.initOriginY, UIScreenWidth, UIScreenHeight - self.initOriginY)];
        self.bgView.backgroundColor = [UIColor whiteColor];
        [self.bgView setCorner:UIRectCornerTopLeft | UIRectCornerTopRight cornerRadius:7];
        [self addSubview:self.bgView];//添加手勢
        UIPanGestureRecognizer *panGesture = [UIPanGestureRecognizer new];
        panGesture.delegate = self;
        //cancelsTouchesInView 默認 YES,自定義的手勢響應后,系統手勢不再響應,但自定義手勢識別前,會先執行系統手勢。設置為 NO 后,自定義手勢和系統手勢會同時識別響應。
        panGesture.cancelsTouchesInView = NO;
        [panGesture addTarget:self action:@selector(panGestureAction:)];
        [self addGestureRecognizer:panGesture];
    }
    return self;
}

 

將列表加到白色背景視圖上,我這兒用的是 UICollectionView,因為列表是瀑布流 ,如果您們用的是UITableView,作相應的變化即可。

@property (nonatomic, strong) UICollectionView *collectionView;

 

[self.bgView addSubview:self.collectionView];

 

2.手勢代理處理

@property (nonatomic, assign) CGFloat beginContentOffsetY;//self.collectionView 偏移的y坐標
@property (nonatomic, assign) CGFloat lastTouchPointY;//記錄一下開始拖動時的y坐標
@property (nonatomic, assign) BOOL isUpPan;//是否上拉
@property (nonatomic, assign) CGFloat initOriginY;//白色背景視圖頂部y坐標
@property (nonatomic, assign) CGFloat needReplaceY;//拖動距離超過此距離時才識別手勢

 

- (void)panGestureAction:(UIPanGestureRecognizer *)gestureRecognizer {
    CGPoint translation = [gestureRecognizer translationInView:gestureRecognizer.view];
    
    //self.collectionView拖動時
    if (self.collectionView.panGestureRecognizer.state != UIGestureRecognizerStatePossible) {
        //self.collectionView拖動時如果 contentOffset.y > 0 就不走自定義手勢
        if (self.collectionView.contentOffset.y > 0) {
            return;
        }
    }

    if (translation.y > self.beginContentOffsetY) {
        self.bgView.top = translation.y - self.beginContentOffsetY  + self.initOriginY;
    } else {
        self.bgView.top = self.initOriginY;
    }
    
    if (gestureRecognizer.state == UIGestureRecognizerStateEnded) {
        //是否上拉
        self.isUpPan = ([gestureRecognizer locationInView:self].y - self.lastTouchPointY < 0 && fabs([gestureRecognizer velocityInView:self].y) > 10);
        if (translation.y > self.needReplaceY && !self.isUpPan) {
            //大於需求拖動的距離並且是下拉才取消視圖
            [self dissmis];
        } else {
            //復位
            [UIView animateWithDuration:0.2f animations:^{
                self.bgView.top = self.initOriginY;
            }];
        }
    } else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        //
        self.beginContentOffsetY = self.collectionView.contentOffset.y;
        //記錄一下開始拖動時的y坐標
        self.lastTouchPointY = [gestureRecognizer locationInView:self].y;
    }
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [super touchesEnded:touches withEvent:event];
    UITouch * aTouch = touches.anyObject;
    CGPoint aPoint = [aTouch locationInView:self];
    //點擊透明背景取消視圖
    if (aPoint.y < self.initOriginY) {
        [self dissmis];
    }
}

 

3.展示、取消視圖實現

- (void)show {
    [UIView animateWithDuration:0.3f animations:^{
        self.top = 0;
    }];
}

 

- (void)dissmis {
    [UIView animateWithDuration:0.2f animations:^{
        self.bgView.top = UIScreenHeight;
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
    }];
}

 

4.UIView的擴展設置圓角

/// 設置圓角
/// @param corner 圓角類型
/// @param cornerRadius 圓角大小
- (void)setCorner:(UIRectCorner)corner cornerRadius:(CGFloat)cornerRadius {
    CAShapeLayer *mask = [CAShapeLayer layer];
    UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds byRoundingCorners:corner cornerRadii:CGSizeMake(cornerRadius*2, cornerRadius*2)];
    mask.path = path.CGPath;
    self.layer.mask = mask;
}

 

 

 5.調用方式

        RecommendView *recommendView = [[RecommendView alloc] initWithFrame:CGRectMake(0, UIScreenHeight, UIScreenWidth, UIScreenHeight)];
        self.view addSubview:recommendView];
        [recommendView show];

 

備注:

translationInView : 手指在視圖上移動的位置(x,y)向下和向右為正,向上和向左為負。

locationInView : 手指在視圖上的位置(x,y)就是手指在視圖本身坐標系的位置。

velocityInView: 手指在視圖上移動的速度(x,y), 正負也是代表方向,值得一體的是在絕對值上|x| > |y| 水平移動, |y|>|x| 豎直移動。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM