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:
