高仿简书个人中心

概述

高仿简书个人中心头像放大缩小,头像的点击,下面的分类等

详细

 

一、准备工作

 

高仿简书个人中心上下 左右滑动页面,开始做之前,首先思路要清晰,逻辑比较繁琐。

10C03A6D50280579F0F630A5A4CFC5E0.jpg

首先看到简书个人中心页面时,我大致给他划分为4大部分:

1,首先是用户的头像

2,用户资料信息

3,三个标题(TitleView)

4,下面UITableView

因为此处有左右滑动和上下两种滑动,所以在上面的2,3,4 我们整体放在一个ScrollView上, 而1,用户头像的改变,根据ScrollView 的上下滑动 y 值对头像大小进行处理。

二、程序实现

项目中不需要配置任何东西,全都是逻辑方面的东西,只要思维逻辑清楚,我们就开始干,

屏幕快照 2017-08-16 12.00.29.png

在上面的项目图中可以清楚的看到,所有的View都是自定义实现的,控制控制器的大小,之前一阿里朋友告诉我,他们公司的硬性规定,无论页面实现什么功能,在控制器中的代码 不能超过300 行,能封装的尽量封装起来,不做繁琐的代码Copy。

首先看下如何自定义头像View

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/** 初始化方法
 * 头像图片
 */
- (instancetype)initWithImage:(UIImage *)image;
 
/** 更新头像大小
 * 滚动视图
 */
- (void)reloadSizeWithScrollView:(UIScrollView *)scrollView;
 
/**
 * 点击头像回调
 */
- (void)handleClickActionWithBlock:(ClickImageBlock)block;

头像大小的改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:ContentOffset] && object == self.scrollView) {
         
        CGFloat offsetY = self.scrollView.contentOffset.y;
        CGFloat scale = 1.0;
        if (offsetY < 0) { // 放大
            scale = MIN(1.5, 1 - offsetY / 300);//简书没有这个功能
        } else if (offsetY > 0) { // 缩小
            scale = MAX(0.40, 1 - offsetY / 300);
        }
        self.yourImages.transform = CGAffineTransformMakeScale(scale, scale);
         
        CGRect frame = self.yourImages.frame;
        frame.origin.y = 15;
        self.yourImages.frame = frame;
    }
}

自定义TitleView(要可以左右滑动,标题下方有标注)

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
- (void)titleButtonClicked:(UIButton *)button {
    _selectedIndex               = button.tag;
    if (self.selectedButton) {
        self.selectedButton.selected = YES;
    }
    button.selected              = NO;
    self.selectedButton          = button;
     
    if (self.buttonSelected) {
        self.buttonSelected(button.tag);
    }
     
    NSString* title              = self.gztitles[button.tag];
    CGFloat sliderWidth          = button.titleLabel.font.pointSize * title.length;
    [self.sliderView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.width.mas_equalTo(sliderWidth);
        make.height.mas_equalTo(2);
        make.centerX.equalTo(button);
        make.bottom.equalTo(self).offset(-2);
    }];
    [UIView animateWithDuration:0.25 animations:^{
        [self layoutIfNeeded];
    }];
}
 
- (void)setSelectedIndex:(NSInteger)selectedIndex {
    _selectedIndex   = selectedIndex;
    UIButton* button = self.subviews[selectedIndex];
    [self titleButtonClicked:button];
}
 
- (void)setGztitles:(NSArray *)gztitles {
    [self.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
    _gztitles               = gztitles;
    CGFloat width         = [UIScreen mainScreen].bounds.size.width / gztitles.count;
     
    for ( int i           = 0; i<gztitles.count; i++ ) {
        UIButton* titleButton = [self titleButton:gztitles[i]];
        titleButton.tag       = i;
        [self addSubview:titleButton];
        [titleButton mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.bottom.equalTo(self);
            make.left.equalTo(self).offset(width * i);
            make.width.mas_equalTo(width);
        }];
        if (i != 0) {
            titleButton.selected  = YES;
        } else {
            self.selectedButton   = titleButton;
        }
    }
    UIButton *button      = self.subviews[0];
    NSString *title       = gztitles[0];
    CGFloat sliderWidth   = button.titleLabel.font.pointSize * title.length;
    [self addSubview:self.sliderView];
    [self.sliderView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.mas_equalTo(sliderWidth);
        make.height.mas_equalTo(4);
        make.centerX.equalTo(button);
        make.bottom.equalTo(self).offset(-3);
    }];
    [self layoutIfNeeded];
}
 
- (UIButton *)titleButton:(NSString *)title {
    UIButton* titleButton       = [[UIButton alloc] init];
    [titleButton addTarget:self action:@selector(titleButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
    titleButton.titleLabel.font = [UIFont systemFontOfSize:15];
    [titleButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
    [titleButton setTitleColor:[UIColor grayColor] forState:UIControlStateSelected];
    [titleButton setTitle:title forState:UIControlStateNormal];
    return titleButton;
}

自定义的信息页面

1
2
3
4
5
6
7
- (void)layoutSubviews {
    [super layoutSubviews];
    [self addSubview:self.nameLabel];
    [self addSubview:self.Address];
    [self addSubview:self.infoLabel];
    [self addSubview:self.editInfoButton];
}

简单的添加属性就好 

UITableView的话也是简单的TableView

最后到我们的控制器页面,在这个页面我们只负责

UITableViewDelegate 的东西,数据我们都在自定义的页面处理,减少控制器页面的代码量,

在控制器中我们就是将自定义的View组合起来

首先是整体一个ScrollView 然后在其上面添加我们事先定义的所有控件。

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
    GZContentScrollView *scrollView           = [[GZContentScrollView alloc] init];
    scrollView.delaysContentTouches           = NO;
    [self.view addSubview:scrollView];
    self.scrollView                           = scrollView;
    scrollView.pagingEnabled                  = YES;
    scrollView.showsVerticalScrollIndicator   = NO;
    scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.delegate                       = self;
    scrollView.contentSize                    = CGSizeMake([UIScreen mainScreen].bounds.size.width * 3, 0);
    UIView *headView                          = [[UIView alloc] init];
    headView.frame               = CGRectMake(0, 0, 0, GZHeadViewHeight + GZTitleHeight);
     
    GZTableView1 *gzTableView1 = [[GZTableView1 alloc] init];
    gzTableView1.delegate            = self;
    gzTableView1.separatorStyle      = UITableViewCellSeparatorStyleNone;
    self.GZTableView1                = gzTableView1;
    gzTableView1.tableHeaderView     = headView;
    [scrollView addSubview:gzTableView1];
    [gzTableView1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(scrollView);
        make.width.mas_equalTo([UIScreen mainScreen].bounds.size.width);
        make.top.equalTo(self.view);
        make.bottom.equalTo(self.view);
    }];
     
    GZTableView2 *gzTableView2= [[GZTableView2 alloc] init];
    gzTableView2.delegate            = self;
    gzTableView2.separatorStyle      = UITableViewCellSeparatorStyleNone;
    self.GZTableView2                = gzTableView2;
    gzTableView2.tableHeaderView     = headView;
    [scrollView addSubview:gzTableView2];
    [gzTableView2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(scrollView).offset([UIScreen mainScreen].bounds.size.width);
        make.width.equalTo(gzTableView1);
        make.top.bottom.equalTo(gzTableView1);
    }];
     
    GZTableView3 *gzTableView3 = [[GZTableView3 alloc] init];
    gzTableView3.delegate            = self;
    gzTableView3.separatorStyle      = UITableViewCellSeparatorStyleNone;
    self.GZTableView3                = gzTableView3;
    gzTableView3.tableHeaderView     = headView;
    [scrollView addSubview:gzTableView3];
    [gzTableView3 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(scrollView).offset([UIScreen mainScreen].bounds.size.width * 2);
        make.width.equalTo(gzTableView1);
        make.top.bottom.equalTo(gzTableView1);
    }];
}

头部视图添加

视图都添加完毕之后,要实现滑动事件,我们必须要进行下面的活动:

1
2
3
4
5
6
7
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView == self.scrollView || !scrollView.window) {
        return;
    }
    CGFloat offsetY      = scrollView.contentOffset.y;
    CGFloat originY      = 0;
    CGFloat otherOffsetY = 0;

 

判断ScrollView 是因为 我们这个页面有两种滑动事件

至此,简书个人中心页面的功能都已实现。

三、运行效果

运行效果如下图显示:

视.gif

 

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

posted on   demo例子集  阅读(793)  评论(0编辑  收藏  举报

(评论功能已被禁用)
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示