iOS 自定义滑动切换TabBar

貌似经常会用到,自己整理收藏起来,方便日后查找备用。

效果如图:

由于制作gif,调整了属性,所以看起来的效果不好。如果用默认配置,生成的gif会很大。

制作gif:

1.使用QuickTimePlayer ,mac上插上iPhone, 然后进行屏幕录制,但是要选择插上的iPhone,然后会自动在Mac弹出同步的iPhone屏幕,点击录制。

2.使用GIFBrewery,选中录制文件*.mov, 进行生成gif。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#import "XPBaseView.h"
 
@protocol XPDetailTabBarViewDelegate;
 
@interface XPDetailTabBarView : XPBaseView
 
@property (nonatomic,weak) id<XPDetailTabBarViewDelegate> delegate;
/**
 *  是否是双语
 */
@property (nonatomic,assign) BOOL isBilingual;
/**
 *  是否点赞
 */
@property (nonatomic,assign) BOOL isLike;
 
@end
 
@protocol XPDetailTabBarViewDelegate <NSObject>
 
@optional
- (void)XPDetailTabBarView:(XPDetailTabBarView*)view clickIndex:(NSInteger)index;
 
@end

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#import "XPDetailTabBarView.h"
 
@interface XPDetailTabBarView ()
 
@property (nonatomic,strong) NSArray *dataImages;
@property (nonatomic,strong) UIView *moveView;
@property (nonatomic,assign) NSInteger moveIndex;
 
@end
 
@implementation XPDetailTabBarView
 
-(void)initData{
     
}
 
-(void)initSubViews{
    self.dataImages = @[@"detail_tab_english",@"icon_like",@"detail_tab_recording",@"detail_tab_quiz",@"detail_tab_myrecord"];
     
    CGFloat itemWidth = SCREEN_WIDTH / self.dataImages.count;
    CGFloat itemHeight = 44;
     
    self.moveView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, itemWidth, itemWidth)];
    self.moveView.backgroundColor = AppStyleThemeOrangeColor;
    [self addSubview:self.moveView];
     
    for (int i = 0; i<self.dataImages.count; i++)
    {
        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        button.tag = 20000+i;
        button.frame = CGRectMake(i*itemWidth, 0, itemWidth, itemHeight);
        button.backgroundColor = [UIColor clearColor];
        [button setImage:[UIImage imageNamed:[self.dataImages objectAtIndex:i]] forState:UIControlStateNormal];
        [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:button];
    }
}
 
-(void)setMoveIndex:(NSInteger)moveIndex{
     
    NSInteger animationType = 1;//1左,2右
    if(moveIndex > _moveIndex){
        animationType = 2;
    }
     
    _moveIndex = moveIndex;
     
    CGFloat itemWidth = SCREEN_WIDTH / self.dataImages.count;
    CGFloat itemHeight = 44;
     
    CGRect rect = CGRectMake(moveIndex*itemWidth, 0, itemWidth, itemHeight);
 
    WS(weakSelf)
    [UIView animateWithDuration:0.2 animations:^{
        if (animationType == 2){//右
            weakSelf.moveView.frame = CGRectMake(rect.origin.x+2, rect.origin.y, rect.size.width, rect.size.height);
        } else if (animationType == 1){//左
            weakSelf.moveView.frame = CGRectMake(rect.origin.x-2, rect.origin.y, rect.size.width, rect.size.height);
        }
    } completion:^(BOOL finished) {
        [UIView animateWithDuration:0.3 animations:^{
            if (animationType == 2){//右
                weakSelf.moveView.frame = CGRectMake(rect.origin.x-5, rect.origin.y, rect.size.width, rect.size.height);
            } else if (animationType == 1){//左
                weakSelf.moveView.frame = CGRectMake(rect.origin.x+5, rect.origin.y, rect.size.width, rect.size.height);
            }
        } completion:^(BOOL finished) {
            [UIView animateWithDuration:0.4 animations:^{
                weakSelf.moveView.frame = rect;
            } completion:^(BOOL finished) {
                 
            }];
        }];
    }];
}
 
- (void)setIsBilingual:(BOOL)isBilingual{
    _isBilingual = isBilingual;
     
    UIButton *button = [self viewWithTag:20000];
    if(isBilingual){
        [button setImage:[UIImage imageNamed:@"detail_tab_english"] forState:UIControlStateNormal];
    }else{
        [button setImage:[UIImage imageNamed:@"detail_tab_bilingual"] forState:UIControlStateNormal];
    }
}
 
- (void)setIsLike:(BOOL)isLike{
    _isLike = isLike;
     
    UIButton *button = [self viewWithTag:20001];
    if(isLike){
        [button setImage:[UIImage imageNamed:@"icon_like_selected"] forState:UIControlStateNormal];
    }else{
        [button setImage:[UIImage imageNamed:@"icon_like"] forState:UIControlStateNormal];
    }
}
 
- (void)buttonClicked:(UIButton*)button{
    NSInteger index = button.tag - 20000;
     
    self.moveIndex = index;
     
    if(self.delegate && [self.delegate respondsToSelector:@selector(XPDetailTabBarView:clickIndex:)]){
        [self.delegate XPDetailTabBarView:self clickIndex:index];
    }
}
@end

  

posted @   PPDev  阅读(1799)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· 展开说说关于C#中ORM框架的用法!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
点击右上角即可分享
微信分享提示