在tvOS的SwiftUI中使用.focused(_:equals:)实现自定义视图可聚焦
解决方案
要让自定义视图配合FocusState和.focused(_:equals:)实现焦点切换时的缩放效果,需要解决两个核心问题:让自定义视图可聚焦,以及同步焦点状态到视图内部的缩放逻辑。
步骤1:修改自定义视图,使其可聚焦并感知焦点状态
自定义视图默认不具备焦点能力,必须添加.focusable()修饰符。同时,通过@Environment(\.isFocused)可以直接获取当前视图的焦点状态,无需手动传递绑定,更符合SwiftUI的设计逻辑:
public struct SimpleView: View { // 通过环境变量获取当前视图的焦点状态 @Environment(\.isFocused) private var isFocused public init() {} public var body: some View { RoundedRectangle(cornerRadius: 20) .fill(.green) .scaleEffect(isFocused ? 1.0 : 0.8) .animation(.easeInOut, value: isFocused) .focusable() // 关键:让自定义视图具备接收焦点的能力 } }
步骤2:调整容器视图,关联焦点枚举与自定义视图
容器视图中只需保留@FocusState变量,并用.focused(_:equals:)修饰符将每个SimpleView与对应的枚举值绑定即可:
public enum EnumView: Hashable { case one, two, three } public struct GalleryView: View { @FocusState private var fokus: EnumView? public init() {} public var body: some View { HStack(alignment: .center) { SimpleView() .focused($fokus, equals: .one) .onChange(of: fokus) { newFocus in print("New focus: \(newFocus)") } SimpleView() .focused($fokus, equals: .two) .onChange(of: fokus) { newFocus in print("New focus: \(newFocus)") } SimpleView() .focused($fokus, equals: .three) .onChange(of: fokus) { newFocus in print("New focus: \(newFocus)") } } } }
原代码失效原因
- 自定义视图不可聚焦:原生控件(如
Button)默认自带.focusable(),但自定义视图需要手动添加该修饰符才能成为焦点目标。 - 焦点状态未同步:原代码中
SimpleView的@State focused是内部独立状态,无法感知外部.focused(_:equals:)标记的焦点变化,导致缩放逻辑无法触发。
现在你可以通过方向键横向切换焦点,每个SimpleView会根据自身焦点状态自动放大或缩小。
内容的提问来源于stack exchange,提问作者Frank Marx
相关产品推荐
相关产品推荐

