Hari ini sulit untuk mengejutkan siapa pun dengan kemampuan untuk menggesek item daftar di aplikasi seluler. Salah satu aplikasi asli-reaksi kami juga memiliki fungsi seperti itu, tetapi baru-baru ini ada kebutuhan untuk mengembangkannya dengan kemampuan untuk menarik dan melepaskan item daftar. Dan karena proses menemukan solusi menghabiskan sel-sel saraf dalam jumlah tertentu, saya memutuskan untuk mengajukan artikel pendek untuk menghemat waktu berharga bagi generasi mendatang.

Dalam aplikasi kami, kami menggunakan paket
react-native-swipe-list-view
untuk membuat daftar swipeable. Pikiran pertama adalah mengambil beberapa paket dengan fungsionalitas drag'n'drop dan menyeberang landak dengan seekor ular.
Pencarian di internet memberi tiga kandidat:
react-native-draggable-list
,
react-native-sortable-list
dan
react-native-draggable-flatlist
.
Menggunakan paket pertama, itu tidak mungkin untuk menjalankan bahkan contoh terlampir (namun, tidak hanya bagi saya, masalah yang sesuai ditunjukkan dalam
masalah ).
Saya harus mengotak-atik paket kedua, tetapi saya berhasil membuat daftar yang dapat diseret & digesek. Namun, hasilnya tidak diilhami - komponennya tanpa berkedip berkedip: berkedip redraw, elemen jatuh jauh di luar daftar, atau bahkan hilangnya mereka. Menjadi jelas bahwa dalam bentuk ini tidak dapat digunakan.
Pada awalnya, paket terakhir juga berperilaku seperti wanita yang berubah-ubah, tetapi kemudian ternyata saya tidak tahu cara memasaknya. Setelah mengambil kunci ke jantung "wanita" ini, saya berhasil mencapai hasil yang dapat diterima.
Di proyek kami, ada daftar gesek yang harus Anda kencangkan tarik dan lepas, tetapi dalam praktiknya lebih baik mulai dari ujung yang lain: pertama buat daftar yang dapat diseret lalu tambahkan kemampuan untuk menggesek.
Pembaca seharusnya tahu cara membuat proyek yang bereaksi asli, jadi mari kita fokus membuat daftar yang kita butuhkan. Contoh yang dibahas di bawah ini adalah kode TypeScript.
Membuat daftar yang dapat diseret
Jadi, mari kita mulai dengan menginstal paket:
yarn add react-native-draggable-flatlist
Kami mengimpor modul yang diperlukan:
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'
Di sini
DraggableFlatList
adalah komponen dari paket yang diinstal yang mengimplementasikan fungsi drag and drop,
ListItem
adalah komponen kami untuk menampilkan item daftar (kode akan disajikan di bawah ini),
fakeData
adalah file json yang berisi data palsu - dalam hal ini, array objek berupa:
{"id": 0, "name": "JavaScript", "favorite": false}
Dalam aplikasi nyata, data ini kemungkinan besar akan datang ke komponen Anda dari alat peraga atau akan diunduh dari jaringan, tetapi dalam kasus kami, kami akan mengelola dengan sedikit darah.
Karena TypeScript digunakan dalam contoh ini, kami menjelaskan beberapa entitas:
type Language = { id: number, name: string, favorite: boolean, } interface AppProps {} interface AppState { data: Array<Language> }
Jenis
Language
memberi tahu kita bidang mana yang akan dimiliki item daftar.
Dalam contoh ini, kita tidak akan mendapatkan apa pun dari alat peraga, sehingga antarmuka
AppProps
sepele, dan dalam cerita ini kita akan menyimpan berbagai objek
Language
, yang ditunjukkan dalam antarmuka
AppState
.
Karena kode komponen tidak terlalu besar, saya akan memberikannya secara keseluruhan:
Kode komponen aplikasi 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} /> ) } }
Metode
onMoveEnd
dipanggil saat item dipindahkan. Dalam hal ini, kita perlu meletakkan daftar dengan tatanan elemen baru di negara, jadi kita memanggil metode
this.setState
.
Metode
renderItem
item daftar dan menerima objek bertipe RenderItemInfo <Language>. Objek ini mencakup bidang-bidang berikut:
item
- elemen berikutnya dari array yang dilewatkan sebagai data ke daftar,move
and moveEnd
adalah fungsi yang dipanggil saat item daftar dipindahkan, komponen DraggableFlatList
menyediakan fungsi-fungsi ini,isActive
adalah bidang boolean yang menentukan apakah item saat ini dapat diseret.
Komponen untuk menampilkan item daftar, pada kenyataannya,
TouchableOpacity
, yang, dengan pers lama, panggilan
move
, dan ketika dirilis, itu
moveEnd
.
Kode komponen ListItem 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
Gaya untuk semua komponen dipindahkan ke file yang terpisah dan tidak diberikan di sini, tetapi mereka dapat dilihat di
repositori .
Hasil yang dihasilkan:

Tambahkan kemampuan untuk menggesek
Nah, kami berhasil mengatasi bagian pertama, kami melanjutkan ke bagian kedua dari balet Marlezon.
Untuk menambahkan kemampuan untuk menggesek item daftar, kami menggunakan paket
react-native-swipe-list-view
.
Untuk memulai, mari kita instal:
yarn add react-native-swipe-list-view
Paket ini berisi komponen
SwipeRow
, yang, menurut dokumentasi, harus mencakup dua komponen:
<SwipeRow> <View style={hiddenRowStyle} /> <View style={visibleRowStyle} /> </SwipeRow>
Perhatikan bahwa Tampilan pertama diambil di bawah yang kedua.
Mari kita ubah kode komponen
ListItem
.
Kode komponen ListItem 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
Pertama, kami menambahkan komponen
SwipeRow
dengan properti
SwipeRow
, yang menentukan jarak di mana elemen dapat digesek.
Kedua, kami memindahkan
TouchableOpacity
kami di dalam
SwipeRow
dan menambahkan Tampilan, yang akan digambar di bawah tombol ini.
Di dalam Tampilan ini, gambar diambil untuk menentukan apakah bahasa itu favorit. Ketika Anda mengkliknya, nilainya harus dibalik, dan karena data ada di komponen induk, Anda perlu melakukan panggilan balik di sini yang melakukan tindakan ini.
Buat perubahan yang diperlukan untuk komponen induk:
Kode komponen aplikasi 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
Sumber proyek di
GitHub .
Hasilnya disajikan di bawah ini:
