من الصعب اليوم مفاجأة أي شخص لديه القدرة على تمرير عناصر القائمة في تطبيقات الهاتف المحمول. كان أحد تطبيقات التفاعل الأصلي لدينا مثل هذه الوظيفة ، ولكن في الآونة الأخيرة كانت هناك حاجة لتوسيعها مع القدرة على سحب وإسقاط عناصر القائمة. وبما أن عملية البحث عن حل كلفتني قدرًا معينًا من الخلايا العصبية ، فقد قررت تقديم مقالة قصيرة من أجل توفير وقت ثمين للأجيال القادمة.

في تطبيقنا ، استخدمنا حزمة
react-native-swipe-list-view
القائمة القابلة للتمرير السريع. كان الفكر الأول هو اتخاذ بعض الحزم مع وظيفة drag'n'drop وعبور القنفذ بثعبان.
أعطى البحث على شبكة الإنترنت ثلاثة مرشحين:
react-native-draggable-list
react-native-sortable-list
react-native-draggable-list
react-native-sortable-list
react-native-draggable-flatlist
react-native-sortable-list
react-native-draggable-flatlist
react-native-sortable-list
react-native-draggable-flatlist
.
باستخدام الحزمة الأولى ، لم يكن من الممكن تشغيل المثال المرفق (ولكن ليس لي فقط ، تتم الإشارة إلى المشكلة المقابلة في
المشكلات ).
اضطررت إلى العبث بالحزمة الثانية ، لكنني تمكنت من إنشاء قائمة قابلة للسحب والقابلة للتبديل. ومع ذلك ، لم يكن مصدر إلهام النتيجة - كان العنصر يومض بشكل خجل: وميض إعادة الرسم أو سقوط عناصر أبعد من القائمة أو حتى اختفائها. أصبح من الواضح أنه في هذا الشكل لا يمكن استخدامه.
في البداية ، تصرفت الحزمة الأخيرة أيضًا كسيدة متقلبة ، ولكن اتضح بعد ذلك أنني لم أكن أعرف كيف أطبخها. بعد أن حصلت على مفتاح قلب هذه "السيدة" ، تمكنت من تحقيق نتيجة مقبولة.
في مشروعنا ، كانت هناك قائمة قابلة للضبط تحتاج إلى ربط السحب والإفلات ، ولكن من الناحية العملية ، من الأفضل أن تبدأ من الحافة الأخرى: قم أولاً بوضع قائمة قابلة للسحب ثم أضف القدرة على التمرير السريع.
من المفترض أن يعرف القراء كيفية إنشاء مشروع رد فعل أصلي ، لذلك دعونا نركز على إنشاء القائمة التي نحتاج إليها. المثال الذي تمت مناقشته أدناه هو رمز TypeScript.
صنع قائمة قابلة للسحب
لذلك ، لنبدأ بتثبيت الحزمة:
yarn add react-native-draggable-flatlist
نحن نستورد الوحدات اللازمة:
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'
هنا
DraggableFlatList
هو مكون من الحزمة المثبتة التي تقوم بتنفيذ
ListItem
السحب والإفلات ،
ListItem
هو
fakeData
لعرض عنصر قائمة (سيتم تقديم الرمز أدناه) ،
fakeData
هو ملف json يحتوي على بيانات مزيفة - في هذه الحالة ، مجموعة من الكائنات من النموذج:
{"id": 0, "name": "JavaScript", "favorite": false}
في تطبيق حقيقي ، من المرجح أن تأتي هذه البيانات إلى المكون الخاص بك من الدعائم أو سيتم تنزيلها من الشبكة ، ولكن في حالتنا سوف ندير القليل من الدم.
نظرًا لاستخدام TypeScript في هذا المثال ، فإننا نصف بعض الكيانات:
type Language = { id: number, name: string, favorite: boolean, } interface AppProps {} interface AppState { data: Array<Language> }
يخبرنا نوع
Language
بالمجالات التي ستحتوي عليها عناصر القائمة.
في هذا المثال ، لن نحصل على أي شيء من الدعائم ، لذلك واجهة
AppProps
تافهة ، وفي القصة سنقوم بتخزين مجموعة من كائنات
Language
، المشار إليها في واجهة
AppState
.
نظرًا لأن رمز المكون ليس كبيرًا جدًا ، فسأقدمه بالكامل:
رمز مكون التطبيق 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} /> ) } }
يتم
onMoveEnd
الأسلوب
onMoveEnd
عند نقل العنصر. في هذه الحالة ، نحتاج إلى وضع القائمة بترتيب جديد للعناصر في الولاية ، لذلك نسميها
this.setState
.
renderItem
طريقة
renderItem
عنصر قائمة وتقبل كائنًا من النوع RenderItemInfo <Language>. يتضمن هذا الكائن الحقول التالية:
item
- تم تمرير العنصر التالي للصفيف كبيانات إلى القائمة ،move
و moveEnd
هي وظائف تسمى عند نقل عنصر قائمة ، يوفر مكون DraggableFlatList
هذه الوظائف ،isActive
هو حقل منطقي يحدد ما إذا كان العنصر قابلاً للسحب حاليًا أم لا.
مكون عرض عنصر القائمة ، في الواقع ، هو
TouchableOpacity
، والذي
move
عند الضغط عليه لفترة طويلة ، وعندما
move
،
move
moveEnd
.
رمز مكون 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
يتم نقل أنماط جميع المكونات إلى ملفات منفصلة ولا يتم تقديمها هنا ، ولكن يمكن عرضها في
المستودع .
النتيجة الناتجة:

إضافة القدرة على انتقاد
حسنًا ، لقد تعاملنا بنجاح مع الجزء الأول ، انتقلنا إلى الجزء الثاني من رقص مارليزون.
لإضافة القدرة على تمرير عناصر القائمة ، نستخدم حزمة
react-native-swipe-list-view
.
للبدء ، دعنا نثبته:
yarn add react-native-swipe-list-view
تحتوي هذه الحزمة على مكون
SwipeRow
، والذي يجب أن يتضمن مكونين:
<SwipeRow> <View style={hiddenRowStyle} /> <View style={visibleRowStyle} /> </SwipeRow>
لاحظ أن العرض الأول يتم رسمه تحت الثانية.
دعنا نغير رمز مكون
ListItem
.
رمز مكون 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
أولاً ، أضفنا مكون
SwipeRow
مع خاصية
SwipeRow
، التي تحدد المسافة التي يمكن تمرير العنصر إليها.
ثانياً ، قمنا بتحريك
SwipeRow
بنا داخل
SwipeRow
بإضافة طريقة عرض ، والتي سيتم رسمها تحت هذا الزر.
داخل طريقة العرض هذه ، يتم رسم صورة لتحديد ما إذا كانت اللغة مفضلة. عند النقر فوقها ، يجب عكس القيمة ، وحيث أن البيانات في المكون الأصلي ، فأنت بحاجة إلى رمي رد اتصال هنا يقوم بتنفيذ هذا الإجراء.
قم بإجراء التغييرات الضرورية على المكون الأصل:
رمز مكون التطبيق 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
مصادر المشروع على
جيثب .
والنتيجة معروضة أدناه:
