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

Программируем под IOS
Ответить
Anonymous
 Как программно прокрутить до определенной ячейки во вложенных элементах 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 ... ws-vertica
Ответить

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

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

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

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

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