我尝试让键盘上的按钮在水平方向上彼此靠近。首先我尝试调整按钮框架的宽度。但我发现如果减小框架宽度,某些长宽度字符(例如“W”)将无法正确显示。
然后我尝试将 HStack 的间距设为负数,就像我在下面的代码中所做的那样。
但这会导致按钮相互重叠,并且可点击区域会向左移动,这是不可接受的(可以通过将背景颜色设置为蓝色来检查)。
有没有一种方法可以在不改变字体大小的情况下减少按钮距离?
struct KeyboardView: View {
let KeyboardStack = [["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"],
["A", "S", "D", "F", "G", "H", "J", "K", "L"],
["Z", "X", "C", "V", "B", "N", "M"]]
var body: some View {
VStack(spacing: 9) {
ForEach(KeyboardStack.indices) { row in
let num = KeyboardStack[row].indices
HStack(spacing: -12) {
ForEach(num) { column in
Button(KeyboardStack[row][column]) {}
.frame(width: 12, height: 12,alignment: .center)
.padding()
// .background(Color.blue)
.font(.system(size: 15, weight: .regular, design: .default))
.foregroundColor(.white)
.buttonStyle(PlainButtonStyle())
}
}
.frame(width: 255, height: 19.5, alignment:.center)
}
}
.frame(width: 445, height: 60, alignment:.center)
}
}
要做的第一件简单的事情就是去掉为每个按钮添加额外填充的
padding()
修饰符。
我假设,鉴于这是一个键盘视图,您希望所有按键具有相同的宽度。您可以使用
PreferenceKey
存储适合某个字母所需的最大宽度,然后将其用于每个 Button
,使其仅根据需要大小:
struct KeyboardView: View {
@State private var keyWidth : CGFloat = 0
let KeyboardStack = [["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"],
["A", "S", "D", "F", "G", "H", "J", "K", "L"],
["Z", "X", "C", "V", "B", "N", "M"]]
var body: some View {
VStack(spacing: 9) {
ForEach(KeyboardStack.indices, id: \.self) { row in
let num = KeyboardStack[row].indices
HStack(spacing: 0) {
ForEach(num, id: \.self) { column in
Button(action: {}) {
Text(KeyboardStack[row][column])
.font(.system(size: 15, weight: .regular, design: .default))
.foregroundColor(.white)
.buttonStyle(PlainButtonStyle())
.frame(width: keyWidth)
.background(GeometryReader {
Color.clear.preference(key: KeyWidthKey.self,
value: $0.frame(in: .local).size.height)
})
.contentShape(Rectangle())
}
}
}.onPreferenceChange(KeyWidthKey.self) { keyWidth = $0 }
}
}
}
}
struct KeyWidthKey: PreferenceKey {
static var defaultValue: CGFloat { 0 }
static func reduce(value: inout Value, nextValue: () -> Value) {
value = max(value, nextValue())
}
}
请注意,如果您更改字体大小,此解决方案将继续有效,因为它不依赖于每个键的硬编码
frame
大小。
我建议仅使用
Button
作为包装视图,构建按钮的内容而不是直接使用字符串。您可以轻松控制其布局。
VStack(spacing: 4) {
ForEach(keys.indices) { row in
HStack(spacing: 3) {
ForEach(keys[row].indices) { column in
Button {
print("Tap \(keys[row][column])")
} label: {
Text(keys[row][column])
.font(.system(size: fontSize))
.foregroundColor(.white)
.frame(minWidth: fontSize)
.padding(3)
.background(
RoundedRectangle(cornerRadius: 2)
.fill(.black)
)
}
}
}
}
}
结果
这里有一个重构的代码和方法给你:,
PS:仍然有很多空间可以进行更多重构,例如摆脱硬代码值并使按键和键盘大小根据屏幕尺寸动态化等等,例如支持其他语言或小写或大写单词,添加声音按键列表可以继续下去。这是一个简单的方法,供您开始或根据您的需要使用此方法。 这就是为什么苹果有一个大团队专门负责键盘,这看起来很简单,但我们使用的 iOS 中的键盘比我们知道的要复杂,它是我们应用程序中的一个应用程序,当我们需要通过键盘输入内容时.
struct KeyboardView: View {
let keyBackgroundColor: Color
let keyForegroundColor: Color
let keyboardBackgroundColor: Color
init(keyBackgroundColor: Color, keyForegroundColor: Color, keyboardBackgroundColor: Color) {
self.keyBackgroundColor = keyBackgroundColor
self.keyForegroundColor = keyForegroundColor
self.keyboardBackgroundColor = keyboardBackgroundColor
}
init() {
self.keyBackgroundColor = Color.gray
self.keyForegroundColor = Color.primary
self.keyboardBackgroundColor = Color.gray.opacity(0.5)
}
private let keyboard: [[String]] = [["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"],
["A", "S", "D", "F", "G", "H", "J", "K", "L"],
["Z", "X", "C", "V", "B", "N", "M"]]
var body: some View {
VStack(spacing: 5.0) {
ForEach(keyboard.indices) { row in
let num = keyboard[row].indices
HStack(spacing: 5.0) {
ForEach(num) { column in
keyBackgroundColor.cornerRadius(2.0)
.frame(width: 24.0, height: 24.0)
.overlay( Text(keyboard[row][column])
.font(.system(size: 15.0, weight: .regular, design: .default))
.foregroundColor(keyForegroundColor)
.fixedSize() )
.onTapGesture { print(keyboard[row][column]) }
}
}
}
}
.padding(5.0)
.background(keyboardBackgroundColor.cornerRadius(5.0))
}
}