OC 拖拽View

使用 

    PanPopView2 *popView2 = [[PanPopView2 alloc] initWithminHeight:300 maxHeight:[UIScreen mainScreen].bounds.size.height - 120 panViewHeight:30];
    [self.view addSubview:popView2];

.h文件

@interface PanPopView2 : UIView
- (instancetype)initWithminHeight:(CGFloat)minHeight
                        maxHeight:(CGFloat)maxHeight
                    panViewHeight:(CGFloat)panViewHeight;
@end

.m文件

#import "PanPopView2.h"

@interface PanPopView2 ()<UITableViewDelegate,UITableViewDataSource,UIGestureRecognizerDelegate>

@property (strong, nonatomic) UITableView *listView;
/// 移动触点 1.触点在label ,永远为yes, 2.触点在tv上, 滑到了label上为YES, 不在label 为NO
@property (assign, nonatomic) BOOL isTouchPanLabel;
///记录TV偏移量
@property (assign, nonatomic) CGFloat contentOffset;
///初始的触点在label上
@property (assign, nonatomic) BOOL istop;
///bgView 更新后的frame
@property (assign, nonatomic) CGRect bgViewFrame;
///最小高度
@property (assign, nonatomic) CGFloat minHeight;
///最大高度
@property (assign, nonatomic) CGFloat maxHeight;
///拖拽最大高度
@property (assign, nonatomic) CGFloat panViewHeight;

@end

@implementation PanPopView2

- (instancetype)initWithminHeight:(CGFloat)minHeight
                        maxHeight:(CGFloat)maxHeight
                    panViewHeight:(CGFloat)panViewHeight{
    self = [super initWithFrame:CGRectZero];
    if (self) {
        self.backgroundColor = UIColor.greenColor;
//        self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height);
        self.minHeight = minHeight;
        self.maxHeight = maxHeight;
        self.panViewHeight = panViewHeight;
        
        [self setUI];
    }
    return self;
}-(void)setUI{
    
    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pantarget:)];
    pan.delegate = self;
    
    self.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height- self.minHeight, [UIScreen mainScreen].bounds.size.width, self.minHeight);
    self.backgroundColor = UIColor.systemRedColor;
    self.userInteractionEnabled = YES;
    [self addGestureRecognizer:pan];
    self.bgViewFrame = self.frame;
    
    UIView *panView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, self.panViewHeight)];
    panView.backgroundColor = UIColor.blackColor;
    [self addSubview:panView];
    
    UITableView *listView = [[UITableView alloc]initWithFrame:CGRectMake(0, self.panViewHeight, self.frame.size.width, self.frame.size.height-self.panViewHeight) style:UITableViewStyleGrouped];
    listView.showsVerticalScrollIndicator = NO;
    listView.backgroundColor = UIColor.clearColor;
    listView.separatorStyle = UITableViewCellSeparatorStyleNone;
    listView.estimatedRowHeight = 0;
    listView.estimatedSectionFooterHeight = 0;
    listView.estimatedSectionHeaderHeight = 0;
    listView.delegate = self;
    listView.dataSource = self;
    listView.scrollEnabled = NO;
    if (@available(iOS 11.0, *)) {
        listView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
    }else {
    }
    [self addSubview:listView];
    self.listView = listView;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 80;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
    return 0.05;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
    return 0.05;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 50;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellid = @"jjj";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellid];
    if (!cell) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellid];
    }
    cell.contentView.backgroundColor = [self arndomColor];
    cell.textLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row];
    return cell;
}

- (UIColor *)arndomColor{
    
    CGFloat red = arc4random_uniform(256)/ 255.0;
    
    CGFloat green = arc4random_uniform(256)/ 255.0;
    
    CGFloat blue = arc4random_uniform(256)/ 255.0;
    
    UIColor *color = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
    
    return color;
    
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (!self.isTouchPanLabel) {
        NSLog(@"%f",scrollView.contentOffset.y);
        self.contentOffset = scrollView.contentOffset.y;
    }
}

//-(void)scrollViewWillBeginDecelerating: (UIScrollView *)scrollView{
//    [scrollView setContentOffset:scrollView.contentOffset animated:NO];
//}

- (void)topFrame{
    [UIView animateWithDuration:0.5 animations:^{
        self.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height - self.maxHeight, self.frame.size.width, self.maxHeight);
        self.listView.frame = CGRectMake(0, self.listView.frame.origin.y , self.listView.frame.size.width, self.maxHeight - self.panViewHeight);
    }completion:^(BOOL finished) {
        self.listView.scrollEnabled = YES;
        self.listView.userInteractionEnabled = YES;
    }];
    self.contentOffset = self.listView.contentOffset.y;
    self.bgViewFrame = self.frame;
}

- (void)bottomFrame{
    [UIView animateWithDuration:0.5 animations:^{
        self.frame = CGRectMake(0, [UIScreen mainScreen].bounds.size.height - self.minHeight, self.frame.size.width, self.minHeight);
    } completion:^(BOOL finished) {
        self.listView.frame = CGRectMake(0, self.listView.frame.origin.y , self.listView.frame.size.width, self.minHeight - self.panViewHeight);
        if (self.listView.contentOffset.y > 0){
            self.listView.scrollEnabled = YES;
            self.listView.userInteractionEnabled = YES;
        }else{
            self.listView.scrollEnabled = NO;
            self.listView.userInteractionEnabled = NO;
        }
    }];
    self.contentOffset = self.listView.contentOffset.y;
    self.bgViewFrame = self.frame;
}

- (void)pantarget:(UIGestureRecognizer*)ges
{
    UIPanGestureRecognizer *pan = (UIPanGestureRecognizer *)ges;
    CGPoint translation = [pan translationInView:self];

    switch (ges.state) {
        case UIGestureRecognizerStateEnded:
        {
            ///方向上移动
            if (!self.istop) {
                if (self.frame.size.height == self.maxHeight) {///在最顶部
                    if (self.listView.contentOffset.y <= 0 && translation.y > 0){///TV滚到顶部下拉 才往下
                        [self bottomFrame];
                    }
                }else if (self.frame.size.height == self.minHeight){///最底部
                    if (translation.y < 0) {///向上滑
                        [self topFrame];
                    }
                }else{/// TV 在中间
                    if ( translation.y > 0){///向下 直接到最低
                        [self bottomFrame];
                    }else if (translation.y < 0){///向上 直接到顶
                        [self topFrame];
                    }
                }
            }else{
                ///滑动 顶部小标签
                if (translation.y < 0) {//向上
                    [self topFrame];
                }else{
                    [self bottomFrame];//向下
                }
            }

            self.contentOffset = self.listView.contentOffset.y;
            self.bgViewFrame = self.frame;
            return;
        }
            break;
        case UIGestureRecognizerStateChanged:
        {
            CGPoint pont = [ges locationInView:self];
            
            if (self.istop) {///拖拽的panView
                self.listView.scrollEnabled = NO;
                if (translation.y < 0) {
                    //向上
                    self.isTouchPanLabel = YES;

                    NSLog(@"正在向上拖拽顶部条%f",translation.y);
                    CGRect frame = self.bgViewFrame;
                    frame.origin.y = MAX(frame.origin.y + translation.y, [UIScreen mainScreen].bounds.size.height - self.maxHeight ) ;
                    frame.size.height = MIN(frame.size.height - translation.y, self.maxHeight) ;
                    [self updateChangedFrame:frame];
                    self.listView.contentOffset = CGPointMake(0, self.contentOffset);
                }else {
                    ///向下
                    self.isTouchPanLabel = YES;

                    NSLog(@"正在向下拖拽顶部条%f",translation.y);
                    CGRect frame = self.bgViewFrame;
                    frame.origin.y = MIN(frame.origin.y + translation.y, [UIScreen mainScreen].bounds.size.height - self.minHeight) ;
                    frame.size.height = MAX(self.minHeight, frame.size.height - translation.y);
                    [self updateChangedFrame:frame];
                    self.listView.contentOffset = CGPointMake(0, self.contentOffset);
                }
                return;
            }

            if (pont.y < self.panViewHeight) {
                self.isTouchPanLabel = YES;

                NSLog(@"呱呱呱%f",pont.y);
                if (self.frame.size.height >= self.maxHeight) {
                    return;
                }
                CGRect frame = self.frame;
                frame.origin.y = frame.origin.y - self.panViewHeight + pont.y;
                frame.size.height = frame.size.height + self.panViewHeight - pont.y;
                [self updateChangedFrame:frame];
                self.listView.contentOffset = CGPointMake(0, self.contentOffset);

            }else {
                self.isTouchPanLabel = NO;
                NSLog(@"取消手势");
                if (self.contentOffset < 0) {
                    if (self.frame.size.height <= self.minHeight) {
                        return;
                    }
                    CGRect frame = self.frame;
                    frame.origin.y = frame.origin.y - self.contentOffset;
                    frame.size.height = frame.size.height + self.contentOffset;
                    [self updateChangedFrame:frame];
                    self.listView.contentOffset = CGPointMake(0, 0);
                }
            }
        }
            break;

        default:
            break;
    }
}

- (void)updateChangedFrame:(CGRect)frame{
    self.frame = frame;
    self.listView.frame = CGRectMake(0, self.panViewHeight, frame.size.width, frame.size.height-self.panViewHeight);
}


//- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveEvent:(nonnull UIEvent *)event
//{
//    NSLog(@"哈哈");
//    return YES;
//}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    NSLog(@"嘤嘤嘤");
    return YES;
}

//- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
//{
//    CGPoint pont = [gestureRecognizer locationInView:self.bgView];
//    self.istop = pont.y < 20;
//    return pont.y < 20;
//}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    CGPoint pont = [gestureRecognizer locationInView:self];
    if (pont.y <= self.panViewHeight) {
        NSLog(@"底部view %f",pont.y);
        self.istop = YES;
        return YES;
    }else {
        NSLog(@"tableview %f",pont.y);
        self.istop = NO;
        return NO;
    }
}


@end
原文地址:https://www.cnblogs.com/qingzZ/p/15078213.html