实现微博个人页面的滑块浮动切换页面效果

前言, 之前写了一篇文章, 实现类似淘宝商品界面的滑块效果, 不过很(##抱歉##)的是, 笔者当时没有测试TableView等的使用,大家反映TableView不能正常使用,(研究一段时间发现, 之前的做法不适结合合TableView使用) 这里就整理了下重新实现了, 比之前的确实要麻烦一点, 如果在你的项目中不需要结合TableView就可以简单的按照之前的方法实现.

最终效果

示例效果.gif

注意!!! 实现这个效果github上的代码有更新, 大家使用最新的代码

更新说明: 使每个页面在顶端滚动的偏移量不相互影响

构思: 利用监控和设置UIScrollView的偏移量来实现

层级结构

.

  1. 层级结构, 第一层为控制器的view, 第二层为contentView, 第三层为 headView和segmentView

  2. 第二层的contentView,设置contentView的大小和控制器的view的大小一样, 来显示子控制器的view的内容, 需要设置他的子控制器view的tableView(collectionVie)的初始偏移量为segmentView和headView的高度之和,同时将segmentView和headView添加到view上面, 以实现tableView在滚动的时候segmentView和headView可以同步滚动

  3. subview的添加顺序, 先添加contentView, 然后再添加segmentView和headView(因为contentView和view大小一样, 若是在后面添加就将segmentView和headView遮住了)

  4. 同步滚动原理: 监控子控制器的scrollView的滚动偏移量(contentOffset.y), 根据偏移量的改变量来同步的调整segmentView和headView的frame, 这里的监控之前我是使用Closure来实现,但是后面需要更新tableView的偏移量有需要一个Closure, 所以就改为了delegate来实现.

  5. 使segmentView浮动: 通过监控子控制器的scrollView的滚动偏移量(contentOffset.y), 根据偏移量的改变量来同步的调整segmentView和headView的frame, 当segmentView同步"滚动"到顶部的时候, 通过判断scrollView的滚动偏移量的范围来固定segmentView和headView的frame, 即达到浮动效果

  6. 在segmentView和headView的frame随着scrollView滚动到下方原始位置的时候, 通过判断scrollView的滚动偏移量的范围来固定segmentView和headView的frame,

实现部分 , 代码量不大

1 属性部分, 这些懒加载方法里面设置了他们的相关属性, 其中的具体设置和动手写一个快速集成网易新闻,腾讯视频,头条首页的ScrollPageView,显示滚动视图这里面介绍的使用相同, 这里就不在赘述了

属性部分.png

注意设置这些控件的frame的时候使用到了一些常量, 请根据您项目的具体需要改变

常量.png
  1. 设置部分
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "简书个人主页"
        
        // 这个是必要的设置, 如果没有设置导致显示内容不正常, 请尝试设置这个属性
        automaticallyAdjustsScrollViewInsets = false
        
        
        //1. 添加子控制器为PageTableViewController或者继承自他的Controller,
        //   或者你可以参考PageTableViewController他里面的实现自行实现(可以使用UICollectionView)相关的代理和属性 并且设置delegate为self
        
        addChildVcs()
        
        // 2. 先添加contentView
        view.addSubview(contentView)
        // 3. 再添加headView
        view.addSubview(headView)
        // 4. 再添加topView
        view.addSubview(topView)

// 添加子控制器的时候需要设置代理
    func addChildVcs() {
        let vc1 = PageTableViewController()
        
        vc1.delegate = self
        addChildViewController(vc1)
        
        let vc2 = Test1Controller()
        vc2.delegate = self
        addChildViewController(vc2)
}

  1. 子控制器的代理方法实现部分
// MARK:- PageTableViewDelegate - 监控子控制器中的tableview的滚动和更新相关的UI
extension Vc8Controller: PageTableViewDelegate {
    
    // 设置将要显示的tableview的contentOffset.y
    func setupTableViewOffSetYWhenViewWillAppear(scrollView: UIScrollView) {
        
        // 当子控制器的tableview向上滚动很多的时候, 重新设置offY
        if offSetY > -(naviBarHeight + segmentViewHeight) {
            offSetY = -(naviBarHeight + segmentViewHeight)
        }
        print("\\\\\\\\(offSetY)--------------")
        
        scrollView.contentOffset.y = offSetY
    }
    
    // 根据子控制器的scrolView的偏移量来调整UI
    func scrollViewIsScrolling(scrollView: UIScrollView) {
        let deltaY =  scrollView.contentOffset.y - offSetY
        offSetY = scrollView.contentOffset.y
        
        
//        print(offSetY)
        
        if offSetY > -(defaultOffSetY - headViewHeight) {
            // 使滑块停在navigationBar下面
            headView.frame.origin.y = naviBarHeight - headViewHeight
            topView.frame.origin.y = naviBarHeight
            return
        } else if offSetY < -defaultOffSetY {
            
            // 使headView停在navigationBar下面
            headView.frame.origin.y = naviBarHeight
            topView.frame.origin.y = naviBarHeight + headViewHeight
            return
        }
        
        // 这里是让滑块和headView随着上下滚动
        headView.frame.origin.y -= deltaY
        topView.frame.origin.y -= deltaY
    }
    
}


  1. contentView的代理方法实现
// MARK:- ContentViewDelegate
extension Vc8Controller: ContentViewDelegate {
    var segmentView: ScrollSegmentView {
        return topView
    }
    
}
  1. 子控制器部分, 这里比较简单, 只需要实现scrollView的滚动代理方法, 在里面通过代理调用子控制器的代理方法, 通知给父控制器, 然后是在viewWillAppear()的方法中通过代理更新tableView(collectioVew)的contentOffset

注意 /// !!! 不要在viewDidLoad()方法里面设置tableView或者collectionView的偏移量, 在初始化方法中设置偏移量,否则可能导致显示不正常

// 协议方法

// MARK: PageTableViewDelegate
protocol PageTableViewDelegate: class {
    func scrollViewIsScrolling(scrollView: UIScrollView)
    func setupTableViewOffSetYWhenViewWillAppear(scrollView: UIScrollView)
}


初始化

  func setupTableView() {
        tableView = UITableView(frame: self.view.bounds, style: .Plain)
        tableView.delegate = self
        tableView.dataSource = self
        // 设置tableview的内容偏移量

        tableView.contentInset = UIEdgeInsets(top: defaultOffSetY, left: 0, bottom: 0, right: 0)
        
        self.view.addSubview(tableView)
    }
    
    
    /// !!! 不要在viewDidLoad()方法里面设置tableView或者collectionView的偏移量, 在初始化方法中设置偏移量,否则可能导致显示不正常
    
    init() {
        super.init(nibName: nil, bundle: nil)
        setupTableView()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }
    

viewWillAppear

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(true)
        // 通知父控制器重新设置tableView的contentOffset.y
        delegate?.setupTableViewOffSetYWhenViewWillAppear(tableView)
//        print(tableView.contentOffset.y)
    }

UIScrollViewDelegate

// MARK: UIScrollViewDelegate - 监控tableview的滚动, 将改变通知给通知父控制器
extension PageTableViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(scrollView: UIScrollView) {
        delegate?.scrollViewIsScrolling(scrollView)
    }
}



源码地址,已更新, 如果您觉得有帮助,不妨给个star鼓励一下,欢迎关注, 欢迎交流


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,738评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,377评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,774评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,032评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,015评论 5 361
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,239评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,724评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,374评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,508评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,410评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,457评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,132评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,733评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,804评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,022评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,515评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,116评论 2 341

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,983评论 4 60
  • 昨天去爬慕田峪长城。说实话每次出门之前总是不想动不想去,哎不过朋友邀请动身,但是去了又觉得不虚此行。不知道是自己...
    memetry阅读 586评论 0 0
  • 这是我爱上你的第四个月,也是我们再也没有见面的第四个月。人生也许真的是很奇怪的东西,比如说我是在离开你的那些天才爱...
    海大宝阅读 247评论 0 0
  • 这是四年前 一篇我写给妹妹的文章 过去这么久了 再读 还是很感动 世界上最爱自己的两个人 曾经现在将来一直为我们做...
    远方君阅读 330评论 0 1
  • 还清楚记得第一次用Flex实现了垂直居中的时候,我那各种unbelievable的心情,然后就深深喜欢上了这个好玩...
    半生不熟_阅读 2,865评论 1 15