【问题标题】:SwiftUI: Change List row Highlight colour when tappedSwiftUI:点击时更改列表行突出显示颜色
【发布时间】:2020-03-27 05:30:17
【问题描述】:

点击时列表行的默认颜色为灰色。

我知道如何使用 .listRowBackground 更改背景颜色,但随后它会更改为整个列表。

如何在点击时更改为自定义颜色,以便只有点击的行保持红色?

import SwiftUI

struct ExampleView: View {
    @State private var fruits = ["Apple", "Banana", "Grapes", "Peach"]

    var body: some View {
        NavigationView {
            List {
                ForEach(fruits, id: \.self) { fruit in
                    Text(fruit)
                }
                .listRowBackground(Color.red)

            }


        }
    }


}

struct ExampleView_Previews: PreviewProvider {
    static var previews: some View {
        ExampleView()
    }
}

【问题讨论】:

标签: swiftui swiftui-list


【解决方案1】:

首先,您希望行上的 .ListRowBackground 修饰符不是整个列表,然后使用它有条件地设置每行上的行背景颜色。如果将点击行的 ID 保存在 @State 变量中,则可以根据选择状态将该行设置为红色或默认颜色。代码如下:

import SwiftUI

struct ContentView: View {
    @State private var fruits = ["Apple", "Banana", "Grapes", "Peach"]
    @State private var selectedFruit: String?

    var body: some View {
        NavigationView {
            List {
                ForEach(fruits, id: \.self) { fruit in
                    Text(fruit)
                        .onTapGesture {
                            self.selectedFruit = fruit
                    }
                    .listRowBackground(self.selectedFruit == fruit ? Color.red : Color(UIColor.systemGroupedBackground))
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

【讨论】:

  • 这可以用于非基于 ForEach 的列表吗?比如那些使用内置选择管理功能的? List(values, selection: $selection) { val in?
  • 我认为它应该可以工作,并且可能是一个更好的整体解决方案。这个特定的解决方案只是试图直接回答原始问题,而不是建议最佳实践。试一试,如果您无法获得所需的内容,请提出一个新问题并发表评论并附上该问题的链接。
  • 如何为LazyVStack 制作它?
【解决方案2】:

跟随@Chuck H,

我正在使用:

        List {
            ForEach(viewModel.sharingGroups, id: \.self) { group in
                Button(action: {
                    self.selectedGroup = group
                }, label: {
                    Text(group.name)
                })
                .listRowBackground(self.selectedGroup == group ? Color.gray : Color(UIColor.systemGroupedBackground))
            }
        }

如果您使用按钮而不是直接使用文本,这使我能够点击行上的任意位置,而不仅仅是文本。

【讨论】:

    【解决方案3】:

    如果您正在为 iOS 上的样式目的寻找替代方案并且不想引入状态管理,因为列表由 UITableView 支持,您可以使用

    UITableViewCell.appearance().selectedBackgroundView = UIView()
    

    完全删除选择颜色。或者:

    UITableViewCell.appearance().selectedBackgroundView = {
                let view = UIView()
                view.backgroundColor = .blue
                return view
            }()
    

    设置特定的高亮颜色

    请注意,这适用于整个应用程序,并且仅适用于支持 UITableView 的平台,因此 MacOS 或 WatchOS 需要其他解决方案。

    【讨论】:

      【解决方案4】:

      这里是改进的优雅解决方案,没有按钮,整行都是可点击的。也适用于 iOS13。

      @ObservedObject var viewModel: TypesListViewModel
      @State private var selectedType: Type?   
      
       List{
             ForEach(viewModel.types, id: \.id){ type in
                  TypeRowView(type: type)
                       .contentShape(Rectangle()) //makes whole row tappable
                       .onTapGesture {
                            selectedType = type
                           }
                       .listRowBackground(selectedType == type ? Color(.systemFill) : Color(.systemBackground))
                 }//ForEach
             }//List
      

      【讨论】:

        【解决方案5】:

        虽然不完美,但可以,如果有改进请留言:

        struct CustomNavigationLink<ContentView: View, DestinationView: View>: View {
        
            let content: () -> ContentView
            let destinationView: () -> DestinationView
            @State private var showDetail = false
            @State private var isTouchDown = false
        
            var body: some View {
                ZStack(alignment: .leading) {
                    Color(.red)
                        .opacity(isTouchDown ? 0.3 : 0)
                    HStack {
                        content()
                        Spacer()
                        NavigationLink(destination: destinationView(),
                                       isActive: self.$showDetail) { EmptyView() }
                                       .hidden()
                                       .frame(width: 0)
                        Image(systemName: "chevron.right")
                            .foregroundColor(.red)
                    }
                    .contentShape(Rectangle())
                    .onTapGesture {
                        showDetail = true
                    }
                    ._onButtonGesture { isTouchDown in
                        withAnimation {
                            self.isTouchDown = isTouchDown
                        }
                    } perform: {}
                }
            }
        }
        

        【讨论】:

          【解决方案6】:

          Apple 在 SwiftUI 中遇到了一些愚蠢的事情。在把我的头撞到墙上之后,我终于取得了一些成功。只需添加一个 Zstack 和 Empty Button。

          var body: some View {
              List {
                  ForEach(data, id: \.self) { item in
                      ZStack {
                          Button("") {}
                          NavigationLink(destination: ItemView(item: item)) {
                              ItemRow(item: item)
                          }
                      }
                  }
              }
          }

          【讨论】:

          • 在 iOS 15 中不起作用
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-02-18
          • 2010-12-12
          • 2013-04-22
          • 1970-01-01
          • 2012-10-24
          • 2013-02-02
          • 2023-03-19
          相关资源
          最近更新 更多