Dans iOS14 Swift UI, vous pouvez désormais contrôler le processus de défilement de la liste avec du code.

introduction

Vous pouvez maintenant faire défiler la liste avec du code que vous ne pouviez pas faire avec l'interface utilisateur Swift dans iOS13 dans iOS14. Cet article résume comment l'implémenter.

Défilement sur iOS 13

Il s'agit d'un processus de "défilement automatique jusqu'à la ○ ème cellule" qui est courant lors du développement d'applications iOS, Il n'y avait aucun moyen de le faire avec l'interface utilisateur Swift sur iOS 13.

struct ContentView: View {
    var body: some View {
        List(0..<100) {
            Text("\($0)")
        }
    }
}

Dans UIKit, vous pouvez facilement implémenter l'exigence correspondante en appelant des méthodes telles que scrollToRow, scrollToItem sous la forme suivante. J'ai souvent utilisé ʻUIViewRepresentable, ʻUIViewControllerRepresentable, etc. juste pour cette fonctionnalité.

// UITableView
tableView.scrollToRow(at: IndexPath(row: 10, section: 0),
                      at: .top,
                      animated: true)

// UICollectionView
collectionView.scrollToItem(at: .init(item: 10, section: 0), 
                            at: .top,
                            animated: true)

Défilement sur iOS14

iOS14 a ajouté une nouvelle vue appelée ScrollViewReader qui peut contrôler l'état de défilement. En utilisant cela, il est possible de mettre en œuvre le processus de défilement automatique vers n'importe quel point.

L'exemple de code est illustré ci-dessous.

Préparation

Tout d'abord, configurez un TextField pour spécifier le point de défilement en tant que préparation.

struct ContentView: View {
    @State private var text: String = ""

    var body: some View {
        VStack {
            HStack {
                TextField("input row number", text: $text)
                Button("Scroll") {
                    guard let row = Int(text) else { return }
                    print(row)
                }
            }.padding()
            
            List(0..<100) {
                Text("\($0)")
            }
        }
    }
}

Cela vous permet d'appuyer sur le bouton pour obtenir la valeur que l'utilisateur a entrée dans TextField.

Contrôle de défilement

Ensuite, c'est la partie implémentation du processus de défilement.

Tout d'abord, entourez la partie où vous voulez contrôler le défilement avec ScrollViewReader. Cela vous permettra d'obtenir une instance ScrollViewProxy qui peut être contrôlée par défilement.

struct ContentView: View {
    @State private var text: String = ""

    var body: some View {
        VStack {
+           ScrollViewReader { (proxy: ScrollViewProxy) in
                HStack {
                    TextField("input row number", text: $text)
                    Button("Scroll") {
                        guard let row = Int(text) else { return }
                    }
                }.padding()
                List(0..<100) {
                    Text("\($0)")
                }
+           }
        }
    }
}

En outre, un identifiant pour spécifier la position de défilement est attribué à la vue cible, et Le défilement peut être réalisé simplement en spécifiant l'ID dans la méthode scrollTo de ScrollViewProxy à l'endroit où vous souhaitez démarrer le contrôle.

struct ContentView: View {
    @State private var text: String = ""

    var body: some View {
        VStack {
            ScrollViewReader { (proxy: ScrollViewProxy) in
                HStack {
                    TextField("input row number", text: $text)
                    Button("Scroll") {
                        guard let row = Int(text) else { return }
+                       withAnimation {
+                           proxy.scrollTo(row, anchor: .top)
+                       }
                    }
                }.padding()

                List(0..<100) {
                    Text("\($0)")
+                       .id($0)
                }
            }
        }
    }
}

Vous pouvez maintenant faire ce que vous voulez.

Au fait, si vous n'ajoutez pas withAnimation, l'animation de défilement ne sera pas effectuée. De plus, la position après le défilement peut être spécifiée en détail avec le deuxième argument «ancre».

prime

Cela a bien fonctionné pour Grid également.

struct ContentView: View {
    @State private var text: String = ""

    var body: some View {
        VStack {
            ScrollViewReader { (proxy: ScrollViewProxy) in
                HStack {
                    TextField("input row number", text: $text)
                    Button("Scroll") {
                        guard let row = Int(text) else { return }
                        withAnimation {
                            proxy.scrollTo(row, anchor: .top)
                        }
                    }
                }.padding()
                
                ScrollView {
                    LazyVGrid(
                        columns: [
                            GridItem(.flexible(minimum: 0, maximum: .infinity)),
                            GridItem(.flexible(minimum: 0, maximum: .infinity)),
                        ],
                        alignment: .center,
                        spacing: nil
                    ) {
                        ForEach(0..<100) {
                            Text("\($0)")
                                .frame(height: 100)
                        }
                    }
                }
            }
        }
    }
}

Recommended Posts

Dans iOS14 Swift UI, vous pouvez désormais contrôler le processus de défilement de la liste avec du code.
Liste des appareils pouvant être prévisualisés avec Swift UI
Mémo d'implémentation SKStoreReviewController dans l'interface utilisateur Swift d'iOS14
Éléments à prendre en compte lors de l'écriture de code en Java
Comment changer la couleur d'arrière-plan de la barre de navigation, etc. dans Swift UI
Comment créer une paire de clés d'ecdsa dans un format lisible par Java
[Swift] J'ai essayé d'utiliser ColorPicker (celui qui peut facilement sélectionner la couleur) ajouté dans iOS14 [SwiftUI]