UISplitViewController - 用侧边栏切换图标替换后 V 形图标

Posted

技术标签:

【中文标题】UISplitViewController - 用侧边栏切换图标替换后 V 形图标【英文标题】:UISplitViewController - replace back-chevron icon with a sidebar toggle icon in portrait 【发布时间】:2022-01-12 19:38:51 【问题描述】:

我正在开发一个使用 UISplitViewController 的 iPadOS 应用程序。到目前为止,我一直在使用旧 API 并手动处理所有内容(包括 displayModeButtonItem)。现在我想迁移到更新的“列样式”API (super.init(style: .doubleColumn)。我遇到了一些 UI 问题,但我设法通过一些变通方法解决了这些问题,但现在我在一个找不到任何解决方案的问题上被阻止:

我想利用ios14的UISplitViewController的所有内置机制,所以我将presentsWithGesture属性设置为true。因此,我得到横向的侧边栏切换图标(这正是我想要的方式),但在纵向我得到一个带有“back”标题的“back-chevron icon”。有没有办法强制向两个方向显示侧边栏切换图标?

【问题讨论】:

大约 16 个月前(iPadOS 14 处于测试阶段)我尝试了类似的方法。似乎(至少)使用主要 辅助 VC 的 iPad 上的默认行为是在从横向旋转到纵向时“隐藏”或关闭 PrimaryVC。我的first 解决方法是标记事物并强制Primary 无论如何都保持可见。这让事情变得太复杂而无法维护,所以我朝着一个非常不同的方向前进——只有一个辅助(和紧凑)VC 并推出我自己的主。在您的情况下,这至少会在所有方向上为您提供相同的导航栏。我知道不是最佳的。 @dfd 实际上,我希望侧边栏以纵向关闭并在此方向上作为叠加层(而不是另一列)。我唯一的问题是纵向按钮的外观。在我的应用程序上下文中,对于应用程序用户来说,“back chevron”不太清楚。这可能对其他应用有意义,但对我的应用没有意义,所以我想在两个方向上都显示侧边栏按钮。 那么你可能需要做两件事。 (1) 确定 iPad 上的方向何时改变。不要忘记,当您的应用程序处于全屏状态时,它会始终显示常规尺寸类别,而当它处于分屏 - 多任务时 - 它可能使用紧凑型尺寸等级取决于屏幕尺寸、方向和您的应用使用的区域大小。 (2) 确定正在显示哪个导航栏 - 如果有的话,因为在显示 Compact VC 时 UISplitViewController 默认不提供。 IIRC,在显示主 VC 时,会显示两个导航栏。根据需要提供您自己的导航栏按钮。 @dfd 任何想法我应该如何提供导航栏按钮?我尝试这样设置:'self.viewController(for:secondary)?.navigationItem.leftBarButtonItem = UIBarButtonItem(...',但这根本没有效果。标准的后退按钮是可见的,但我的自定义按钮不是。 【参考方案1】:

我设置了一个示例项目,但我没有得到你的行为。我想这是因为我们在设置 UISplitViewController 时做的事情不同。

首先,非常感谢 Matt Neuburg(@matt 在 SO 上)的两部分文章。 (part one here) 这为我的代码提供了一些重大更改。

基本上,我不再将UISplitViewController 设置为场景中的根视图。相反,我根本不碰SceneDelegate,而是使用默认的ViewController

let primaryVC = PrimaryVC()
let secondaryVC = SecondaryVC()
let compactVC = CompactVC()

override func viewDidLoad() 
    super.viewDidLoad()
    let split = UISplitViewController(style: .doubleColumn)
    self.addChild(split)
    self.view.addSubview(split.view)
    split.view.frame = self.view.bounds
    split.presentsWithGesture = true
    split.preferredSplitBehavior = .tile
    split.view.autoresizingMask = [.flexibleHeight, .flexibleWidth]
    split.didMove(toParent: self)
    split.setViewController(primaryVC, for: .primary)
    split.setViewController(secondaryVC, for: .secondary)
    split.setViewController(compactVC, for: .compact)

当我这样做时,我得到一个“sidebar.left”按钮,而 Chevron 没有“返回”按钮。我正在使用 Xcode 13.1,并在 iPadOS 14.0 和 15.1 的目标上进行了尝试。

如果您需要添加/替换条形按钮,我要做的是:

var barBtnSidebarLeft = UIBarButtonItem(image: UIImage(systemName:"sidebar.left"), style: .plain, target: self, action: #selector(leftSidebarTapped)) navigationItem.leftBarButtonItem = barBtnSidebarLeft

但请注意,如果您这样做,您将获得 两个 侧边栏按钮!关于栏按钮,还有一点需要注意 - 虽然UISplitViewController 默认为 Primary 和 Secondary 提供导航栏,但它为 Compact。 (坦率地说,我不认为在紧凑的情况下拥有一个好习惯。)

最后,阅读我提供的链接。它真正开始使用UISplitViewControllerDelegate 来帮助您正确传递场景状态值。 (我更喜欢称它为场景状态而不是应用状态,因为 iPad 可以有多个应用窗口。)

编辑

最后一个想法。 IIRC 你可以这样做:

presentsWithGesture 设置为`false 在两个视图控制器中随意放置您自己的条形按钮 手动(通过委托函数?)打开和关闭主视图控制器

【讨论】:

以上是关于UISplitViewController - 用侧边栏切换图标替换后 V 形图标的主要内容,如果未能解决你的问题,请参考以下文章

Ipad UISplitViewController

UISplitViewController - 双列样式不起作用

UISplitViewController 一致分隔符

UISplitViewController - 并排或纵向叠加

在 UIViewControllers 和 UISplitViewController 之间导航 [关闭]

将 UIToolBar 放在 UISplitViewController 上方?