#swiftui #swiftui-scrollview #scrollviewreader
Вопрос:
Я разрабатываю приложение с помощью swiftui. После масштабирования, когда я говорю прокрутить в угол с помощью ScrollViewReader, он исчезает с экрана. мой код приведен ниже. Это не удается после нескольких попыток. это происходит не каждый раз.
import SwiftUI struct ContentView: View { @State var zoomIn = false var body: some View { GeometryReader { g in ScrollViewReader { reader in ScrollView([.horizontal,.vertical], showsIndicators: false) { VStack(spacing: 20) { ForEach(0 ..lt; 11, id:.self) { row in HStack(spacing: 20) { ForEach(0 ..lt; 11, id:.self) { column in Text("Item (row) (column)") .foregroundColor(.white) .frame(width: zoomIn ? 70 : 35, height: zoomIn ? 70 : 35) .background(Color.red) .id("(row)(column)") .onTapGesture { withAnimation { reader.scrollTo( ["00", "010","100","1010"].randomElement()!) } } } } } } Button("Zoom") { withAnimation { zoomIn.toggle() } } } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
мой домашний экран.
after scrollTo
Ответ №1:
Я думаю, что проблема, с которой вы столкнулись, заключается в том, что 2 ForEach
, похоже, просто не очень хорошо работают с ScrollReader
. Я использовал другой подход и использовал идентифицируемую структуру и а LazyVGrid
. Это позволило мне использовать один ForEach
и идентифицировать отдельные квадраты с a UUID
. Затем я использовал то же UUID
самое в scrollTo()
. Единственная трудность , с которой я столкнулся, заключалась в том, что ScrollReader
я не знал, что делать с двунаправленным ScrollView
, поэтому я создал функцию, которая возвращала UnitPoint
и использовала ее в качестве якоря scrollTo()
. Это, похоже, сделало свое дело, и оно работает очень надежно.
struct BiDirectionScrollTo: View { let scrollItems: [ScrollItem] = Array(0..lt;100).map( { ScrollItem(name: $0.description) }) let columns = [ // Using 3 grid items forces there to be 3 columns GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80)), GridItem(.fixed(80)) ] init() { } var body: some View { ScrollViewReader { reader in ScrollView([.horizontal,.vertical], showsIndicators: false) { LazyVGrid(columns: columns, spacing: 20) { ForEach(scrollItems, id: .id) { item in Text("Item (item.name)") .foregroundColor(.white) .frame(width: 80, height: 80) .background(Color.red) .id(item.id) .onTapGesture { withAnimation { if let index = [0, 9, 55, 90, 99].randomElement() { print(index) reader.scrollTo(scrollItems[index].id, anchor: setUnitPoint(index)) } } } } } } } } private func setUnitPoint(_ index:Int) -gt; UnitPoint { switch true { case index % 10 lt; 2 amp;amp; index / 10 lt; 2: return .topLeading case index % 10 gt;= 7 amp;amp; index / 10 lt; 7: return .topTrailing case index % 10 lt; 2 amp;amp; index / 10 gt;= 7: return .bottomLeading case index % 10 gt;= 2 amp;amp; index / 10 gt;= 7: return .bottomTrailing default: return .center } } } struct ScrollItem: Identifiable { let id = UUID() var name: String }
Комментарии:
1. Это очень мило. углы без проблем. но на этот раз он попадает не в те места в интерьере. например, индекс прокрутки равен 50, но он увеличивается до 70. Я не понимаю, зачем ты это сделал? Я просто изменил кадр на 300 и позволил index = Array(0..
2. Это пример, основанный на вашем вопросе. Если вам нужно что-то в центре, просто добавьте для этого регистр в функцию «setUnitPoint». Вы можете видеть, как это делается. Вот почему я установил значение
default
to.center
для обработки средних случаев, но на самом деле я не кодировал их вswitch
. Я просто разделил вид на квадранты, но если вы сделаете их ближе к краю,.default
они займут середину.3. Я изменил их все на центральные. прокручивается в ненужные места. В коде нет никаких проблем, почему это происходит? Я попробовал это на ios 15 iphone 13 similator и ipad pro 12.9 ios 15 similator. тот же результат
4. Я обновил свой ответ, чтобы показать вам, как его также перенести в центр. Я думаю, проблема в том , что если вы изменили ВСЕ
func setUnitPoint
на.center
, вы говорите ему попытаться поместить углы в центр, что не работает. Вместо этого вам нужно определить, находится ли один из ваших квадратов в центре или в углу, и пойти туда. Если вы посмотрите в обновленномfunc setUnitPoint()
, вы увидите, что я изменил тест на то, что делает угол. Вы также можете добавить аналогичные тесты, чтобы он попал в сторону. Я не занимался всеми делами. Вам нужно решить, какие дела вы хотите охватить самостоятельно.5. Я допустил ошибку при преобразовании строк и столбцов 🙁 сейчас это работает отлично. большое вам спасибо @Yrb