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.
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)
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.
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.
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».
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