自定义 TableView 滚动指示器 (iOS)

Posted

技术标签:

【中文标题】自定义 TableView 滚动指示器 (iOS)【英文标题】:Custom TableView Scroll indicator (iOS) 【发布时间】:2016-06-17 17:00:00 【问题描述】:

我有一个使用 tableview 的应用程序,有时这个 tableview 中可以有多达 100 个项目。因此,我被指派自定义此滚动指示器,以便用户轻松滚动浏览其内容。为此,我需要实现以下内容:

1) 我需要滚动指示器始终显示。

2) 我需要将滚动指示器从 ios 默认的灰色指示器更改为橙色指示器,并在其中间添加一个向内延伸的标签。此标签将包含单元格的日期。当您在滚动条中向下滚动时,日期会更改以反映您在页面上的位置。 (请参见图片进行说明)。

3) 当您单击并按住此自定义 TableView 的滚动指示器时,它会启用快速滚动。

解决此问题的最佳方法是什么?我应该使用图书馆吗?

【问题讨论】:

恐怕你不能直接做你需要自己创建。 那么我应该继承什么? UIScrollView? 是的,最好使用UIScrollView子类,你需要像scrollview中的子视图一样添加它,并用contentSize和contentOffset计算上下滚动,会很有趣.. 【参考方案1】:

这不是一个完美的解决方案,但这是我想出的,这应该会让您走上正确的轨道,以完善此解决方案以满足您的需求。基本上你需要做几个基本的步骤:

1实例化一个tableView(UITableView)和scrollViewIndicator(UIView)

2 根据tableView的contentSize计算scrollIndicator的高度。然后将 tableView 和 scrollIndicator 添加到容器视图中,并将 tableView 上方的滚动指示器及其 alpha 属性设置为 0(我们滚动时淡入)

3检查tableView(UIScrollView的子类)的contentOffset,并根据这个值移动scrollIndicator

4 tableView 减速后将 scrollIndicator 淡出

您的特定自定义滚动指示器将由您的项目和需求决定。这应该会让你走上正确的轨道,但我认为你最大的问题是在引入“分页”后计算 scrollIndicator 的高度。但我对你有信心!祝我的朋友好运。

#import "ViewController.h"

static CGFloat indicatorPadding =          5;
static CGFloat indicatorHeightMultiplyer = 0.05;
static CGFloat indicatorWidth =            3;
static CGFloat indicatorShowAnimation =    0.10;

@interface ViewController () <UITableViewDataSource, UITableViewDelegate> 
    CGFloat lastScrollOffset;
    BOOL    isFadingIndicator;


@property (strong, nonatomic) UITableView *tableView;
@property (strong, nonatomic) UIView      *scrollIndicator;

@end

@implementation ViewController

- (void)viewDidLoad 
    [super viewDidLoad];

    isFadingIndicator = NO;

    // Set Up TableView
    self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
    self.tableView.rowHeight = 100;
    self.tableView.dataSource = self;
    self.tableView.delegate = self;
    self.tableView.showsHorizontalScrollIndicator = NO;
    self.tableView.showsVerticalScrollIndicator = NO;
    [self.tableView layoutIfNeeded];

    // Calculate indicator size based on TableView contentSize
    CGFloat indicatorHeight = self.tableView.contentSize.height * indicatorHeightMultiplyer;

    // Set Up Scroll Indicator
    self.scrollIndicator = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetWidth(self.tableView.frame) - indicatorPadding, indicatorPadding, indicatorWidth, indicatorHeight)];
    self.scrollIndicator.backgroundColor = [UIColor orangeColor];
    self.scrollIndicator.layer.cornerRadius = self.scrollIndicator.frame.size.width / 2;

    // Add TableView
    [self.view addSubview:self.tableView];

    // Add Scroll Indicator
    [self.view addSubview:self.scrollIndicator];


- (void)didReceiveMemoryWarning 
    [super didReceiveMemoryWarning];



#pragma mark - TABLE VIEW METHODS

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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];

    return cell;


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

    return 10;


-(void)scrollViewDidScroll:(UIScrollView *)scrollView 

    if (scrollView == self.tableView) 

        [self showIndicator];

        if (lastScrollOffset >= scrollView.contentOffset.y) 
            [self moveScrollIndicatorDownward:YES withOffset:scrollView.contentOffset.y];
        
        else 
            [self moveScrollIndicatorDownward:NO withOffset:scrollView.contentOffset.y]; // upward
        

        lastScrollOffset = scrollView.contentOffset.y;

    



-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
    [self hideIndicator];


#pragma mark - SCROLL INDICATOR METHODS

-(void)showIndicator 

    if (self.scrollIndicator.alpha == 0 && isFadingIndicator == NO) 
        // fade in scroll indicator
        isFadingIndicator = YES;
        [UIView animateWithDuration:indicatorShowAnimation animations:^
            self.scrollIndicator.alpha = 1;
         completion:^(BOOL finished) 
            isFadingIndicator = NO;
        ];

    



-(void)hideIndicator 

    if (self.scrollIndicator.alpha == 1 && isFadingIndicator == NO) 
        // fade out scroll indicator
        isFadingIndicator = YES;
        [UIView animateWithDuration:indicatorShowAnimation animations:^
            self.scrollIndicator.alpha = 0;
         completion:^(BOOL finished) 
            isFadingIndicator = NO;
        ];
    


-(void)moveScrollIndicatorDownward:(BOOL)downwards withOffset:(CGFloat)offset 

    if ([self canMoveScrollIndicator:downwards]) 

        self.scrollIndicator.center = CGPointMake(CGRectGetMidX(self.scrollIndicator.frame), (CGRectGetHeight(self.scrollIndicator.frame) / 2) + offset);

    
    else 
        // maybe 'bounce' scroll indicator if isDecelerting is YES?
    



-(BOOL)canMoveScrollIndicator:(BOOL)downwards 

    if (downwards) 
        if (self.scrollIndicator.frame.origin.y >= self.tableView.frame.size.height - indicatorPadding) 
            return NO;
        
        else 
            return YES;
        
    
    else 
        // upwards
        if ((self.scrollIndicator.frame.origin.y + self.scrollIndicator.frame.size.height) <= self.tableView.frame.origin.y + indicatorPadding) 
            return NO;
        
        else 
            return YES;
        
    



@end

【讨论】:

【参考方案2】:

您必须隐藏本机滚动指示器:tableView.showsVerticalScrollIndicator = false 并创建自定义 UIView 对象,该对象将在 tableView.contentOffset.y 更改时移动。可以通过帮助scrollViewDidScroll 函数对其进行跟踪。

【讨论】:

以上是关于自定义 TableView 滚动指示器 (iOS)的主要内容,如果未能解决你的问题,请参考以下文章

使用自定义 uitableviewcell 滚动 tableview 的问题

iphone使用自定义单元格滚动tableview太慢了

在 iOS 13 中关闭 UIScrollView 指示器清理

带有自定义 UITextView 单元格的 TableView 将导航栏滚动到屏幕外

我需要在 TableView 中创建基于图像的自定义附件类型的示例代码

如何在 UIViewController 的 tableView 顶部添加自定义视图并能够一起滚动