SwiftUI: как программно прокрутить до определенной ячейки во вложенных элементах ScrollViews (вертикальные, содержащие гIOS

Программируем под IOS
Ответить
Anonymous
 SwiftUI: как программно прокрутить до определенной ячейки во вложенных элементах ScrollViews (вертикальные, содержащие г

Сообщение Anonymous »

У меня есть представление SwiftUI с вложенными элементами ScrollView — вертикальный

Код: Выделить всё

ScrollView
[/b], содержащий горизонтальный

Код: Выделить всё

ScrollView
[/b], отображающий сетку ячеек (столбцы AK, строки 1–100). Я хочу программно перейти к определенной ячейке (например, [/b]) при нажатии кнопки.
Цель развертывания: iOS 16 (решения для iOS 17 и более поздних версий приемлемы, но предпочтительна совместимость с iOS 16)
Ограничение: Я не могу вычислить точные координаты/смещение целевой ячейки — это упрощенная демонстрация производственного кода, в которой расчет смещения вручную невозможен.

Код: Выделить всё

import SwiftUI

struct ContentView: View {
var body: some View {
VStack {
NestedScrollingView()
}
.padding()
}
}

struct NestedScrollingView: View {
@StateObject var viewModel = NestedScrollingViewModel()
let myMap = Dictionary(uniqueKeysWithValues: ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"].map { ($0, Array(1...100)) })

var body: some View {
ScrollView(.vertical, showsIndicators: false) {
RoundedRectangle(cornerRadius: 8)
.foregroundStyle(Color.blue)
.frame(height: 100)
.padding()
Button("Target Scroll View \(viewModel.scrollTokey.description)") {
viewModel.onClickScrollTo()
}
.buttonStyle(.borderedProminent)
.padding()

gridView
}
}

var gridView: some View {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .top, spacing: 4) {
ForEach(myMap.keys.sorted(), id: \.self) { key in
VStack(spacing: 4) {
Text(key)
.font(.caption)

ForEach(myMap[key] ?? [], id: \.self) { value in
Text("\(key):\(value)")
.font(.caption)
.frame(width: 50, height: 50)
.border(Color.gray, width: 1)
.padding(4)
}
}
}
}
.padding(8)
}
}
}

class NestedScrollingViewModel: ObservableObject {
let scrollTokey: [String: Int] = ["K": 60]

func onClickScrollTo() {
// Need to scroll to K:60
}
}
Что я пробовал
  • Модификатор ScrollPosition(id:) для iOS 17+ — добавлен

    Код: Выделить всё

    .id("\(key)-\(value)")
    [/b] в каждую ячейку и использовал

    Код: Выделить всё

    @State private var scrollPosition: String?
    [/b] с

    Код: Выделить всё

    .scrollPosition(id: $scrollPosition, anchor: .center)
    [/b] в горизонтальном элементе ScrollView. Это работает только для прямых дочерних элементов содержимого ScrollView, а не для вложенных элементов внутри VStacks/HStacks.
  • Код: Выделить всё

    ScrollViewReader
    в горизонтальном ScrollView[/b] — горизонтальный ScrollView заключен в

    Код: Выделить всё

    ScrollViewReader
    [/b] и использовал

    Код: Выделить всё

    proxy.scrollTo(id, anchor: .center). При этом происходит прокрутка по горизонтали до столбца K, но не прокрутка по вертикали[/b] до строки 60.
    
    [*][b]ScrollViewReader
    в вертикальном ScrollView[/b] — Вертикальный прокси-сервер не может найти идентификаторы, находящиеся внутри вложенного горизонтального ScrollView.
  • Два ScrollViewReader (по одному для каждой оси) — Используются отдельные прокси-серверы для вертикальной и горизонтальной прокрутки. Горизонтальный прокси-сервер работает, но вертикальный прокси-сервер по-прежнему не может достичь идентификаторов внутри вложенного горизонтального элемента ScrollView.
Single ScrollView([.horizontal, .vertical]) — обе оси объединены в один ScrollView, поэтому есть один

Код: Выделить всё

ScrollViewReader
[/b] может перейти к любой ячейке. Это меняет UX (нет прокрутки по независимой оси).
Требования:
  • Совместимость с iOS 16+ (в качестве резервного решения допускается только iOS 17+).
  • Невозможно вручную рассчитать смещение пикселей.
  • Необходимо поддерживать вложенную структуру ScrollView (вертикальную, содержащую вертикальные элементы). горизонтальный)


Подробнее здесь: https://stackoverflow.com/questions/799 ... crollviews
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»