如何像在 iMessage 群聊中一样在导航栏中放置集合视图

Posted

技术标签:

【中文标题】如何像在 iMessage 群聊中一样在导航栏中放置集合视图【英文标题】:How to put a collection view in the navigation bar like in iMessage group chats 【发布时间】:2016-12-04 21:52:00 【问题描述】:

我正在尝试在导航栏中放置一个集合视图,如 iMessage 群聊中所见,其中所有成员的姓名首字母都在导航栏中的圆圈中。

我在 SO 上找到了答案 here,我尽力将其转换为 ios10/Swift 3,但集合视图单元格未正确显示在导航栏中。这是我的代码:

import UIKit


weak var collectionView: UICollectionView?

class ChatController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource 

override func viewDidLoad() 
    super.viewDidLoad()

    let layout = UICollectionViewFlowLayout()
    let collectionView = UICollectionView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(300), height: CGFloat(80)), collectionViewLayout: layout)
    collectionView.backgroundColor = UIColor.clear
    navigationItem.titleView? = collectionView
    collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
    collectionView.delegate? = self
    collectionView.dataSource? = self
    view.addSubview(collectionView)
    collectionView.reloadData()



func numberOfSections(in collectionView: UICollectionView) -> Int 
    return 1


func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    return 5


func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = (collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) )
    cell.backgroundColor = UIColor.orange
    cell.layer.cornerRadius = 24
    return cell


func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 
    return CGSize(width: CGFloat(50), height: CGFloat(50))



还有导航栏类:

import Foundation
import UIKit



class NavigationBar: UINavigationBar 

var chatController: ChatController?

override func sizeThatFits(_ size: CGSize) -> CGSize 
    return CGSize(width: CGFloat(self.superview!.bounds.size.width), height: CGFloat(80))


func setFrame(frame: CGRect) 
    var f = frame
    f.size.height = 80
    super.frame = f




看起来集合视图单元格正在显示,但它们位于导航栏下方而不是导航栏内部(见下图)。如果我隐藏导航栏,单元格会转到视图的顶部,但我希望将它们放在导航栏中。

这是我在应用程序委托中的 UI 代码,不确定我是否在这里犯了新手错误:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
    // Override point for customization after application launch.

    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()
    window?.rootViewController = UINavigationController(rootViewController: ChatController())

    return true

我正在以编程方式执行此操作(没有情节提要)。谁能看出我哪里出错了?

【问题讨论】:

调用view.addSubview(collectionView) collectionView.reloadData() 作为viewDidLoad 的最后一次调用。在添加导航栏的位置发布代码。 谢谢,我忘了添加子视图。不幸的是,这并不能解决问题!仍然只是一个普通的视图控制器/导航栏。 展示如何添加 ChatController。 将集合视图添加到导航栏中的标题视图 原谅我,因为我很新,这是我第一次以编程方式做一个界面,但我不是用这行 navigationItem.titleView = collectionView 【参考方案1】:

这是我提出的解决方案

来自Apple

如果您想在导航栏中显示自定义视图,则必须先将这些视图包装在 UIBarButtonItem 对象中,然后再将它们添加到导航项。

有关导航项如何与导航控制器、自定义视图控制器和导航栏协同工作以显示其内容的信息,请参阅View Controller Programming Guide for iOS。

weak var collectionView: UICollectionView?
override func viewDidLoad() 
    super.viewDidLoad()
    let navigationitem = UINavigationItem(title: "")    //creates a new item with no title
    navigationitem.titleView = collectionView //your collectionview here to display as a view instead of the title that is usually there
    self.navigationController?.navigationBar.items = [navigationitem] //adds the navigation item to the navigationbar

从文档中我相信这应该可行。请记住让您的集合视图单元格足够小以适合导航栏。如果它不起作用,请告诉我,也许我明天可以解决一些问题。

【讨论】:

这真的很有趣,我没有意识到你必须将视图包装在一个条形按钮项目中,我会做更多的阅读......虽然很有趣,因为我在我的 OP 中引用的示例( obj-c 中关于 SO 的另一个答案没有这样做就可以正常工作。我尝试了您的代码,但不幸的是发生了崩溃,这是错误:*** 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无法调用 setItems:动画:直接在控制器管理的 UINavigationBar 上。” 谷歌该错误,您会立即找到解决方案。 你能分享一下哪个结果对你有用吗?我搜索了错误并在结果的第一页尝试了解决方案,但问题仍然存在。

以上是关于如何像在 iMessage 群聊中一样在导航栏中放置集合视图的主要内容,如果未能解决你的问题,请参考以下文章

如何像在 iOS 中为 iMessage 一样为 Android 创建贴纸包?

如何使用电报机器人 api 在群聊中接收消息

如何在 IOS 的 XMPP 群聊中接收通知

TextField 没有被键盘顺利推上,就像在 Whatsapp 和环聊中一样

iOS 10 iMessage 应用扩展:如何计算超高导航栏的高度

使用 XMPP 在群聊中传输文件