如何让 UIButton 按下以在 Swift 中的 UICollectionViewCell 中工作?
How do I get a UIButton press to work in a UICollectionViewCell in Swift?
所以这是 Swift 中的一个 tvOS 项目。我有一个自定义 UICollectionViewCell,其中一个按钮作为其子视图之一。我向按钮添加了一个目标以允许它解释点击。这是相关代码的简化版本
class CustomCell: UICollectionViewCell {
var button:UIButton!
override init(frame: CGRect) {
super.init(frame: frame)
button = UIButton(...) // Button is initialized with a frame
button.userInteractionEnabled = true
button.enabled = true
button.addTarget(self, action: "pressed:", forControlEvents: .PrimaryActionTriggered)
contentView.addSubview(button)
}
func pressed(sender: UIButton!) {
print("button pressed!")
}
}
出于某种原因,它从未打印出我的消息。我尝试将 'pressedEnded' 添加到单元格 class 以查看它是否有任何内容并被调用
func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
// If I put a breakpoint here it's reached
}
有什么建议吗?我在模拟器里运行按钮可以得到焦点,所以不知道为什么不能得到任何事件
所以,我想出了解决这个问题的方法,尽管它在某种程度上是一种解决方法。基本上对于 UICollectionView
我需要确保单元格的 不能 获得焦点。
接下来我在 CustomCell
之前有 didUpdateFocusInContext
。当 单元格 时,这实际上是为按钮设置动画,但当我检查按钮时,它从未获得焦点。我猜这是拦截它。所以我从 CustomCell
中删除了该函数,而是在我的文件底部添加了该函数作为 UIButton 的扩展。
这也可以通过创建 UIButton
的子类并改用它来完成,但这会减少代码(这可能是理想的方式)。所以完整的代码看起来像:
class MyCollection: UICollectionView, UICollectionViewDelegate {
// Need initializer functions as well as functions for creating CustomCell's. They're omitted because they're not relevant to the answer
func collectionView(collectionView: UICollectionView, canFocusItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
}
class CustomCell: UICollectionViewCell {
var button:UIButton!
override init(frame: CGRect) {
super.init(frame: frame)
button = UIButton(...) // Button is initialized with a frame
button.userInteractionEnabled = true
button.enabled = true
button.addTarget(self, action: "pressed:", forControlEvents: .PrimaryActionTriggered)
self.addSubview(button)
}
func pressed(sender: UIButton!) {
print("button pressed!")
}
}
extension UIButton {
override public func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator)
if self.superview is CustomCell { // This ensures that all UIButtons aren't affected
if context.nextFocusedView == self {
// Perform actions for when UIButton is focused
}else {
// Perform actions for when UIButton loses focus
}
}
}
}
以上答案是正确的,如果您使用自定义 UICollectionViewCell
您也可以在其子类中针对特定单元格执行此操作:
override func canBecomeFocused() -> Bool {
return false
}
似乎 UICollectionViewCell 被清晰的视图自动覆盖,捕捉点击。
对我们来说,只需调用 bringSubview(toFront: checkButton) 即可。现在 checkButton touchUpInside 动作被调用了。
import UIKit
class SerieItemCollectionViewCell: UICollectionViewCell {
var checked : (()->())?
static let reuseIdentifier = "SerieItemCollectionViewCell"
@IBOutlet weak var checkButton: UIButton!
@IBOutlet var imageView: UIImageView!
override func layoutSubviews() {
super.layoutSubviews()
bringSubview(toFront: checkButton)
}
@IBAction func buttonClicked(_ sender: Any) {
checked?()
print("Hello")
}
}
确保为 UICollectionViewCell 选中启用用户交互复选框。
所以这是 Swift 中的一个 tvOS 项目。我有一个自定义 UICollectionViewCell,其中一个按钮作为其子视图之一。我向按钮添加了一个目标以允许它解释点击。这是相关代码的简化版本
class CustomCell: UICollectionViewCell {
var button:UIButton!
override init(frame: CGRect) {
super.init(frame: frame)
button = UIButton(...) // Button is initialized with a frame
button.userInteractionEnabled = true
button.enabled = true
button.addTarget(self, action: "pressed:", forControlEvents: .PrimaryActionTriggered)
contentView.addSubview(button)
}
func pressed(sender: UIButton!) {
print("button pressed!")
}
}
出于某种原因,它从未打印出我的消息。我尝试将 'pressedEnded' 添加到单元格 class 以查看它是否有任何内容并被调用
func pressesEnded(presses: Set<UIPress>, withEvent event: UIPressesEvent?) {
// If I put a breakpoint here it's reached
}
有什么建议吗?我在模拟器里运行按钮可以得到焦点,所以不知道为什么不能得到任何事件
所以,我想出了解决这个问题的方法,尽管它在某种程度上是一种解决方法。基本上对于 UICollectionView
我需要确保单元格的 不能 获得焦点。
接下来我在 CustomCell
之前有 didUpdateFocusInContext
。当 单元格 时,这实际上是为按钮设置动画,但当我检查按钮时,它从未获得焦点。我猜这是拦截它。所以我从 CustomCell
中删除了该函数,而是在我的文件底部添加了该函数作为 UIButton 的扩展。
这也可以通过创建 UIButton
的子类并改用它来完成,但这会减少代码(这可能是理想的方式)。所以完整的代码看起来像:
class MyCollection: UICollectionView, UICollectionViewDelegate {
// Need initializer functions as well as functions for creating CustomCell's. They're omitted because they're not relevant to the answer
func collectionView(collectionView: UICollectionView, canFocusItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
}
class CustomCell: UICollectionViewCell {
var button:UIButton!
override init(frame: CGRect) {
super.init(frame: frame)
button = UIButton(...) // Button is initialized with a frame
button.userInteractionEnabled = true
button.enabled = true
button.addTarget(self, action: "pressed:", forControlEvents: .PrimaryActionTriggered)
self.addSubview(button)
}
func pressed(sender: UIButton!) {
print("button pressed!")
}
}
extension UIButton {
override public func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocusInContext(context, withAnimationCoordinator: coordinator)
if self.superview is CustomCell { // This ensures that all UIButtons aren't affected
if context.nextFocusedView == self {
// Perform actions for when UIButton is focused
}else {
// Perform actions for when UIButton loses focus
}
}
}
}
以上答案是正确的,如果您使用自定义 UICollectionViewCell
您也可以在其子类中针对特定单元格执行此操作:
override func canBecomeFocused() -> Bool {
return false
}
似乎 UICollectionViewCell 被清晰的视图自动覆盖,捕捉点击。
对我们来说,只需调用 bringSubview(toFront: checkButton) 即可。现在 checkButton touchUpInside 动作被调用了。
import UIKit
class SerieItemCollectionViewCell: UICollectionViewCell {
var checked : (()->())?
static let reuseIdentifier = "SerieItemCollectionViewCell"
@IBOutlet weak var checkButton: UIButton!
@IBOutlet var imageView: UIImageView!
override func layoutSubviews() {
super.layoutSubviews()
bringSubview(toFront: checkButton)
}
@IBAction func buttonClicked(_ sender: Any) {
checked?()
print("Hello")
}
}
确保为 UICollectionViewCell 选中启用用户交互复选框。