使 UILabel 可聚焦和可点击 (tvOS)
Make UILabel focusable and tappable (tvOS)
我正在尝试实现 6 行高描述标签,我希望它是可聚焦的。理想情况下,这意味着扩展 UILabel class 以制作自定义组件。我尝试通过实施 canBecomeFocused
和 didUpdateFocusInContext
但我的 UILabel 似乎没有得到任何关注。
我也尝试用 UIButton 替换 UILabel,但按钮并没有真正针对这类事情进行优化。这也意味着我需要将 buttonType
的焦点从自定义更改为普通......而 buttonType 似乎是只读 属性.
实际上,我希望 Apple 在 Apple TV Movies 应用程序中实现完全相同的文本标签。对于电影描述,他们有一个显示几行文本的文本标签和一个 "more"。聚焦时,它看起来像一个按钮(周围有阴影)并改变了背景颜色。点击时 - 它会打开一个包含整个电影描述的模式 window。
有什么建议吗?或者也许有人已经为 tvOS 实现了这个自定义控件?或者更好的情况 - Apple 有一个组件可以执行此操作,但我遗漏了一些东西。
P.S:欢迎Swift解决方案:)
好的,回答我自己的问题:)
所以看起来有些视图 "focusable" 在 tvOS 上开箱即用,而其他视图必须按照指示才能这样做。
我最终使用了 UITextView
,它有一个 selectable
属性,但默认情况下如果不是这些可聚焦视图之一。必须禁用 TextView
的编辑以使其看起来像 UILabel
。此外,目前存在一个错误,它会阻止您使用 Interface Builder 中的 selectable
属性 但可以从代码中使用。
当然,canBecomeFocused()
和didUpdateFocusInContext
也必须实施。您还需要传递 UIViewController
因为 UITextView
无法呈现模式视图控制器。下面是我最终创建的。
class FocusableText: UITextView {
var data: String?
var parentView: UIViewController?
override func awakeFromNib() {
super.awakeFromNib()
let tap = UITapGestureRecognizer(target: self, action: "tapped:")
tap.allowedPressTypes = [NSNumber(integer: UIPressType.Select.rawValue)]
self.addGestureRecognizer(tap)
}
func tapped(gesture: UITapGestureRecognizer) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let descriptionView = storyboard.instantiateViewControllerWithIdentifier("descriptionView") as? DescriptionViewController {
if let view = parentView {
if let show = show {
descriptionView.descriptionText = self.data
view.modalPresentationStyle = UIModalPresentationStyle.OverFullScreen
view.presentViewController(descriptionView, animated: true, completion: nil)
}
}
}
}
override func canBecomeFocused() -> Bool {
return true
}
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
if context.nextFocusedView == self {
coordinator.addCoordinatedAnimations({ () -> Void in
self.layer.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.2).CGColor
}, completion: nil)
} else if context.previouslyFocusedView == self {
coordinator.addCoordinatedAnimations({ () -> Void in
self.layer.backgroundColor = UIColor.clearColor().CGColor
}, completion: nil)
}
}
}
使用只有一个单元格的集合视图,并在焦点移动到单元格时在 didUpdateFocusInContext 中添加变换到单元格并更改单元格背景颜色。
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
coordinator.addCoordinatedAnimations({
if self.focused {
self.transform = CGAffineTransformMakeScale(1.01, 1.01)
self.backgroundColor = UIColor.whiteColor()
self.textLabel.textColor = .blackColor()
}
else {
self.transform = CGAffineTransformMakeScale(1, 1)
self.backgroundColor = UIColor.clearColor()
self.textLabel.textColor = .whiteColor()
}
}, completion: nil)
}
如果您像 iTunes 一样使用图像作为背景并将其用于单元格后面的视觉效果视图,您可以尝试提取图像的颜色。
您还可以对视频控制器中的 collectionView 应用变换,使其看起来像处于焦点状态
您可以使用系统按钮,将故事板中的背景图片设置为包含您想要的颜色的图片
关于使 UILabel 可聚焦:
class MyLabel: UILabel {
override var canBecomeFocused: Bool {
return true
}
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocus(in: context, with: coordinator)
backgroundColor = context.nextFocusedView == self ? .blue:.red
}
}
重要!!!
如苹果开发者门户网站所述:
这个 属性 的值为 true 如果视图可以成为焦点;否则为假。
默认情况下,此 属性 的值为 false。 属性 通知焦点引擎视图是否能够被聚焦。有时即使视图 returns 为真,视图也可能由于以下原因而无法聚焦:
视图已隐藏。
视图的 alpha 设置为 0。
视图已将 userInteractionEnabled 设置为 false。
视图当前不在视图层次结构中。
我正在尝试实现 6 行高描述标签,我希望它是可聚焦的。理想情况下,这意味着扩展 UILabel class 以制作自定义组件。我尝试通过实施 canBecomeFocused
和 didUpdateFocusInContext
但我的 UILabel 似乎没有得到任何关注。
我也尝试用 UIButton 替换 UILabel,但按钮并没有真正针对这类事情进行优化。这也意味着我需要将 buttonType
的焦点从自定义更改为普通......而 buttonType 似乎是只读 属性.
实际上,我希望 Apple 在 Apple TV Movies 应用程序中实现完全相同的文本标签。对于电影描述,他们有一个显示几行文本的文本标签和一个 "more"。聚焦时,它看起来像一个按钮(周围有阴影)并改变了背景颜色。点击时 - 它会打开一个包含整个电影描述的模式 window。
有什么建议吗?或者也许有人已经为 tvOS 实现了这个自定义控件?或者更好的情况 - Apple 有一个组件可以执行此操作,但我遗漏了一些东西。
P.S:欢迎Swift解决方案:)
好的,回答我自己的问题:)
所以看起来有些视图 "focusable" 在 tvOS 上开箱即用,而其他视图必须按照指示才能这样做。
我最终使用了 UITextView
,它有一个 selectable
属性,但默认情况下如果不是这些可聚焦视图之一。必须禁用 TextView
的编辑以使其看起来像 UILabel
。此外,目前存在一个错误,它会阻止您使用 Interface Builder 中的 selectable
属性 但可以从代码中使用。
当然,canBecomeFocused()
和didUpdateFocusInContext
也必须实施。您还需要传递 UIViewController
因为 UITextView
无法呈现模式视图控制器。下面是我最终创建的。
class FocusableText: UITextView {
var data: String?
var parentView: UIViewController?
override func awakeFromNib() {
super.awakeFromNib()
let tap = UITapGestureRecognizer(target: self, action: "tapped:")
tap.allowedPressTypes = [NSNumber(integer: UIPressType.Select.rawValue)]
self.addGestureRecognizer(tap)
}
func tapped(gesture: UITapGestureRecognizer) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let descriptionView = storyboard.instantiateViewControllerWithIdentifier("descriptionView") as? DescriptionViewController {
if let view = parentView {
if let show = show {
descriptionView.descriptionText = self.data
view.modalPresentationStyle = UIModalPresentationStyle.OverFullScreen
view.presentViewController(descriptionView, animated: true, completion: nil)
}
}
}
}
override func canBecomeFocused() -> Bool {
return true
}
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
if context.nextFocusedView == self {
coordinator.addCoordinatedAnimations({ () -> Void in
self.layer.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.2).CGColor
}, completion: nil)
} else if context.previouslyFocusedView == self {
coordinator.addCoordinatedAnimations({ () -> Void in
self.layer.backgroundColor = UIColor.clearColor().CGColor
}, completion: nil)
}
}
}
使用只有一个单元格的集合视图,并在焦点移动到单元格时在 didUpdateFocusInContext 中添加变换到单元格并更改单元格背景颜色。
override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
coordinator.addCoordinatedAnimations({
if self.focused {
self.transform = CGAffineTransformMakeScale(1.01, 1.01)
self.backgroundColor = UIColor.whiteColor()
self.textLabel.textColor = .blackColor()
}
else {
self.transform = CGAffineTransformMakeScale(1, 1)
self.backgroundColor = UIColor.clearColor()
self.textLabel.textColor = .whiteColor()
}
}, completion: nil)
}
如果您像 iTunes 一样使用图像作为背景并将其用于单元格后面的视觉效果视图,您可以尝试提取图像的颜色。
您还可以对视频控制器中的 collectionView 应用变换,使其看起来像处于焦点状态
您可以使用系统按钮,将故事板中的背景图片设置为包含您想要的颜色的图片
关于使 UILabel 可聚焦:
class MyLabel: UILabel {
override var canBecomeFocused: Bool {
return true
}
override func didUpdateFocus(in context: UIFocusUpdateContext, with coordinator: UIFocusAnimationCoordinator) {
super.didUpdateFocus(in: context, with: coordinator)
backgroundColor = context.nextFocusedView == self ? .blue:.red
}
}
重要!!! 如苹果开发者门户网站所述:
这个 属性 的值为 true 如果视图可以成为焦点;否则为假。
默认情况下,此 属性 的值为 false。 属性 通知焦点引擎视图是否能够被聚焦。有时即使视图 returns 为真,视图也可能由于以下原因而无法聚焦:
视图已隐藏。
视图的 alpha 设置为 0。
视图已将 userInteractionEnabled 设置为 false。
视图当前不在视图层次结构中。