#swift #swiftui
#быстрый #свифтуи
Вопрос:
У меня есть структура DBScrollViewCellWrapper
. этот дисплей содержит
struct DBScrollViewCellWrapper: View, Identifiable, Equatable {
let id = UUID().uuidString
let view: AnyView
@State var showSelectionLine: Bool = false
var body: some View {
VStack(spacing: 0){
view
if self.showSelectionLine{
Rectangle()
.frame(width: 10, height: 1)
.foregroundColor(.red)
}
}
}
static func == (lhs: DBScrollViewCellWrapper, rhs: DBScrollViewCellWrapper) -> Bool { lhs.id == rhs.id }
}
затем сгенерируйте номер DBScrollViewCellWrapper
ячейки. при нажатии на ячейку отображается выбранная ячейка, выделенная линией.
struct DBScrollView: View {
let views: [DBScrollViewCellWrapper]
var showsIndicators = false
var completion:(DBScrollViewCellWrapper,Int)->Void = {x,index in}
var isHorizontal: Bool = false
var leadingSpacing: CGFloat = 0
var trailingSpacing: CGFloat = 0
var itemSpacing: CGFloat = 5
var isFixSize: Bool = false
var fixWidth: CGFloat = .infinity
var fixHeight: CGFloat = .infinity
@State var showSelectionLine: Bool = false
@State private var previousItem : DBScrollViewCellWrapper?
init(views: [DBScrollViewCellWrapper],
showsIndicators: Bool = false,
isHorizontal: Bool = false,
leadingSpacing: CGFloat = 0,
trailingSpacing: CGFloat = 0,
itemSpacing: CGFloat = 5,
isFixSize: Bool = false,
fixWidth: CGFloat = .infinity,
fixHeight: CGFloat = .infinity,
completion: @escaping (DBScrollViewCellWrapper,Int)->Void = {val,index in}) {
self.views = views.map { $0 } //DBScrollViewCellWrapper(view: $0)
self.showsIndicators = showsIndicators
self.completion = completion
self.isHorizontal = isHorizontal
self.leadingSpacing = leadingSpacing
self.trailingSpacing = trailingSpacing
self.itemSpacing = itemSpacing
self.isFixSize = isFixSize
self.fixWidth = fixWidth
self.fixHeight = fixHeight
}
var body: some View {
GeometryReader(content: { geometry in
ScrollView(isHorizontal ? .horizontal : .vertical, showsIndicators: showsIndicators, content: {
self.generateViews(in: geometry)
})
.padding(.leading, self.leadingSpacing)
.padding(.trailing, self.trailingSpacing)
})
}
private func generateViews(in geometry: GeometryProxy) -> some View{
return ZStack{
if isHorizontal{
HStack(spacing: itemSpacing){
ForEach(self.views) { item in
item
.padding(5)
.border(Color.black)
.onTapGesture(count: 1, perform: {
self.tapped(value: item)
})
}
Spacer()
}
}else{
VStack(spacing: itemSpacing){
ForEach(self.views, id: .id) { item in
item
.padding(5)
.border(Color.clear)
.onTapGesture(count: 1, perform: {
self.tapped(value: item)
})
}
Spacer()
}
}
}
}
func tapped(value: DBScrollViewCellWrapper) {
guard let index = views.firstIndex(of: value) else { assert(false, "This should never happen"); return }
value.showSelectionLine = true
completion(value,index)
}
}
Предварительный просмотр кода:
struct DBScrollView_Previews: PreviewProvider {
static var previews: some View {
let arr = Array(0...100)
let arrView = arr.map{DBScrollViewCellWrapper(view: AnyView(Text("($0)")))}
DBScrollView(views: arrView, isHorizontal: false) { (cell, inx) in
cell.showSelectionLine = true
}
}
}
Проблема
при нажатии на ячейку изменялось значение ячейки, но это не обновлялось.
Комментарии:
1. Вы изменяете копию представления в стеке, но не представление в иерархии представлений. Перечитайте о состояниях и потоках данных SwiftUI. Большая часть этого кода должна быть переработана.
2. Как выбрать ячейку? Пожалуйста, помогите @Asperi
Ответ №1:
Переработанный код для выбора
struct DBScrollView: View {
private let views: [DBScrollViewCellWrapper]
var showsIndicators = false
var completion:(DBScrollViewCellWrapper,Int)->Void = {x,index in}
var isHorizontal: Bool = false
var leadingSpacing: CGFloat = 0
var trailingSpacing: CGFloat = 0
var itemSpacing: CGFloat = 5
var isFixSize: Bool = false
var fixWidth: CGFloat = .infinity
var fixHeight: CGFloat = .infinity
@State var selectedIndex: Int = -1
@State var showSelectionLine: Bool = false
@State private var previousItem : DBScrollViewCellWrapper?
init(views: [AnyView],
showsIndicators: Bool = false,
isHorizontal: Bool = false,
leadingSpacing: CGFloat = 0,
trailingSpacing: CGFloat = 0,
itemSpacing: CGFloat = 5,
isFixSize: Bool = false,
fixWidth: CGFloat = .infinity,
fixHeight: CGFloat = .infinity,
completion: @escaping (DBScrollViewCellWrapper,Int)->Void = {val,index in}) {
self.views = views.map { DBScrollViewCellWrapper(view: AnyView($0))}
self.showsIndicators = showsIndicators
self.completion = completion
self.isHorizontal = isHorizontal
self.leadingSpacing = leadingSpacing
self.trailingSpacing = trailingSpacing
self.itemSpacing = itemSpacing
self.isFixSize = isFixSize
self.fixWidth = fixWidth
self.fixHeight = fixHeight
}
var body: some View {
GeometryReader(content: { geometry in
ScrollView(isHorizontal ? .horizontal : .vertical, showsIndicators: showsIndicators, content: {
self.generateViews(in: geometry)
})
.padding(.leading, self.leadingSpacing)
.padding(.trailing, self.trailingSpacing)
})
}
private func generateViews(in geometry: GeometryProxy) -> some View{
return ZStack{
if isHorizontal{
HStack(alignment: .center, spacing: itemSpacing){
ForEach(self.views.indices, id:.self) { index in
let item = self.views[index]
VStack(spacing: 0){
item.view
.foregroundColor(self.selectedIndex == index ? Color.yellow : Color.white)
.padding(5)
.onTapGesture(count: 1, perform: {
self.selectedIndex = index
self.tapped(value: item)
})
Rectangle()
.frame(width: self.selectedIndex == index ? 10 : 0, height: 1, alignment: .center)
.foregroundColor(Color.yellow)
}
}
Spacer()
}
}else{
VStack(spacing: itemSpacing){
ForEach(self.views.indices, id: .self) { index in
let item = self.views[index]
VStack(spacing: 0){
item.view
.padding(5)
.border(Color.white)
.onTapGesture(count: 1, perform: {
self.selectedIndex = index
self.tapped(value: item)
})
Rectangle()
.frame(width: self.selectedIndex == index ? 10 : 0, height: 1, alignment: .center)
.foregroundColor(Color.yellow)
}
}
Spacer()
}
}
}
}
func tapped(value: DBScrollViewCellWrapper) {
guard let index = views.firstIndex(of: value) else { assert(false, "This should never happen"); return }
completion(value,index)
}
}
struct DBScrollViewCellWrapper: Identifiable, Equatable {
let id = UUID().uuidString
let view: AnyView
static func == (lhs: DBScrollViewCellWrapper, rhs: DBScrollViewCellWrapper) -> Bool { lhs.id == rhs.id } } struct DBScrollView_Previews: PreviewProvider {
static var previews: some View {
let arr = Array(0...100)
let arrView = arr.map{AnyView(Text("($0)"))}
DBScrollView(views: arrView, isHorizontal: true) { (cell, inx) in
}
.background(Color.black)
}
}