仿微博 iOS 客户端 TabBar 中间按钮

原文连接:仿微博 iOS 客户端 TabBar 中间按钮
项目源码:模仿微博客户端项目源码ios

我在模仿微博 iOS 客户端。如图:git

微博客户端 TabBar 中间按钮和其余按钮不同,一个是样式不同,一个是点击事件不同。github

思路

第一个想法实际上是建一个 UITabBarController 的子类,自定义 TabBar 的样式,可是由于还没学习过,因此此次但愿另找一个办法。swift

第二个想法是用一个 button 覆盖 TabBar 中间按钮。无非就是在代码里新建一个UIButton,用CGRectMake()定位。ide

一个错误的尝试

有了上面的思路,我就在首页的 ViewController 中的viewDidLoad()方法中添加了以下代码:post

//100px 高宽随便设置用来测试的。
    let postBtn = UIButton()
    postBtn.frame = CGRectMake(self.view.frame.width/2 - 50, self.view.frame.height - 100, 100, 100)
    postBtn.setBackgroundImage(UIImage(named: "post_btn"), forState: .Normal)
    self.view.addSubview(postBtn)

结果如图:学习

两个问题测试

  • 按钮被什么东西挡住了?动画

  • 这个按钮添加在首页的 View 里面,因此只有首页有,其余 tab 怎么办?每一个 tab 写一个吗?spa

问题一

在 Tabbed Application,底部始终有一个在最上层的 TabBar。每个 tab 页面的 view 都在 TabBar 下面,因此在 tab 页面的 view 中在 TabBar 所在的位置添加子 subview,subview 会被盖住。

因此思路二行不通了吗?

问题二

重复一点代码倒没什么,不过有没有办法避免呢?

解决方案

我发现做为 Initial View Controller 的这个 Tab Bar View Controller 也能够添加一个自定义的 ViewController。

因而我新建了一个 UITabBarController 的子类。在viewDidLoad()中添加了 button。下面的代码是调整过 button 大小位置后的最终代码。

//  TabBarViewController.swift
import UIKit

class TabBarViewController: UITabBarController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        //  初始化一些要用到的参数
        let WINDOW_HEIGHT = self.view.frame.height
        let TAB_HEIGHT = self.tabBar.frame.height
        let GRID_WIDTH = self.view.frame.width / 5
        let MARGIN_X = CGFloat(2)
        let MARGIN_Y = CGFloat(5)
        let BTN_WIDTH = TAB_HEIGHT - MARGIN_X * 2
        let BTN_HEIGHT = TAB_HEIGHT - MARGIN_Y * 2
        
        //  遮罩层,用于遮挡本来的 TabBarItem
        let modalView = UIView()
        modalView.frame = CGRectMake(GRID_WIDTH * 2, WINDOW_HEIGHT - TAB_HEIGHT, GRID_WIDTH, TAB_HEIGHT)
        self.view.addSubview(modalView)
        
        //  添加自定义按钮
        let postBtn = UIButton()
        postBtn.frame = CGRectMake(GRID_WIDTH * 2 + (GRID_WIDTH - BTN_WIDTH) / 2, WINDOW_HEIGHT - TAB_HEIGHT + MARGIN_Y, BTN_WIDTH, BTN_HEIGHT)
        postBtn.setBackgroundImage(UIImage(named: "post_btn"), forState: .Normal)
        self.view.addSubview(postBtn)
        
        //  给按钮添加事件
        postBtn.addTarget(self, action: "postButtonClicked:", forControlEvents: .TouchUpInside)
    }
}

效果如图:

解释

对于问题一

由于是直接在 TabBarController 的 view 上添加 subview,因此按钮正常显示。

对于问题二

由于 TabBar 是全部 tab 页面公用的,因此不用在每一个页面单独添加按钮。

遮罩层的做用

由于自定义按钮的大小没有覆盖 TabBar 中间 item 的大小,因此点击边缘部分会进入对应的 tab 页面。而微博客户端这个按钮点击后,应该是出现以下页面,而非进入 tab 页。因此用遮罩层挡住那个 TabBar item。

自定义按钮的点击事件

这个加号按钮点击完以后应该是出现一个半透明视图,包含一些按钮。因此我在最后给按钮添加了一个点击事件,负责完成显示新视图及其中的动画。

若是对这个半透明视图和其中动画的实现有兴趣,能够到我 github 下载源码看看。由于都是最基本的 Animation,因此可能不会单独写一篇分享。

模拟微博客户端 github 仓库

我的以为值得注意的是,个人解决方案是:这个半透明视图在第一次出现以后就保存在 TabBarViewController 的类成员变量里,以后的关闭和再显示只是将视图的 alpha 值在 0 和 1 之间切换。

说不定也会总结一次。由于实现过程当中踩到一些跟 Animation 有关的坑,好比有些属性变换是当即执行的,不能用动画渐变实现

基本的 Animation 知识,建议去看 @林永坚Jake 在慕课网发布的 iOS-动画入门iOS-动画进阶

相关文章
相关标签/搜索