【问题标题】:Constraints reactivate when contextMenu appears出现 contextMenu 时重新激活约束
【发布时间】:2021-06-27 10:51:11
【问题描述】:

我正在使用 UIContextMenuConfiguration 对集合视图单元格进行操作。一切都按预期工作,但是如果我的单元格从笔尖(取消)激活了约束,它会在长按时刷新。

为了演示这个问题,我创建了一个新项目,故事板中有一个collectionView。集合视图中的自定义单元格有一个带有两个约束的标签,一个约束将其固定在单元格的底部(最初处于活动状态),另一个将其对齐在中心(最初禁用)。

这是我的代码,

import UIKit

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
        cell.configure()
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
        return UIContextMenuConfiguration.init(identifier: nil, previewProvider: nil) { (array) -> UIMenu? in
            return UIMenu(title: "Hello", image: nil, identifier: nil, options: .destructive, children: [UIAction(title: "Share", image: UIImage(systemName: "tray.and.arrow.up"), identifier: nil) { _ in
                print("HelloWorld!")
              }])
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: 265, height: 128)
    }
}

class CollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var bottomConstraint: NSLayoutConstraint!
    @IBOutlet weak var centerConstraint: NSLayoutConstraint!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    func configure() {
        bottomConstraint.isActive = false
        centerConstraint.isActive = true
    }
}

【问题讨论】:

  • 您需要提供更多细节。用你的代码快速测试,我没有看到你得到的结果。
  • 哦,谢谢告知,现在信息够了吗?
  • 您是否想要在显示上下文菜单时将标签放到底部?
  • 不,我不想(我希望它保持在上下文菜单演示之前的状态)但是当显示上下文菜单时,框架似乎隐式地重新激活了我已取消激活的约束出于某种原因。
  • 我认为你在用这种方法自找麻烦。在 Storyboard 上设置 .isActive 创建的约束通常不是一个好主意。你想要做什么?

标签: ios swift uicollectionview autolayout uicontextmenuconfiguration


【解决方案1】:

该问题似乎与以下直接相关:

  • 在 Storyboard 中创建了两个相互冲突的约束
  • 将一个约束设置为未安装
  • 取消激活 已安装 约束并激活 未安装 约束

当用previewProvider: nil 初始化UIContextMenuConfiguration - 这告诉 UIKit自动生成预览视图 - 约束的“已安装”状态被重置。

绕过它的一种方法:

不要将中心约束标记为“未安装”,而是将其优先级设为 998,并将底部约束的优先级设为 999(这将防止 IB 抱怨)。

然后您可以将您的 configure() 功能保留为:

func configure() {
    bottomConstraint.isActive = false
    centerConstraint.isActive = true
}

标签的 centerY 约束将在单元格和上下文菜单的预览中保持活动状态。

但是,如果您希望预览视图看起来与单元格不同,那么最好的选择(并且可能是更好的方法)是使用自定义 @ 987654325@.

【讨论】:

  • 当用previewProvider: nil 初始化UIContextMenuConfiguration 时——告诉UIKit 自动生成预览视图——约束的“已安装”状态被重置。你能详细说明一下吗,我的意思是 UIKit 如何保持一切就位,但只重置约束的“已安装”状态。此外,您提出的解决方案与我想要的影响略有不同。 configure 函数的功能不会对上下文菜单预览产生任何影响,并且自动布局将尝试同时满足这两个约束,从而导致标签放大。
  • 基本上,您对冲突约束的假设有点误导,因为约束可能不冲突,但它们旨在以相互排斥的方式激活。
  • 约束的“已安装”状态被重置 ...这是来自观察。使用Debug View Hierarchy,我们可以很容易地看到 UIKit 正在使用 Storyboard-set 约束的“已安装”状态。 “冲突的约束”我的意思是如果它们都是活动的 - 你的代码是否在某个时候将它们设置为互斥并不重要。
  • 我曾问过 “你希望标签在显示上下文菜单时降到底部吗?” 你说不......但听起来像你 确实希望预览看起来与单元格不同。在这种情况下,您最好使用自己的previewProvider——或者,至少,不要尝试使用未安装的约束。
  • 哦,不。很抱歉造成混乱,非常感谢您试图帮助我。基本上,我正在寻找一个看起来与单元格完全相同的上下文菜单。但是,单元格可以出现在不同的状态(不同的安装约束集)。关于“冲突约束”的事情,我想强调一个事实,即在我们当前的示例中,将它们设置为 active 会使视图处于不同的状态,而不是显示冲突约束警告,因为 UIKit 会通过增加标签的高度(不是预期的输出)同时满足两者
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-18
  • 2021-11-18
  • 1970-01-01
  • 2018-04-20
  • 1970-01-01
  • 2011-08-26
相关资源
最近更新 更多