美文网首页很常
[iOS]极简横向滚动菜单栏

[iOS]极简横向滚动菜单栏

作者: 世上无南西 | 来源:发表于2021-04-23 15:45 被阅读0次

    之前不同的项目写了好几次,这次想想封装一下,代码虽然不多,但是重复造轮子总不是好习惯。

    原理:ScrollView横向滚动,依次排列菜单按钮,以颜色和下划线来标识选择

    效果如图中横向菜单栏
    图中实现效果还有与collectionView的联动,本文中就不提及了。

    实现起来没有复杂逻辑,直接上全套代码:

    typedef void(^MenuClickEvent)(NSInteger index);
    
    @interface BDMenuScrollView : UIScrollView
    {
        UIView * markLine;
        NSInteger lastIndex;
    }
    
    @property(nonatomic) NSInteger selectedIndex;
    
    @property(nonatomic) BOOL repeatTouch;
    
    @property(nonatomic, copy)MenuClickEvent clickBlock;
    
    -(void)setMenuWithArray:(NSArray *)array;
    
    -(void)setButtonSelectedAtIndex:(NSInteger)index;
    
    @end
    
    @implementation BDMenuScrollView
    - (instancetype)initWithFrame:(CGRect)frame
    {
        self = [super initWithFrame:frame];
        if (self) {
            self.showsVerticalScrollIndicator = NO;
            self.showsHorizontalScrollIndicator = NO;
        }
        return self;
    }
    -(void)setMenuWithArray:(NSArray *)array{
        for (UIView * view in self.subviews) {
            [view removeFromSuperview];
        }
        
        if(array.count){
            CGRect frame = CGRectMake(0, 0, 0, self.frame.size.height);
            for (int i = 0; i<array.count; i++) {
                NSString * titleStr = array[i];
                
                UIButton * button = [[UIButton alloc] initWithFrame:frame];
                [self addSubview:button];
                [button addTarget:self action:@selector(buttonEvent:) forControlEvents:UIControlEventTouchUpInside];
                [button setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
                [button setTitleColor:[UIColor colorFromHexString_au:@"04ab62"] forState:UIControlStateSelected];
                [button setTitle:titleStr forState:UIControlStateNormal];
                button.titleLabel.font = [UIFont systemFontOfSize:16];
                button.tag = 100+i;
                [button sizeToFit];
                
                frame = button.frame;
                frame.size.height = self.frame.size.height;
                frame.size.width = frame.size.width + 30;
                button.frame = frame;
                frame.origin.x = CGRectGetMaxX(frame);
                
                if(i == 0){
                    button.selected = YES;
                    self.selectedIndex = 0;
                    
                    // add markline
                    markLine  = [[UIView alloc]initWithFrame:CGRectMake(0, self.frame.size.height-2, 40, 2)];
                    [self addSubview:markLine];
                    markLine.backgroundColor = [UIColor colorFromHexString_au:@"04ab62"];
                    markLine.center = CGPointMake(button.center.x, markLine.centerY);
                }
            }
            
            self.contentSize = CGSizeMake(frame.origin.x, 0);
        }else{
            return;
        }
    }
    
    -(void)setButtonSelectedAtIndex:(NSInteger)index{
        [self scrollToIndex:index];
    }
    
    -(void)scrollToIndex:(NSInteger)index{
        if(self.selectedIndex == index){
            return;
        }
        
        NSInteger a = lastIndex > self.selectedIndex ? lastIndex : self.selectedIndex;
        NSInteger b = lastIndex <= self.selectedIndex ? lastIndex : self.selectedIndex;
        
        // 忽略中间值
        if(index <= a && index >= b){
            return;
        }
        
        lastIndex = self.selectedIndex;
        UIButton * lastButton = [self viewWithTag:lastIndex + 100];
        lastButton.selected = NO;
        self.selectedIndex = index;
        lastButton = [self viewWithTag:self.selectedIndex + 100];
        lastButton.selected = YES;
        __weak typeof(self) weakself = self;
        [UIView animateWithDuration:0.2 animations:^{
            markLine.center = CGPointMake(lastButton.center.x, markLine.center.y);
        } completion:^(BOOL finished) {
            // 防止外部高频调用的时候出现中间值, 产生结果偏移
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                lastIndex = weakself.selectedIndex;
            });
        }];
        
        if(self.contentOffset.x > lastButton.frame.origin.x){
            [self setContentOffset:CGPointMake(lastButton.frame.origin.x, 0) animated:YES];
        }else if(self.contentOffset.x + self.frame.size.width < CGRectGetMaxX(lastButton.frame)){
            [self setContentOffset:CGPointMake(CGRectGetMaxX(lastButton.frame)-self.frame.size.width, 0) animated:YES];
        }
    }
    
    -(void)buttonEvent:(UIButton *)button{
        if(button.tag - 100 == self.selectedIndex && !self.repeatTouch){
            return;
        }
        NSInteger clickIndex = button.tag - 100;
        if(self.clickBlock){
            self.clickBlock(clickIndex);
        }
        
        [self scrollToIndex:clickIndex];
    }
    
    @end
    

    相关文章

      网友评论

        本文标题:[iOS]极简横向滚动菜单栏

        本文链接:https://www.haomeiwen.com/subject/zawcrltx.html