弹出房间界面

功能说明

  • 区分弹出秀场&普通房间
  • 如果用户是秀场直播,那么弹出秀场房间界面
  • 如果用户是电脑直播,那么弹出普通房间界面
  • 秀场界面弹出
  • 直接以Model方式,从底部弹出即可
  • 普通界面弹出
  • 将界面PUSH出来
  • 注意:
  • 1> 界面push之后,不能再显示UITabbar(默认依然在下面)
  • 2> 弹出的界面需要因此导航栏,但是首页导航栏依然正常展示
  • 3> 弹出完成后,实现全屏Pop,手势左滑退出控制器

效果展示

  • 效果展示

弹出功能实现

  • 监听UICollectionView的Cell点击
  • 在BaseAnchorViewController中实现对应的代码方法监听即可
  • 创建两个房间的控制器(房间不同,需要创建两个控制器)
  • RoomNormalViewController(普通房间控制器)
  • RoomShowViewController(秀场房间控制器)
  • 在监听Cell点击方法中执行弹出逻辑
  • 取出对应的AnchorModel对象
  • 根据anchor中的isVertical属性,判断弹出方式
  • 0 : 电脑直播
  • 1 : 手机直播
  • 根据方式,弹出控制器即可
    1.     func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    2.         // 1.取出主播信息
    3.         let anchor = baseVM.anchorGroups[indexPath.section].anchors[indexPath.item]
    4. 
    5.         // 2.判断是手机直播&电脑直播
    6.         anchor.isVertical == 1 ? presentShowLiveVM(anchor: anchor) : pushNormalLiveVM(anchor: anchor)
    7.     }
    8. 
    9.     private func presentShowLiveVM(anchor : AnchorModel) {
    10.         // 创建控制器
    11.         let showVC = RoomShowViewController()
    12. 
    13.         // 弹出
    14.         present(showVC, animated: true, completion: nil)
    15.     }
    16. 
    17.     private func pushNormalLiveVM(anchor : AnchorModel) {
    18.         // 1.创建控制器
    19.         let normalVC = RoomNormalViewController()
    20. 
    21.         // 2.push
    22.         navigationController?.pushViewController(normalVC, animated: true)
    23.     }
     
    显示&隐藏UINavigationBar
    • 显示&隐藏UINavigationBar使用下面方法即可 
      
    • navigationController.setNavigationBarHidden(true, animated: true)
    • true : 隐藏
    • false : 显示
    • 在RoomNormalViewController的系统回调方法中分别执行对应的方法 
      
    • viewWillAppear:执行隐藏方法
    • viewWillDisappear:执行显示方法
    • 注意: 
      
    • 这样做会产生一个问题,就是原来系统的左边缘的滑动退出控制器手势无效了
    • 一旦我们隐藏了导航栏,那么该手势就会自动失效
    • 如果希望继续显示,则需要按照下面的步骤 
        
    • 1> navigationController?.interactivePopGestureRecognizer?.delegate = self
    • 2> navigationController?.interactivePopGestureRecognizer?.isEnabled = true
    • 代码如下:
    1. class RoomNormalViewController: UIViewController, UIGestureRecognizerDelegate {
    2. 
    3.     override func viewDidLoad() {
    4.         super.viewDidLoad()
    5. 
    6.         view.backgroundColor = UIColor.purple
    7. 
    8.         // 保留Pop手势
    9.         navigationController?.interactivePopGestureRecognizer?.delegate = self
    10.         navigationController?.interactivePopGestureRecognizer?.isEnabled = true
    11.     }
    12. 
    13. 
    14.     override func viewWillAppear(_ animated: Bool) {
    15.         super.viewWillAppear(animated)
    16. 
    17.         navigationController?.setNavigationBarHidden(true, animated: true)
    18.     }
    19. 
    20.     override func viewWillDisappear(_ animated: Bool) {
    21.         super.viewWillDisappear(animated)
    22. 
    23.         navigationController?.setNavigationBarHidden(false, animated: true)
    24.     }
    25. }
     
    隐藏UITabbar
    • 在push时隐藏UITabbar非常简答 
      
    • 因为系统已经提供了一个控制器的属性
    • 设置控制器的hidesBottomBarWhenPushed为true即可
    • 注意:所有的push控制器其实都需要因此,那么怎么办呢? 
      
    • 方案一:抽取统一的父类
    • 方案二:截取push过程,在push的那一刻,设置控制器的属性
    • 该位置采取方案二:更为简单 
      
    • 如何截取?
    • 自定义UINavigationController
    • 重写
    pushViewController(_ viewController: UIViewController, animated: Bool)
    • 方法
    • 将之前的UINavigationController改成自定义的
    • 代码如下:
    1. class CustomNavigationController: UINavigationController {
    2. 
    3.     override func viewDidLoad() {
    4.         super.viewDidLoad()
    5.     }
    6. 
    7.     override func pushViewController(_ viewController: UIViewController, animated: Bool) {
    8.         viewController.hidesBottomBarWhenPushed = true
    9.         super.pushViewController(viewController, animated: animated)
    10.     }
    11. }


    添加全屏Pop手势

    思路分析:添加全屏Pop手势一直以来都有两种实现思路
    • 方式一:自己在Push出来的View中添加UIPanGestureRecognizer手势
    • 添加手势,监听手势滑动
    • 随着手势滑动,逐渐退出控制器的View
    • 优点:最容易想到,使用自定义专场即可实现
    • 缺点:较为麻烦
    • 方式二:利用运行时机制,获取系统的Pop手势target&action
    • 获取系统的手势监听View
    • 获取系统的手势target&action
    • 创建自己的手势,添加事件监听时,使用上步中的target&action
    • 将手势,添加到系统手势监听的View中
    • 优点:实现非常简单
    • 缺点:需要用到运行时机制,且不容易想到

    实现方案:方案二(简单)

    • 该位置我们采用第二种实现方案,也是我个人常用的实现方案
    • 首先,我们已经知道系统是有一个左滑手势
    • 该左滑手势只能在左边缘滑动才会生效
    • 但是该手势的View&target&action系统已经创建好了
    • 我们可以自己创建一个手势,但是利用系统的View&target&action
    • 问题?
    • 1> 如果获取系统手势的View?
    • 比如简单,因为可以直接获取interactivePopGestureRecognizer手势
    • interactivePopGestureRecognizer.view即可获得
    • 2> 如果获取target&action
    • 该方式较为麻烦,需要使用KVC
    • 通过某一些Key来获取可接
    • 3> 通过哪些key呢?
    • 需要用运行时,遍历所有的属性找到
      • 代码分析:
      1. class CustomNavigationController: UINavigationController {
      2. 
      3.     override func viewDidLoad() {
      4.         super.viewDidLoad()
      5. 
      6.         // 1.取出手势&view
      7.         guard let gesture = interactivePopGestureRecognizer else { return }
      8.         gesture.isEnabled = false
      9.         let gestureView = gesture.view
      10. 
      11.         // 2.获取所有的target
      12.         let target = (gesture.value(forKey: "_targets") as? [NSObject])?.first
      13.         guard let transition = target?.value(forKey: "_target") else { return }
      14.         let action = Selector(("handleNavigationTransition:"))
      15. 
      16.         // 3.创建新的手势
      17.         let popGes = UIPanGestureRecognizer()
      18.         popGes.maximumNumberOfTouches = 1
      19.         gestureView?.addGestureRecognizer(popGes)
      20.         popGes.addTarget(transition, action: action)
      21.     }
      22. 
      23.     override func pushViewController(_ viewController: UIViewController, animated: Bool) {
      24.         viewController.hidesBottomBarWhenPushed = true
      25.         super.pushViewController(viewController, animated: animated)
      26.     }
      27. }