如何在WatchOS上的SwiftUI列表中设置行样式?

时间:2019-10-17 14:08:48

标签: watchkit swiftui apple-watch

我正在使用SwiftUI,正在尝试在WatchOS的列表视图内创建具有自定义.buttonStyle的按钮列表,但无法使其正常工作。目前甚至可能吗?如果可以,怎么办?

示例项目:

struct Superhero: Identifiable {
    var id = UUID()
    var name: String
}

var superheroes = [
    Superhero(name: "Batman"),
    Superhero(name: "Superman"),
    Superhero(name: "Wonder Woman"),
    Superhero(name: "Aquaman"),
    Superhero(name: "Green Lantern"),
    Superhero(name: "The Flash")
]

struct SuperheroButtonStyle: ButtonStyle {

  func makeBody(configuration: Self.Configuration) -> some View {
    configuration.label
        .frame(minWidth: 0, maxWidth: .infinity)
        .foregroundColor(.white)
        .background(configuration.isPressed ? Color.white.opacity(0.95) : .green)
        .cornerRadius(13.0)
  }
}

struct SuperHeroesView: View{
    var body: some View {
        List {

            ForEach(superheroes) { superhero in
                Button(action: {
                    print(superhero.name)
                }){
                    Text(superhero.name)
                }.buttonStyle(SuperheroButtonStyle())
           }

       }
    }
}

此代码产生以下内容: picture of WatchOS app

相反,我希望按钮看起来像这样:

picture of wanted result

在最后一个示例中,我使用的是ScrollView而不是List,这意味着在滚动列表时,行和行都没有缩小和褪色的效果。

我已经尝试过使用负填充,但这不能给我更大的拐角半径(比默认半径更大的圆角),而且看起来并不好。

那么有没有一种方法可以将ListStyle正确地应用到ButtonStyle上,包括具有自定义的cornerRadius?

或者还有其他方法可以更好地控制行的外观,同时仍保留List随附的动画?

6 个答案:

答案 0 :(得分:5)

.listRowPlatterColor(.clear)给了我想要的东西。这可能比找到它要困难。

struct ContentView: View {
    @State private var EnrouteText = "Enroute"
    var body: some View {
        List {
            Button(action: {
                self.EnrouteText = getCurrentTime()
            }) {
                Text(EnrouteText)
            }
            .buttonStyle(BtnStyle(bgColor: .red, fgColor: .white))
            .listRowInsets(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
            .listRowPlatterColor(.clear)

            // The rest of the buttons.
        }
    }
}

// Button Styles
struct BtnStyle: ButtonStyle {
    var bgColor: Color
    var fgColor: Color

    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .frame(minWidth: 0, maxWidth: .infinity)
            .padding()
            .foregroundColor(fgColor)
            .background(bgColor)
            .cornerRadius(32)
    }
}

Example of using listRowPlatterColor to clear the final part of the background

答案 1 :(得分:1)

我不知道您是否已经解决了这个问题,但是我最终还是使用了

List {

        ForEach(superheroes) { superhero in
            Button(action: {
                print(superhero.name)
            }){
                Text(superhero.name)
            }
            .buttonStyle(SuperheroButtonStyle())
            .listRowInsets(EdgeInsets.init(top: 0, leading: 0, bottom: 0, trailing: 0))
       }

   }

将按钮的边缘扩展到列表的边缘,如下所示:

Rows with extended edges

您还可以添加修饰符

.environment(\.defaultMinListRowHeight, 20)

到列表本身,以允许行高缩小到所需大小。在此示例中,我选择了20:

Correctly sized row height

最后有一个

.listRowPlatterColor(.clear)

修饰符,可用于更改行本身的背景色。在此示例中,我选择“清除”以隐藏按钮未完全覆盖的边缘。

Clear Platter

答案 2 :(得分:1)

根据Human Interface Guidelines,建议滚动视图中的按钮(例如List)看起来像是圆角矩形(而不是胶囊)。

如果您尝试使用.listRowBackground,则会得到一个尖锐的矩形(不需要):

enter image description here

如果您改用.listRowPlatterColor,则会得到Apple推荐的使用方式(尽管只是一行代码):

enter image description here

Button("Log out") {}
  .listRowPlatterColor(Color.blue)

答案 3 :(得分:0)

我知道这不是应该实现的方式,但是看来SwiftUI中存在一个错误,阻止listRowPlatterColorlistRowBackground甚至listRowInsets做任何事情在最新版本的watchOS中。

这是我现在如何解决它:

ZStack {
    Color.black
    MyRowView()
}
    .padding(.horizontal, -8)

答案 4 :(得分:0)

要以某种颜色显示整个单元格的背景,必须使用.listRowBackground修饰符。您可以根据自己的喜好使用CapsuleRoundedRectangle作为背景:

struct SuperHeroesView: View{
    var body: some View {
        List {
            ForEach(superheroes) { superhero in
                Button(action: { print(superhero.name) }){
                    Text(superhero.name)
                }   .buttonStyle(SuperheroButtonStyle())
            }   .listRowBackground(Capsule()
                                       .fill(Color.green))
                // or as an alternative:
                //.listRowBackground(RoundedRectangle(cornerRadius: 13.0)
                //                       .fill(Color.green))
       }
    }
}

您可能还想更改按钮样式,因为背景突出显示效果只会影响按钮,而不会影响整个单元格:

struct SuperheroButtonStyle: ButtonStyle {

  func makeBody(configuration: Self.Configuration) -> some View {
    configuration.label
        .frame(minWidth: 0, maxWidth: .infinity)
        .foregroundColor(configuration.isPressed ? .gray : .white)
  }
}

答案 5 :(得分:-1)

struct SuperHeroesView: View{
        var body: some View {
            List {
                ForEach(superheroes) { superhero in
                    Button(action: {
                        print(superhero.name)
                    }){
                        Text(superhero.name)
                    }.buttonStyle(SuperheroButtonStyle())
                        .listRowInsets(EdgeInsets())
                        .listRowBackground(Color.clear)
                }.environment(\.defaultMinListRowHeight, 20)

            }
        }
    }