SwiftUI 按钮仅点击文本部分
SwiftUI Button tap only on text portion
我的按钮的背景区域未检测到用户交互。与所述按钮交互的唯一方法是点击按钮的文本/标签区域。如何让整个 Button 都可以点击?
struct ScheduleEditorButtonSwiftUIView: View {
@Binding var buttonTagForAction : ScheduleButtonType
@Binding var buttonTitle : String
@Binding var buttonBackgroundColor : Color
let buttonCornerRadius = CGFloat(12)
var body: some View {
Button(buttonTitle) {
buttonActionForTag(self.buttonTagForAction)
}.frame(minWidth: (UIScreen.main.bounds.size.width / 2) - 25, maxWidth: .infinity, minHeight: 44)
.buttonStyle(DefaultButtonStyle())
.lineLimit(2)
.multilineTextAlignment(.center)
.font(Font.subheadline.weight(.bold))
.foregroundColor(Color.white)
.border(Color("AppHighlightedColour"), width: 2)
.background(buttonBackgroundColor).opacity(0.8)
.tag(self.buttonTagForAction)
.padding([.leading,.trailing], 5)
.cornerRadius(buttonCornerRadius)
}
}
这解决了我这边的问题:
var body: some View {
GeometryReader { geometry in
Button(action: {
// Action
}) {
Text("Button Title")
.frame(
minWidth: (geometry.size.width / 2) - 25,
maxWidth: .infinity, minHeight: 44
)
.font(Font.subheadline.weight(.bold))
.background(Color.yellow).opacity(0.8)
.foregroundColor(Color.white)
.cornerRadius(12)
}
.lineLimit(2)
.multilineTextAlignment(.center)
.padding([.leading,.trailing], 5)
}
}
您使用 UIScreen
而不是 GeometryReader
有什么原因吗?
我认为这是一个更好的解决方案,将 .frame
值添加到 Text()
按钮将覆盖整个区域
Button(action: {
//code
}) {
Text("Click Me")
.frame(minWidth: 100, maxWidth: .infinity, minHeight: 44, maxHeight: 44, alignment: .center)
.foregroundColor(Color.white)
.background(Color.accentColor)
.cornerRadius(7)
}
回答有点晚,但我找到了两种方法 —
选项 1:使用几何 Reader
Button(action: {
}) {
GeometryReader { geometryProxy in
Text("Button Title")
.font(Font.custom("SFProDisplay-Semibold", size: 19))
.foregroundColor(Color.white)
.frame(width: geometryProxy.size.width - 20 * 2) // horizontal margin
.padding([.top, .bottom], 10) // vertical padding
.background(Color.yellow)
.cornerRadius(6)
}
}
选项 2:将 HStack 与间隔符一起使用
HStack {
Spacer(minLength: 20) // horizontal margin
Button(action: {
}) {
Text("Hello World")
.font(Font.custom("SFProDisplay-Semibold", size: 19))
.frame(maxWidth:.infinity)
.padding([.top, .bottom], 10) // vertical padding
.background(Color.yellow)
.foregroundColor(Color.white)
.cornerRadius(6)
}
Spacer(minLength: 20)
}.frame(maxWidth:.infinity)
我在这里的思考过程是,虽然选项 1 更简洁,但我会选择选项 2,因为它与其父级的大小耦合较少(通过 GeometryReader
)并且更符合我认为 SwiftUI 的含义使用 HStack
、VStack
等
正确的解决方案是使用 .contentShape()
API.
Button(action: action) {
HStack {
Spacer()
Text("My button")
Spacer()
}
}
.contentShape(Rectangle())
您可以更改提供的形状以匹配按钮的形状;如果您的按钮是 RoundedRectangle
,您可以提供它。
您可以通过添加修饰符来定义命中测试的内容形状:contentShape(_:eoFill:)
重要的是你必须在 Button 的内容中应用。
Button(action: {}) {
Text("Select file")
.frame(width: 300)
.padding(100.0)
.foregroundColor(Color.black)
.contentShape(Rectangle()) // Add this line
}
.background(Color.green)
.cornerRadius(4)
.buttonStyle(PlainButtonStyle())
另一个
Button(action: {}) {
VStack {
Text("Select file")
.frame(width: 100)
Text("Select file")
.frame(width: 200)
}
.contentShape(Rectangle())
}
.background(Color.green)
.cornerRadius(4)
.buttonStyle(PlainButtonStyle())
简答
确保 Text
(或按钮内容)跨越触摸区域的长度,并使用 .contentShape(Rectangle())
。
Button(action:{}) {
HStack {
Text("Hello")
Spacer()
}
.contentShape(Rectangle())
}
长答案
分为两部分:
Button
的内容(例如Text
)需要拉伸
- 命中测试需要考虑的内容
拉伸内容(例如Text
):
// Solution 1 for stretching content
HStack {
Text("Hello")
Spacer()
}
// Solution 2 for stretching content
Text("Hello")
.frame(maxWidth: .infinity, alignment: .leading)
// Alternatively, you could specify a specific frame for the button.
要考虑命中测试的内容,请使用 .contentShape(Rectangle())
:
// Solution 1
Button(action:{}) {
HStack {
Text("Hello")
Spacer()
}
.contentShape(Rectangle())
}
// Solution 2
Button(action:{}) {
Text("Hello")
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
}
您可能正在这样做:
Button { /*to do something on button click*/}
label: { Text("button text").foregroundColor(Color.white)}
.frame(width: 45, height: 45, alignment: .center)
.background(Color.black)
解法:
Button(action: {/*to do something on button click*/ })
{
HStack {
Spacer()
Text("Buttton Text")
Spacer() } }
.frame(width: 45, height: 45, alignment: .center)
.foregroundColor(Color.white)
.background(Color.black).contentShape(Rectangle())
当我遇到同样的问题时,我正在处理需要用户交互的按钮和文本。在查看并测试了许多答案(包括来自 post 的一些答案)之后,我最终使其按以下方式工作:
对于按钮:
/* WITH IMAGE */
Button {
print("TAppeD")
} label: {
Image(systemName: "plus")
.frame(width: 40, height: 40)
}
/* WITH TEXT */
Button {
print("TAppeD")
} label: {
Text("My button")
.frame(height: 80)
}
对于文本:
Text("PP")
.frame(width: 40, height: 40)
.contentShape(Rectangle())
.onTapGesture {
print("TAppeD")
}
对于文本,当 Text
没有 .background
时,我只需要 .contentShape(Rectangle())
修饰符,以使整个文本框架响应点击手势,而使用按钮时,我使用带框架的文本或图像视图,既不需要 .background 也不需要 .contentShape。
Image of the following code in preview (I'm not allowed to include pictures yet )
import SwiftUI
struct ContentView: View {
@State var tapped: Bool = true
var body: some View {
VStack {
RoundedRectangle(cornerRadius: 19)
.frame(width: 40, height: 40)
.foregroundColor(tapped ? .red : .green)
Spacer()
HStack (spacing: 0) {
Text("PP")
.frame(width: 40, height: 40)
.contentShape(Rectangle())
.onTapGesture {
tapped.toggle()
}
Button {
print("TAppeD")
tapped.toggle()
} label: {
Image(systemName: "plus")
.frame(width: 40, height: 40)
}
.background(Color.red)
Button {
print("TAppeD")
tapped.toggle()
} label: {
Text("My button")
.frame(height: 80)
}
.background(Color.yellow)
}
Spacer()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
我的按钮的背景区域未检测到用户交互。与所述按钮交互的唯一方法是点击按钮的文本/标签区域。如何让整个 Button 都可以点击?
struct ScheduleEditorButtonSwiftUIView: View {
@Binding var buttonTagForAction : ScheduleButtonType
@Binding var buttonTitle : String
@Binding var buttonBackgroundColor : Color
let buttonCornerRadius = CGFloat(12)
var body: some View {
Button(buttonTitle) {
buttonActionForTag(self.buttonTagForAction)
}.frame(minWidth: (UIScreen.main.bounds.size.width / 2) - 25, maxWidth: .infinity, minHeight: 44)
.buttonStyle(DefaultButtonStyle())
.lineLimit(2)
.multilineTextAlignment(.center)
.font(Font.subheadline.weight(.bold))
.foregroundColor(Color.white)
.border(Color("AppHighlightedColour"), width: 2)
.background(buttonBackgroundColor).opacity(0.8)
.tag(self.buttonTagForAction)
.padding([.leading,.trailing], 5)
.cornerRadius(buttonCornerRadius)
}
}
这解决了我这边的问题:
var body: some View {
GeometryReader { geometry in
Button(action: {
// Action
}) {
Text("Button Title")
.frame(
minWidth: (geometry.size.width / 2) - 25,
maxWidth: .infinity, minHeight: 44
)
.font(Font.subheadline.weight(.bold))
.background(Color.yellow).opacity(0.8)
.foregroundColor(Color.white)
.cornerRadius(12)
}
.lineLimit(2)
.multilineTextAlignment(.center)
.padding([.leading,.trailing], 5)
}
}
您使用 UIScreen
而不是 GeometryReader
有什么原因吗?
我认为这是一个更好的解决方案,将 .frame
值添加到 Text()
按钮将覆盖整个区域
Button(action: {
//code
}) {
Text("Click Me")
.frame(minWidth: 100, maxWidth: .infinity, minHeight: 44, maxHeight: 44, alignment: .center)
.foregroundColor(Color.white)
.background(Color.accentColor)
.cornerRadius(7)
}
回答有点晚,但我找到了两种方法 —
选项 1:使用几何 Reader
Button(action: {
}) {
GeometryReader { geometryProxy in
Text("Button Title")
.font(Font.custom("SFProDisplay-Semibold", size: 19))
.foregroundColor(Color.white)
.frame(width: geometryProxy.size.width - 20 * 2) // horizontal margin
.padding([.top, .bottom], 10) // vertical padding
.background(Color.yellow)
.cornerRadius(6)
}
}
选项 2:将 HStack 与间隔符一起使用
HStack {
Spacer(minLength: 20) // horizontal margin
Button(action: {
}) {
Text("Hello World")
.font(Font.custom("SFProDisplay-Semibold", size: 19))
.frame(maxWidth:.infinity)
.padding([.top, .bottom], 10) // vertical padding
.background(Color.yellow)
.foregroundColor(Color.white)
.cornerRadius(6)
}
Spacer(minLength: 20)
}.frame(maxWidth:.infinity)
我在这里的思考过程是,虽然选项 1 更简洁,但我会选择选项 2,因为它与其父级的大小耦合较少(通过 GeometryReader
)并且更符合我认为 SwiftUI 的含义使用 HStack
、VStack
等
正确的解决方案是使用 .contentShape()
API.
Button(action: action) {
HStack {
Spacer()
Text("My button")
Spacer()
}
}
.contentShape(Rectangle())
您可以更改提供的形状以匹配按钮的形状;如果您的按钮是 RoundedRectangle
,您可以提供它。
您可以通过添加修饰符来定义命中测试的内容形状:contentShape(_:eoFill:)
重要的是你必须在 Button 的内容中应用。
Button(action: {}) {
Text("Select file")
.frame(width: 300)
.padding(100.0)
.foregroundColor(Color.black)
.contentShape(Rectangle()) // Add this line
}
.background(Color.green)
.cornerRadius(4)
.buttonStyle(PlainButtonStyle())
另一个
Button(action: {}) {
VStack {
Text("Select file")
.frame(width: 100)
Text("Select file")
.frame(width: 200)
}
.contentShape(Rectangle())
}
.background(Color.green)
.cornerRadius(4)
.buttonStyle(PlainButtonStyle())
简答
确保 Text
(或按钮内容)跨越触摸区域的长度,并使用 .contentShape(Rectangle())
。
Button(action:{}) {
HStack {
Text("Hello")
Spacer()
}
.contentShape(Rectangle())
}
长答案
分为两部分:
Button
的内容(例如Text
)需要拉伸- 命中测试需要考虑的内容
拉伸内容(例如Text
):
// Solution 1 for stretching content
HStack {
Text("Hello")
Spacer()
}
// Solution 2 for stretching content
Text("Hello")
.frame(maxWidth: .infinity, alignment: .leading)
// Alternatively, you could specify a specific frame for the button.
要考虑命中测试的内容,请使用 .contentShape(Rectangle())
:
// Solution 1
Button(action:{}) {
HStack {
Text("Hello")
Spacer()
}
.contentShape(Rectangle())
}
// Solution 2
Button(action:{}) {
Text("Hello")
.frame(maxWidth: .infinity, alignment: .leading)
.contentShape(Rectangle())
}
您可能正在这样做:
Button { /*to do something on button click*/}
label: { Text("button text").foregroundColor(Color.white)}
.frame(width: 45, height: 45, alignment: .center)
.background(Color.black)
解法:
Button(action: {/*to do something on button click*/ })
{
HStack {
Spacer()
Text("Buttton Text")
Spacer() } }
.frame(width: 45, height: 45, alignment: .center)
.foregroundColor(Color.white)
.background(Color.black).contentShape(Rectangle())
当我遇到同样的问题时,我正在处理需要用户交互的按钮和文本。在查看并测试了许多答案(包括来自 post 的一些答案)之后,我最终使其按以下方式工作:
对于按钮:
/* WITH IMAGE */
Button {
print("TAppeD")
} label: {
Image(systemName: "plus")
.frame(width: 40, height: 40)
}
/* WITH TEXT */
Button {
print("TAppeD")
} label: {
Text("My button")
.frame(height: 80)
}
对于文本:
Text("PP")
.frame(width: 40, height: 40)
.contentShape(Rectangle())
.onTapGesture {
print("TAppeD")
}
对于文本,当 Text
没有 .background
时,我只需要 .contentShape(Rectangle())
修饰符,以使整个文本框架响应点击手势,而使用按钮时,我使用带框架的文本或图像视图,既不需要 .background 也不需要 .contentShape。
Image of the following code in preview (I'm not allowed to include pictures yet )
import SwiftUI
struct ContentView: View {
@State var tapped: Bool = true
var body: some View {
VStack {
RoundedRectangle(cornerRadius: 19)
.frame(width: 40, height: 40)
.foregroundColor(tapped ? .red : .green)
Spacer()
HStack (spacing: 0) {
Text("PP")
.frame(width: 40, height: 40)
.contentShape(Rectangle())
.onTapGesture {
tapped.toggle()
}
Button {
print("TAppeD")
tapped.toggle()
} label: {
Image(systemName: "plus")
.frame(width: 40, height: 40)
}
.background(Color.red)
Button {
print("TAppeD")
tapped.toggle()
} label: {
Text("My button")
.frame(height: 80)
}
.background(Color.yellow)
}
Spacer()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}