uitableview添加手势拖动悬停

本文介绍如何在 iOS 开发中实现一个UITableView,允许用户在其一定范围内进行手势拖动,拖动到顶部或底部时能内部滑动。通过自定义HJGestureTable类并处理手势与滑动冲突,实现了拖动悬停效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

实现uitableview 在一定范围内可以拖动 ,拖动到最顶部或最底部时可以内部滑动

首先我们定义一个HJGestureTable 继承自UITableView 并实现如下方法

// 允许处理多个手势

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer

{

    NSLog(@"%@,%@",gestureRecognizer.view,otherGestureRecognizer.view);

    return YES;

}

第二步 解决拖动手势和滑动的冲突

#import "ViewController.h"

#import "HJGestureTable.h"

 

#define Nav_TopHeight ([UIScreen mainScreen].bounds.size.height >= 812.0 ? 35 : 20)

#define Kuan_Width [UIScreen mainScreen].bounds.size.width

#define Gao_HEIGHT [UIScreen mainScreen].bounds.size.height

#define BL_Kuan [UIScreen mainScreen].bounds.size.width/375

typedef enum{

    Top = 0,

    Bottom,

}TopOrBottom;//从顶部开始拖动还是从底部开始拖动

@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>

{

    BOOL alsoPanGesture;

}

@property(nonatomic,assign)TopOrBottom  topOrBottom;

@property(nonatomic,strong)HJGestureTable * trendsTableView;

 

@property(nonatomic,assign)float topOriginY;//trendsTableView可以拖动到的最顶部

 

@property(nonatomic,assign)float bottomOriginY;//trendsTableView可以拖动到的最底部

 

 

 

@end

 

@implementation ViewController

 

-(HJGestureTable *)trendsTableView

{

    if (!_trendsTableView) {

        _trendsTableView = [[HJGestureTable alloc] initWithFrame:CGRectMake(0, self.bottomOriginY, Kuan_Width, Gao_HEIGHT-self.topOriginY)];

        _trendsTableView.delegate = self;

        _trendsTableView.dataSource = self;

        [self.view addSubview:_trendsTableView];

    }

    return _trendsTableView;

}

- (void)viewDidLoad {

    [super viewDidLoad];

    

    self.view.backgroundColor = [UIColor whiteColor];

    

    self.topOriginY = Nav_TopHeight+50*BL_Kuan;

    self.bottomOriginY = Nav_TopHeight+400*BL_Kuan;

    self.trendsTableView.separatorStyle = NO;

    [self.trendsTableView setContentSize:CGSizeMake(Kuan_Width, self.trendsTableView.frame.size.height+300)];

    //添加拖动手势

    UIPanGestureRecognizer * pan =[[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePan:)];

    [self.trendsTableView addGestureRecognizer:pan];

}

-(void)scrollViewDidScroll:(UIScrollView *)scrollView

{

    //让手势拖动监听先执行,防止手势拖动还没有监听到,tableview自身已经滚动了,从而self.trendsTableView.contentOffset.y!=0

    if(!alsoPanGesture)

    {

        [self.trendsTableView setContentOffset:CGPointMake(0, 0)];

    }

    //当self.trendsTableView的位置在最顶部和最底部之间时让self.trendsTableView只可以拖动,让self.trendsTableView自身滑动无效

    if (self.trendsTableView.frame.origin.y>self.topOriginY&&self.trendsTableView.frame.origin.y<self.bottomOriginY)

    {

        NSLog(@"当self.trendsTableView手势拖动时,self.trendsTableViewn自身滑动事件禁止");

        [self.trendsTableView setContentOffset:CGPointMake(0, 0)];

    }

    

    //当self.trendsTableView拖动到顶部 self.trendsTableView的内部还要向下滚动时让self.trendsTableView可以拖动

    if(self.trendsTableView.frame.origin.y==self.topOriginY && self.trendsTableView.contentOffset.y<0)

    {

        [self.trendsTableView setContentOffset:CGPointMake(0, 0)];

    }

    //当self.trendsTableView拖动到底部 self.trendsTableView的内部还要向上滚动时让self.trendsTableView可以拖动

    if(self.trendsTableView.frame.origin.y==self.bottomOriginY && self.trendsTableView.contentOffset.y>0)

    {

        [self.trendsTableView setContentOffset:CGPointMake(0, 0)];

    }

}

#pragma mark - 手势执行的方法

-(void)handlePan:(UIPanGestureRecognizer *)rec{

    alsoPanGesture = YES;

    //返回在横坐标上、纵坐标上拖动了多少像素

    CGPoint point=[rec translationInView:self.view];

    //当self.trendsTableView内部没有滚动到顶部时 不允许拖动

    if (self.trendsTableView.contentOffset.y!=0)

    {

        NSLog(@"%f",self.trendsTableView.contentOffset.y);

        return;

    }

    if (self.trendsTableView.frame.origin.y+point.y<=self.topOriginY ) {

        //当self.trendsTableView拖动到最顶部时可以滑动  且self.trendsTableView的位置不再随拖动改变

        self.trendsTableView.frame = CGRectMake(self.trendsTableView.frame.origin.x, self.topOriginY, self.trendsTableView.frame.size.width, self.trendsTableView.frame.size.height);

        self.trendsTableView.scrollEnabled = YES;

    }

    else if (self.trendsTableView.frame.origin.y+point.y>=self.bottomOriginY)

    {

        //当self.trendsTableView拖动到最底部时可以滑动  且self.trendsTableView的位置不再随拖动改变

        self.trendsTableView.frame = CGRectMake(self.trendsTableView.frame.origin.x, self.bottomOriginY, self.trendsTableView.frame.size.width, self.trendsTableView.frame.size.height);

        self.trendsTableView.scrollEnabled = YES;

    }

    else

    {

        self.trendsTableView.frame = CGRectMake(self.trendsTableView.frame.origin.x, self.trendsTableView.frame.origin.y+point.y, self.trendsTableView.frame.size.width, self.trendsTableView.frame.size.height);

        self.trendsTableView.scrollEnabled = NO;//防止在拖动的同时 self.trendsTableView内部滚动

    }

    [rec setTranslation:CGPointMake(0, 0) inView:self.view];

    if(rec.state == UIGestureRecognizerStateEnded || rec.state == UIGestureRecognizerStateCancelled)//拖动结束

    {

        //当self.trendsTableView拖动结束时  让self.trendsTableView的位置滚动到最顶部或者最底部

        if (self.topOrBottom == Bottom) {

            if (self.trendsTableView.frame.origin.y<self.bottomOriginY-30*BL_Kuan) {

                self.topOrBottom = Top;

                [UIView animateWithDuration:0.5 animations:^{

                    self.trendsTableView.frame = CGRectMake(self.trendsTableView.frame.origin.x, self.topOriginY, self.trendsTableView.frame.size.width, self.trendsTableView.frame.size.height);

                } completion:^(BOOL finished) {

                    self.trendsTableView.scrollEnabled = YES;

                }] ;

            }

            else

            {

                [UIView animateWithDuration:0.5 animations:^{

                    self.trendsTableView.frame = CGRectMake(self.trendsTableView.frame.origin.x, self.bottomOriginY, self.trendsTableView.frame.size.width, self.trendsTableView.frame.size.height);

                } completion:^(BOOL finished) {

                    self.trendsTableView.scrollEnabled = YES;

                }] ;

            }

        }

        else

        {

            if (self.trendsTableView.frame.origin.y>self.topOriginY+30*BL_Kuan) {

                self.topOrBottom = Bottom;

                [UIView animateWithDuration:0.5 animations:^{

                    self.trendsTableView.frame = CGRectMake(self.trendsTableView.frame.origin.x, self.bottomOriginY, self.trendsTableView.frame.size.width, self.trendsTableView.frame.size.height);

                } completion:^(BOOL finished) {

                    self.trendsTableView.scrollEnabled = YES;

                }] ;

            }

            else

            {

                [UIView animateWithDuration:0.5 animations:^{

                                  self.trendsTableView.frame = CGRectMake(self.trendsTableView.frame.origin.x, self.topOriginY, self.trendsTableView.frame.size.width, self.trendsTableView.frame.size.height);

                              } completion:^(BOOL finished) {

                                  self.trendsTableView.scrollEnabled = YES;

                              }] ;

            }

        }

    }

}

#pragma mark---UITableViewDelegate

 

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

    return 10;

}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

    return  207*BL_Kuan;

}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    NSString *tableIdentifier = [NSString stringWithFormat:@"RoomTableViewCell"] ;

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableIdentifier];

    if (cell == nil)

    {

        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];

    }

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    if (indexPath.row%2==0) {

        cell.backgroundColor = [UIColor purpleColor];

    }

    else

    {

        cell.backgroundColor = [UIColor yellowColor];

    }

    return cell;

}

demo地址:  

https://github.com/tangmengbo/UIPanGesture_UItableview.git
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

义中

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值