swiftui ScrollViewReader прокрутка не корректно работает

#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