SwiftUI:点击时更改列表行突出显示颜色
SwiftUI: Change List row Highlight colour when tapped
点击时列表行的默认颜色为灰色。
我知道如何使用 .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()
}
}
首先,您希望行上的 .ListRowBackground 修饰符不是整个列表,然后使用它有条件地设置每一行的行背景颜色。如果将点击行的 ID 保存在 @State var 中,则可以根据选择状态将行设置为红色或默认颜色。这是代码:
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()
}
}
关注@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))
}
}
如果直接使用按钮而不是文本,这使我可以点击行中的任意位置,而不仅仅是文本。
如果您正在 iOS 上寻找用于样式目的的替代方案并且不想引入状态管理,因为列表由 UITableView 支持,您可以使用
UITableViewCell.appearance().selectedBackgroundView = UIView()
完全删除选择颜色。或者:
UITableViewCell.appearance().selectedBackgroundView = {
let view = UIView()
view.backgroundColor = .blue
return view
}()
设置特定的突出显示颜色
请注意,这适用于整个应用程序,并且仅适用于支持 UITableView 的平台,因此 MacOS 或 WatchOS 将需要其他解决方案。
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)
}
}
}
}
}
这里是没有按钮的改进优雅解决方案,整行都是可点击的。也适用于 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
不完美,但是可以用,如果有改进欢迎留言:
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: {}
}
}
}
点击时列表行的默认颜色为灰色。
我知道如何使用 .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()
}
}
首先,您希望行上的 .ListRowBackground 修饰符不是整个列表,然后使用它有条件地设置每一行的行背景颜色。如果将点击行的 ID 保存在 @State var 中,则可以根据选择状态将行设置为红色或默认颜色。这是代码:
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()
}
}
关注@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))
}
}
如果直接使用按钮而不是文本,这使我可以点击行中的任意位置,而不仅仅是文本。
如果您正在 iOS 上寻找用于样式目的的替代方案并且不想引入状态管理,因为列表由 UITableView 支持,您可以使用
UITableViewCell.appearance().selectedBackgroundView = UIView()
完全删除选择颜色。或者:
UITableViewCell.appearance().selectedBackgroundView = {
let view = UIView()
view.backgroundColor = .blue
return view
}()
设置特定的突出显示颜色
请注意,这适用于整个应用程序,并且仅适用于支持 UITableView 的平台,因此 MacOS 或 WatchOS 将需要其他解决方案。
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)
}
}
}
}
}
这里是没有按钮的改进优雅解决方案,整行都是可点击的。也适用于 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
不完美,但是可以用,如果有改进欢迎留言:
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: {}
}
}
}