Native reagieren: Erstellen Sie eine ziehbare und wischbare Liste

Heutzutage ist es schwer, jemanden mit der Möglichkeit zu überraschen, Listenelemente in mobilen Anwendungen zu wischen. Eine unserer reaktionsnativen Anwendungen verfügte ebenfalls über solche Funktionen. In letzter Zeit musste sie jedoch um die Möglichkeit erweitert werden, Listenelemente per Drag & Drop zu verschieben. Und da mich das Finden einer Lösung eine gewisse Menge an Nervenzellen gekostet hat, habe ich beschlossen, einen kurzen Artikel einzureichen, um wertvolle Zeit für zukünftige Generationen zu sparen.



In unserer Anwendung haben wir das Paket "React react-native-swipe-list-view , um die Swip-Liste zu erstellen. Der erste Gedanke war, ein Paket mit Drag'n'Drop-Funktionalität zu nehmen und den Igel mit einer Schlange zu überqueren.

Eine Suche im Internet ergab drei Kandidaten: react-native-draggable-list , react-native-draggable-flatlist react-native-sortable-list und react-native-draggable-flatlist .

Mit dem ersten Paket war es nicht möglich, auch nur das angehängte Beispiel auszuführen (jedoch ist nicht nur für mich das entsprechende Problem in den Problemen angegeben ).

Ich musste mit dem zweiten Paket basteln, aber es gelang mir, eine ziehbare und wischbare Liste zu erstellen. Das Ergebnis war jedoch nicht inspiriert - die Komponente blinkte schamlos: Blinken beim Neuzeichnen, Fallen von Elementen weit über die Liste hinaus oder sogar deren Verschwinden. Es wurde klar, dass es in dieser Form nicht verwendet werden kann.

Zuerst verhielt sich das letzte Päckchen auch wie eine launische Frau, aber dann stellte sich heraus, dass ich einfach nicht wusste, wie man es kocht. Nachdem ich einen Schlüssel zum Herzen dieser "Dame" gefunden hatte, gelang es mir, ein akzeptables Ergebnis zu erzielen.

In unserem Projekt gab es eine wischbare Liste, an der Sie Drag & Drop befestigen müssen. In der Praxis ist es jedoch besser, am anderen Rand zu beginnen: Erstellen Sie zuerst eine ziehbare Liste und fügen Sie dann die Möglichkeit zum Wischen hinzu.

Die Leser sollten wissen, wie man ein reaktionsnatives Projekt erstellt. Konzentrieren wir uns also auf die Erstellung der Liste, die wir benötigen. Das unten diskutierte Beispiel ist TypeScript-Code.

Erstellen einer Draggable-Liste


Beginnen wir also mit der Installation des Pakets:

 yarn add react-native-draggable-flatlist 

Wir importieren die notwendigen Module:

 import React, { Component } from 'react' import { View } from 'react-native' import styles from './styles' import DraggableFlatList, { RenderItemInfo, OnMoveEndInfo } from 'react-native-draggable-flatlist' import ListItem from './components/ListItem' import fakeData from './fakeData.json' 

Hier ist DraggableFlatList eine Komponente aus dem installierten Paket, die die Drag & Drop- ListItem implementiert. ListItem ist unsere Komponente zum Anzeigen eines Listenelements (der Code wird unten dargestellt). fakeData ist eine fakeData Datei, die gefälschte Daten enthält - in diesem Fall ein Array von Objekten des Formulars:

 {"id": 0, "name": "JavaScript", "favorite": false} 

In einer realen Anwendung werden diese Daten höchstwahrscheinlich von Requisiten zu Ihrer Komponente gelangen oder aus dem Netzwerk heruntergeladen werden. In unserem Fall werden wir jedoch mit wenig Blut auskommen.

Da in diesem Beispiel TypeScript verwendet wird, beschreiben wir einige Entitäten:

 type Language = { id: number, name: string, favorite: boolean, } interface AppProps {} interface AppState { data: Array<Language> } 

Der Language , welche Felder die Listenelemente haben werden.

In diesem Beispiel erhalten wir nichts von Requisiten, daher ist die AppProps Oberfläche trivial, und in der Story werden wir ein Array von AppState speichern, das in der AppState Oberfläche angegeben ist.

Da der Komponentencode nicht sehr groß ist, werde ich ihn in seiner Gesamtheit angeben:

App-Komponentencode
 class App extends Component<AppProps, AppState> { constructor(props: AppProps) { super(props) this.state = { data: fakeData, } } onMoveEnd = ({ data }: OnMoveEndInfo<Language>) => { this.setState({ data: data ? [...data] : [] }) } render() { return ( <View style={styles.root}> <DraggableFlatList data={this.state.data} renderItem={this.renderItem} keyExtractor={(item) => item.id.toString()} scrollPercent={5} onMoveEnd={this.onMoveEnd} /> </View> ) } renderItem = ({ item, move, moveEnd, isActive }: RenderItemInfo<Language>) => { return ( <ListItem name={item.name} move={move} moveEnd={moveEnd} isActive={isActive} /> ) } } 


Die onMoveEnd Methode onMoveEnd aufgerufen, wenn das Element verschoben wird. In diesem Fall müssen wir die Liste mit der neuen Reihenfolge der Elemente in den Status this.setState , daher rufen wir die this.setState Methode auf.

Die renderItem Methode renderItem ein Listenelement an und akzeptiert ein Objekt vom Typ RenderItemInfo <Sprache>. Dieses Objekt enthält die folgenden Felder:

  • item - das nächste Element des Arrays, das als Daten an die Liste übergeben wird.
  • move und moveEnd sind Funktionen, die aufgerufen werden, wenn ein Listenelement verschoben wird. Die DraggableFlatList Komponente bietet diese Funktionen:
  • isActive ist ein boolesches Feld, das bestimmt, ob das Element derzeit ziehbar ist.

Die Komponente zum Anzeigen des Listenelements ist in der Tat TouchableOpacity , die bei längerem Drücken move aufruft und bei Freigabe moveEnd .

ListItem-Komponentencode
 import React from 'react' import { Text, TouchableOpacity } from 'react-native' import styles from './styles' interface ListItemProps { name: string, move: () => void, moveEnd: () => void, isActive: boolean, } const ListItem = ({ name, move, moveEnd, isActive }: ListItemProps) => { return ( <TouchableOpacity style={[styles.root, isActive && styles.active]} onLongPress={move} onPressOut={moveEnd} > <Text style={styles.text}>{name}</Text> </TouchableOpacity> ) } export default ListItem 


Stile für alle Komponenten werden in separate Dateien verschoben und hier nicht angegeben, können jedoch im Repository angezeigt werden.

Das resultierende Ergebnis:



Fügen Sie die Fähigkeit zum Wischen hinzu


Nun, wir haben den ersten Teil erfolgreich gemeistert, wir fahren mit dem zweiten Teil des Marlezon-Balletts fort.

Um die Möglichkeit zum Wischen von Listenelementen hinzuzufügen, verwenden wir das Paket " react-native-swipe-list-view .

Lassen Sie uns zunächst Folgendes installieren:

 yarn add react-native-swipe-list-view 

Dieses Paket enthält die SwipeRow Komponente, die laut Dokumentation zwei Komponenten enthalten sollte:

 <SwipeRow> <View style={hiddenRowStyle} /> <View style={visibleRowStyle} /> </SwipeRow> 

Beachten Sie, dass die erste Ansicht unter der zweiten gezeichnet wird.

Lassen Sie uns den Code der ListItem Komponente ListItem .

ListItem-Komponentencode
 import React from 'react' import { Text, TouchableOpacity, View, Image } from 'react-native' import { SwipeRow } from 'react-native-swipe-list-view' import { Language } from '../../App' import styles from './styles' const heart = require('./icons8-heart-24.png') const filledHeart = require('./icons8-heart-24-filled.png') interface ListItemProps { item: Language, move: () => void, moveEnd: () => void, isActive: boolean, onHeartPress: () => void, } const ListItem = ({ item, move, moveEnd, isActive, onHeartPress }: ListItemProps) => { return ( <SwipeRow rightOpenValue={-180}> <View style={styles.hidden}> <TouchableOpacity onPress={onHeartPress}> <Image source={item.favorite ? filledHeart : heart} /> </TouchableOpacity> </View> <TouchableOpacity activeOpacity={1} style={[styles.root, isActive && styles.active]} onLongPress={move} onPressOut={moveEnd} > <Text style={styles.text}>{item.name}</Text> </TouchableOpacity> </SwipeRow> ) } export default ListItem 


Zuerst haben wir die SwipeRow Komponente mit der Eigenschaft SwipeRow hinzugefügt, die die Entfernung bestimmt, über die das Element gewischt werden kann.

Zweitens haben wir unsere TouchableOpacity in SwipeRow und eine Ansicht hinzugefügt, die unter dieser Schaltfläche gezeichnet wird.

In dieser Ansicht wird ein Bild gezeichnet, um festzustellen, ob die Sprache ein Favorit ist. Wenn Sie darauf klicken, sollte der Wert umgekehrt werden. Da sich die Daten in der übergeordneten Komponente befinden, müssen Sie hier einen Rückruf auslösen, der diese Aktion ausführt.

Nehmen Sie die erforderlichen Änderungen an der übergeordneten Komponente vor:

App-Komponentencode
 import React, { Component } from 'react' import { View } from 'react-native' import styles from './styles' import DraggableFlatList, { RenderItemInfo, OnMoveEndInfo } from 'react-native-draggable-flatlist' import ListItem from './components/ListItem' import fakeData from './fakeData.json' export type Language = { id: number, name: string, favorite: boolean, } interface AppProps {} interface AppState { data: Array<Language> } class App extends Component<AppProps, AppState> { constructor(props: AppProps) { super(props) this.state = { data: fakeData, } } onMoveEnd = ({ data }: OnMoveEndInfo<Language>) => { this.setState({ data: data ? [...data] : [] }) } toggleFavorite = (value: Language) => { const data = this.state.data.map(item => ( item.id !== value.id ? item : { ...item, favorite: !item.favorite } )) this.setState({ data }) } render() { return ( <View style={styles.root}> <DraggableFlatList data={this.state.data} renderItem={this.renderItem} keyExtractor={(item) => item.id.toString()} scrollPercent={5} onMoveEnd={this.onMoveEnd} /> </View> ) } renderItem = ({ item, move, moveEnd, isActive }: RenderItemInfo<Language>) => { return ( <ListItem item={item} move={move} moveEnd={moveEnd} isActive={isActive} onHeartPress={() => this.toggleFavorite(item)} /> ) } } export default App 


Quellen des Projekts auf GitHub .

Das Ergebnis ist unten dargestellt:

Source: https://habr.com/ru/post/de460567/


All Articles