实现 instagram 底部弹出菜单的一个例子(模拟 instagram 系列)

前端之家收集整理的这篇文章主要介绍了实现 instagram 底部弹出菜单的一个例子(模拟 instagram 系列)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

原文链接实现 instagram 底部弹出菜单的一个例子(模拟 instagram 系列)
模拟 instagram 项目源码:github 仓库:模拟 instagram
聊胜于无,最近有点低潮期的感觉,但是得坚持下去。写不动代码了,所以写一篇简单的总结。

目标和成果

instagram 截图如下:

成果如下:

要实现的内容

  1. 黑色半透明遮罩层

  2. 弹出动画

  3. 点击取消按钮或者背景菜单收回

思路

应该是有一种跟 UIPresentationController 有关的解决方法,但是我还不会,所以这次不用。

之前在模拟微博的项目里也用到了弹出层,所以我想这次也义勇和上次同样的方式,在 TabBarController 里面添加 subview。

但有两点不同:

  1. 上次是点击 tabBarItem 来执行弹出,这次要点击第一个 tab 页里的按钮。怎么样让 TabBarController 得到消息?

  2. 上次弹出的按钮是独立的,这次弹出的菜单和指定的图片有关。所以需要有一个标志记录当前点击的是哪一张图片的 more 按钮。

解决方案 Part.1 创建菜单视图

在 storyboard 拖进一个 ViewController,添加内容,设置好约束。如图:

注意,这个 ViewController 的 root view 要讲背景设置为 黑色、透明度 30%,以模拟遮罩层。

新建一个视图文件 BottomMenuView.swift,继承 UIViewController。修改刚才新建的 ViewController 类为 BottomMenuView,并设置 StoryboardID 为”BottomMenu”。

关联好 IBOutlet 对象和点击事件。

  1. import Foundation
  2. import UIKit
  3.  
  4. class BottomMenuView: UIViewController {
  5.  
  6. @IBOutlet weak var menuBgView: UIView!
  7. @IBOutlet weak var reportBtn: UIButton!
  8. @IBOutlet weak var shareToFacebookBtn: UIButton!
  9. @IBOutlet weak var tweetBtn: UIButton!
  10. @IBOutlet weak var copyURLBtn: UIButton!
  11. @IBOutlet weak var noticeBtn: UIButton!
  12. @IBOutlet weak var dismissBtn: UIButton!
  13. @IBOutlet weak var buttonPanel: UIView!
  14. override func viewDidLoad() {
  15. super.viewDidLoad()
  16. }
  17. override func viewDidAppear(animated: Bool) {
  18. //这里是设置颜色、按钮边框形状。
  19. let maskPathAllCorner = UIBezierPath(roundedRect: noticeBtn.bounds,byRoundingCorners: [.BottomLeft,.BottomRight,.TopLeft,.TopRight],cornerRadii: CGSize(width: 5,height: 5.0))
  20. let maskPathTopCorner = UIBezierPath(roundedRect: noticeBtn.bounds,byRoundingCorners: [.TopLeft,height: 5.0))
  21. let maskPathBottomCorner = UIBezierPath(roundedRect: noticeBtn.bounds,.BottomRight],height: 5.0))
  22. let shapeAllCorner = CAShapeLayer()
  23. shapeAllCorner.path = maskPathAllCorner.CGPath
  24. let shapeTopCorner = CAShapeLayer()
  25. shapeTopCorner.path = maskPathTopCorner.CGPath
  26. let shapeBottomCorner = CAShapeLayer()
  27. shapeBottomCorner.path = maskPathBottomCorner.CGPath
  28. reportBtn.layer.mask = shapeTopCorner
  29. noticeBtn.layer.mask = shapeBottomCorner
  30. dismissBtn.layer.mask = shapeAllCorner
  31. }
  32. @IBAction func bgTapped(sender: UITapGestureRecognizer) {
  33. //给背景 view 添加一个点击事件
  34. //当点击时,让菜单收回
  35. }
  36. @IBAction func dismissBtnPressed(sender: UIButton) {
  37. //点击事件,当点击时,让菜单收回
  38. }
  39. }

在 TabBarViewController.swift 中,修改 viewDidLoad 方法

  1. override func viewDidLoad() {
  2. super.viewDidLoad()
  3. self.tabBar.tintColor = UIColor.whiteColor()
  4. for it in self.tabBar.items! {
  5. it.badgeValue = "100"
  6. }
  7. self.delegate = self
  8. //找到对应视图,并添加为 TabBarView 的子视图。子视图默认 alpha 值为0。
  9. //这样每次只用修改 alpha 值来显示和隐藏,不用重新添加子视图。
  10. self.bottomMenu = self.storyboard?.instantiateViewControllerWithIdentifier("BottomMenu") as! BottomMenuView
  11. self.bottomMenu.modalTransitionStyle = .CoverVertical
  12. self.view.addSubview(self.bottomMenu.view)
  13. self.bottomMenu.view.alpha = 0
  14. }

解决方案 Part.2 给 TabBarController 传递消息

因为 more 按钮在 tab 页的 viewController 里面,我们暂时没办法直接执行 TabBarController 里面的函数,或者对它的 view 进行操作,所以要想个办法发送通知

发送通知当然是用 NSNotification。

发送显示菜单通知

在 firstViewController (即第一个 tab 页的 controller)中添加 more 按钮点击事件,在里面发送一个通知

  1. @IBAction func moreButtonPressed(sender: UIButton) {
  2. NSNotificationCenter.defaultCenter().postNotification(NSNotification(name: "ShowBottomMenu",object: sender.tag))
  3. }

在这个通知里面,object 是当前按钮的 tag 值。这是在每个 cell 初始化的时候,给当前 cell 的每个 button 的 tag 赋值为当前图片的 id,保证之后能够判断每个点击事件来自哪个 cell/图片

发送收回菜单通知

回到 BottomMenuView.swift,在两个点击事件添加发送通知

  1. @IBAction func bgTapped(sender: UITapGestureRecognizer) {
  2. NSNotificationCenter.defaultCenter().postNotification(NSNotification(name: "DismissBottomMenu",object: nil))
  3. }
  4. @IBAction func dismissBtnPressed(sender: UIButton) {
  5. NSNotificationCenter.defaultCenter().postNotification(NSNotification(name: "DismissBottomMenu",object: nil))
  6. }

接收通知

在 TabBarViewController.swift 的 viewDidLoad 方法添加一下两行用于接收通知

  1. NSNotificationCenter.defaultCenter().addObserver(self,selector: "showBottomMenu:",name: "ShowBottomMenu",object: nil)
  2. NSNotificationCenter.defaultCenter().addObserver(self,selector: "dismissBottomMenu:",name: "DismissBottomMenu",object: nil)

经过上面的步骤,TabBarViewController 就能接收到显示或者收回底部菜单通知了。然后我们可以在自定义函数里面编写显示和隐藏的动画。

解决方案 Part.3 显示/收回菜单动画

这部分很简单啦。

  1. func showBottomMenu(notification: NSNotification) {
  2. //获取当前 section id
  3. let tag = notification.object as! Int
  4. print(tag)
  5. self.bottomMenu.buttonPanel.frame.origin.y = self.view.frame.height
  6. UIView.animateWithDuration(0.3) { () -> Void in
  7. self.bottomMenu.view.alpha = 1
  8. self.bottomMenu.buttonPanel.frame.origin.y = self.view.frame.height - self.bottomMenu.buttonPanel.frame.height
  9. }
  10. }
  11.  
  12. func dismissBottomMenu(notification: NSNotification) {
  13. print(notification.object)
  14. UIView.animateWithDuration(0.3) { () -> Void in
  15. self.bottomMenu.view.alpha = 0
  16. self.bottomMenu.buttonPanel.frame.origin.y = self.view.frame.height
  17. }
  18. }

在 showBottomMenu 方法中,获取到了一个 tag 值,这个是留着将来编写对应的菜单按钮点击事件的。

猜你在找的Swift相关文章