在tvOS上使用PrimitiveButtonStyle自定义按钮样式

tvOS上.frame只能修改label,而非button。通过自定义PrimitiveButtonStyle,可以自由修改button。tvOS还需要手动处理@FocusState

下面例子就是写一个固定大小的按钮样式,这样就不会因为文字或者图片大小而产生差异。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import SwiftUI

struct FixedSizeButtonStyle: PrimitiveButtonStyle {
@FocusState private var isFocused: Bool
var size: CGSize
var cornerRadius: CGFloat
func makeBody(configuration: Configuration) -> some View {
configuration.label
.frame(width: size.width, height: size.height)
.foregroundColor(.accentColor)
.background(
RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
.stroke()
.foregroundStyle(.linearGradient(colors: [.white.opacity(0.5), .clear, .white.opacity(0.5), .clear], startPoint: .topLeading, endPoint: .bottomTrailing))
)
.background(
RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
.fill((isFocused ? Color.white : Color.gray).opacity(0.5).gradient)
)
.scaleEffect(isFocused ? 1.2 : 1)
.animation(.easeOut(duration: 0.2), value: isFocused)
.focusable()
.focused($isFocused)
.onTapGesture {
configuration.trigger()
}
}
}

extension Button {
func fixedSizeButtonStyle(size: CGSize = CGSize(width: 122, height: 80), cornerRadius: CGFloat = 20) -> some View {
buttonStyle(FixedSizeButtonStyle(size: size, cornerRadius: cornerRadius))
.frame(width: size.width, height: size.height)
}
}

效果图:

iPerfman-tv-screenshot