MacOS 上 SwiftUI 中的按钮问题

Ada*_*hus 17 macos button swiftui

我在 MACOS 上使用 SwiftUI

如果我这样做:

      Button(action: { } ) {
        Text("Press")
        .padding()
        .background(Color.blue)
      }
Run Code Online (Sandbox Code Playgroud)

我明白了:

在此处输入图片说明

两个灰色区域是可点击按钮的末端。但我希望按钮是蓝色区域的形状。任何想法如何让整个蓝色区域都可以点击。

(我确实考虑过使用 .onTapGesture 但这不会使按钮动画化,因此您知道您已经点击了它。)

Gen*_*gan 21

您可以通过使用ButtonStyle来实现您想要的外观,然后根据传入的配置值指定颜色和其他样式属性。

如果有一个快乐的媒介,您可以继承默认按钮半径、基于文本长度和其他属性的自动宽度,那将会很好,但至少有能力指定所有属性并获得您想要的外观。

希望这可以帮助!

import SwiftUI

struct BlueButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .foregroundColor(configuration.isPressed ? Color.blue : Color.white)
            .background(configuration.isPressed ? Color.white : Color.blue)
            .cornerRadius(6.0)
            .padding()
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            Text("Hello World")
                .frame(maxWidth: .infinity, maxHeight: .infinity)

            Button(action: {
            }) {
                Text("Press")
                    .frame(maxWidth: 100, maxHeight: 24)
            }
            .buttonStyle(BlueButtonStyle())
        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 同样的方法也讨论在:https://alejandromp.com/blog/2019/06/22/swiftui-reusable-button-style/ (2认同)

Ada*_*hus 9

受到@Gene Z. Ragan 很好的回答的启发,我从这个答案开始,并进一步研究了这一点:

使 ButtonStyle 更加灵活:

struct NiceButtonStyle: ButtonStyle {
  var foregroundColor: Color
  var backgroundColor: Color
  var pressedColor: Color

  func makeBody(configuration: Self.Configuration) -> some View {
    configuration.label
      .font(.headline)
      .padding(10)
      .foregroundColor(foregroundColor)
      .background(configuration.isPressed ? pressedColor : backgroundColor)
      .cornerRadius(5)
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在呼叫站点添加一些糖以使其更干净:

extension View {
  func niceButton(
    foregroundColor: Color = .white,
    backgroundColor: Color = .gray,
    pressedColor: Color = .accentColor
  ) -> some View {
    self.buttonStyle(
      NiceButtonStyle(
        foregroundColor: foregroundColor,
        backgroundColor: backgroundColor,
        pressedColor: pressedColor
      )
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

then 意味着我们可以使用默认颜色:白色前景,灰色背景和重音颜色pressedColor

  Button(action: { } ) {
    Text("Button A")
  }
  .niceButton()
Run Code Online (Sandbox Code Playgroud)

或者我们可以自定义颜色:

  Button(action: { } ) {
    Text("Button B has a long description")
  }
  .niceButton(
    foregroundColor: .blue,
    backgroundColor: .yellow,
    pressedColor: .orange
  )
Run Code Online (Sandbox Code Playgroud)

我们得到:

在此处输入图片说明

再次感谢基因。


Ada*_*hus 5

我在反馈助手上向苹果提出了这个问题,看看他们是否有任何有用的想法。

\n\n

对话在这里:

\n\n

我说:

\n\n

如果在带有 SwiftUI 的 MACOS 上我这样做:

\n\n
  Button(action: { } ) {\n    Text("Press")\n    .padding()\n    .background(Color.blue)\n  }\n
Run Code Online (Sandbox Code Playgroud)\n\n

我得到一个蓝色的盒子,两侧有两个灰色的部分。\n附加图像。\n这两个灰色区域是可点击按钮的末端。但我希望按钮是蓝色区域的形状。

\n\n

相同的代码在 iOS 上可以正常运行。

\n\n

(我确实考虑过使用 .onTapGesture 但这不会为按钮设置动画,以便您知道您已经点击了它。)

\n\n

苹果说:

\n\n

iOS 和 macOS 有不同的默认 ButtonStyles \xe2\x80\x94 iOS 是无边框的,macOS 具有标准边框效果。

\n\n

听起来您\xe2\x80\x99正在尝试创建自定义ButtonStyle(因此没有任何系统提供chrome)。所以你\xe2\x80\x99ll想要创建它,它可以将蓝色背景应用到按钮的标签,然后将其应用到带有文本的简单按钮,例如

\n\n
Button("Press"), action {}).buttonStyle(BluePaddingButtonStyle()\n
Run Code Online (Sandbox Code Playgroud)\n\n

这将确保它在运行它的每个平台上具有相同的外观。

\n\n

我说:

\n\n

你好,谢谢你的解释。\n我明白你的意思,我\xe2\x80\x99m 同意我\xe2\x80\x99ve 提出的方法。

\n\n

\xe2\x80\x99 看起来仍然不正确:

\n\n
  Button(action: { } ) {\n    Text("Press")\n    .padding()\n    .background(Color.blue)\n  }\n
Run Code Online (Sandbox Code Playgroud)\n\n

应该产生一些看起来很奇怪的东西。\n我不明白为什么那段代码不能\xe2\x80\x99t只产生一个蓝色按钮。

\n\n

正如我所说 - 它\xe2\x80\x99s不是问题,因为我\xe2\x80\x99已经解决了它,但它\n目前\xe2\x80\x99并不直观。

\n\n

苹果说:

\n\n

ViewBuilder 中提供的内容用作按钮的标签:而不是整个按钮。该按钮仍将带有周围的背景、边框、前景样式等,如它\xe2\x80\x99s ButtonStyle 所描述的那样。因此,如果您的按钮需要具有非常特定的外观,那么它需要自定义该样式:要么是 BorderlessButtonStyle(但请注意,它仍然具有特定的前景外观样式),要么是自定义 ButtonStyle。

\n\n

我的想法:

\n\n

这确实帮助我理解了为什么它会这样显示,但直观上它似乎仍然是错误的!

\n


小智 5

您可以通过添加.buttonStyle(.borderless).

Button(action: { } ) {
   Text("Press")
      .padding()
      .background(Color.blue)
}
.buttonStyle(.borderless)
Run Code Online (Sandbox Code Playgroud)