الفرق بين المراجعتين لصفحة: «ReactNative/panresponder»
جميل-بيلوني (نقاش | مساهمات) |
رقية-بورية (نقاش | مساهمات) ط مراجعة |
||
سطر 1: | سطر 1: | ||
<noinclude>{{DISPLAYTITLE:PanResponder في React Native}}</noinclude> | <noinclude>{{DISPLAYTITLE:PanResponder في React Native}}</noinclude> | ||
توحِّد <code>PanResponder</code> العديد من اللمسات ضمن إيماءةٍ واحدة، وتجعل الإيماءة أحاديّة اللّمسة متجاوبةً مع اللّمسات الإضافيّة، ويمكن | توحِّد <code>PanResponder</code> العديد من اللمسات ضمن إيماءةٍ واحدة، وتجعل الإيماءة أحاديّة اللّمسة متجاوبةً مع اللّمسات الإضافيّة، ويمكن استخدامها للتعرُّف على الإيماءات الأساسيّة متعدّدة اللّمسات. | ||
تحتوي <code>PanResponder</code> بشكل افتراضيٍّ على معالجٍ باسم <code>InteractionManager</code> لمنع أحداث JS طويلة الأمد من مقاطعة الإيماءات | تحتوي <code>PanResponder</code> بشكل افتراضيٍّ على معالجٍ باسم <code>InteractionManager</code> لمنع أحداث JS طويلة الأمد من مقاطعة الإيماءات الجارية، وتُقدِّم <code>panresponder</code> غلافًا يمكن التّنبؤ به لمعالجات المستجيب (responder handlers) المُقدَّم من [[ReactNative/gesture responder system|نظام مستجيب الإيماءات(gesture responder system)]] ، حيث تعطي لكلّ معالجٍ كائنًا جديدًا <code>gestureState</code> بجانب كائن الحدَث الأصيل: <syntaxhighlight lang="javascript"> | ||
onPanResponderMove: (event, gestureState) => {} | onPanResponderMove: (event, gestureState) => {} | ||
</syntaxhighlight>الحدَث الأصيل هو عبارة عن حدَث لمسةٍ مصطنَعةٍ (synthetic) على شكل كائن <code>[[ReactNative/pressevent|PressEvent]]</code>. | </syntaxhighlight>الحدَث الأصيل هو عبارة عن حدَث لمسةٍ مصطنَعةٍ (synthetic) على شكل كائن <code>[[ReactNative/pressevent|PressEvent]]</code>. | ||
سطر 10: | سطر 8: | ||
يتضمَّن الكائن <code>gestureState</code> ما يلي: | يتضمَّن الكائن <code>gestureState</code> ما يلي: | ||
* <code>stateID</code>: مُعرِّف (ID) الكائن <code>gestureState</code> ويبقى ما دامت هنالك لمسة واحدة على | * <code>stateID</code>: مُعرِّف (ID) الكائن <code>gestureState</code>، ويبقى ما دامت هنالك لمسة واحدة على الأقلّ على الشّاشة. | ||
* <code>moveX</code>: الإحداثيات | * <code>moveX</code>: الإحداثيات الأفقيّة الأخيرة على الشّاشة للَّمسة المتحركة حديثًا. | ||
* <code>moveY</code>: الإحداثيات العموديّة الأخيرة على | * <code>moveY</code>: الإحداثيات العموديّة الأخيرة على الشّاشة للّمسة المتحركة حديثًا. | ||
* <code>x0</code>: الإحداثيات | * <code>x0</code>: الإحداثيات الأفقيّة على الشّاشة لمكان منح (grant) المستجيب. | ||
* <code>y0</code>: الإحداثيات العموديّة على | * <code>y0</code>: الإحداثيات العموديّة على الشّاشة لمكان منح المستجيب. | ||
* <code>dx</code>: المسافة | * <code>dx</code>: المسافة الأفقيّة المجمَّعة للإيماءة من لحظة بدء اللّمسة. | ||
* <code>dy</code>: المسافة العموديّة المجمَّعة للإيماءة من لحظة بدء | * <code>dy</code>: المسافة العموديّة المجمَّعة للإيماءة من لحظة بدء اللّمسة. | ||
* <code>vx</code>: | * <code>vx</code>: السّرعة الأفقية الحاليّة للإيماءة. | ||
* <code>vy</code>: | * <code>vy</code>: السّرعة العموديّة الحاليّة للإيماءة. | ||
* <code>numberActiveTouches</code>: عدد | * <code>numberActiveTouches</code>: عدد اللّمسات الحالية على الشّاشة. | ||
== نموذج الاستخدام == | == نموذج الاستخدام == | ||
سطر 68: | سطر 66: | ||
== مثال == | == مثال == | ||
تُستخدم <code>panresponder</code> مع الواجهة البرمجية (API) <code>[[ReactNative/animations|Animated]]</code> للمساعدة في إنشاء إيماءاتٍ معقّدةٍ في واجهة المستخدم (UI)، | تُستخدم <code>panresponder</code> مع الواجهة البرمجية (API) <code>[[ReactNative/animations|Animated]]</code> للمساعدة في إنشاء إيماءاتٍ معقّدةٍ في واجهة المستخدم (UI)، ويحتوي المثال التالي على المكون المتحرّك <code>[[ReactNative/view|View]]</code>، والذي يمكن سحبه بحريّةٍ عبر الشّاشة: | ||
* مثال لمكون | * مثال لمكون الدّالة (Function Component) | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
سطر 116: | سطر 114: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
* مثال لمكون | * مثال لمكون الصّنف (Class Component) | ||
<syntaxhighlight lang="javascript"> | <syntaxhighlight lang="javascript"> | ||
سطر 197: | سطر 195: | ||
</syntaxhighlight>وبالنسبة للأحداث التي لها مكافئات في طور الالتقاط (أي طور إنتشار الحدث من العنصر الجذر وحتى العنصر الهدف capture phase)، نُحدِّث <code>gestureState</code> مرةً واحدةً فقط أثناء طور الالتقاط (capture phase) مباشرةً، ويمكن استخدامه في طور الانتشار (bubble phase، أو طور الغليان أو الفوران حيث ينتشر الحدث من العنصر الهدف وحتى الأعلى باتجاه العنصر الجذر) أيضًا. | </syntaxhighlight>وبالنسبة للأحداث التي لها مكافئات في طور الالتقاط (أي طور إنتشار الحدث من العنصر الجذر وحتى العنصر الهدف capture phase)، نُحدِّث <code>gestureState</code> مرةً واحدةً فقط أثناء طور الالتقاط (capture phase) مباشرةً، ويمكن استخدامه في طور الانتشار (bubble phase، أو طور الغليان أو الفوران حيث ينتشر الحدث من العنصر الهدف وحتى الأعلى باتجاه العنصر الجذر) أيضًا. | ||
يجب الانتباه عند التعامل مع الاستجابات <code>onStartShould*</code> | يجب الانتباه عند التعامل مع الاستجابات <code>onStartShould*</code> لأنّها تعكس <code>gestureState</code> لأحداث البدء، أو الانتهاء لطوري العقدة (الفقاعة أو الالتقاط)، فعندما تصبح العقدة هي المستجيب يمكن الوثوق بأن الإيماءة تعالج كلّ حدث بدءٍ، أو انتهاءٍ، ويحدَّث <code>gestureState</code> تبعًا لذلك، وقد لا يكون <code>numberActiveTouches</code> دقيقًا تمامًا إلّا إذا كنت أنت المستجيب. | ||
== مصادر == | == مصادر == |
مراجعة 10:06، 22 يناير 2021
توحِّد PanResponder
العديد من اللمسات ضمن إيماءةٍ واحدة، وتجعل الإيماءة أحاديّة اللّمسة متجاوبةً مع اللّمسات الإضافيّة، ويمكن استخدامها للتعرُّف على الإيماءات الأساسيّة متعدّدة اللّمسات.
تحتوي PanResponder
بشكل افتراضيٍّ على معالجٍ باسم InteractionManager
لمنع أحداث JS طويلة الأمد من مقاطعة الإيماءات الجارية، وتُقدِّم panresponder
غلافًا يمكن التّنبؤ به لمعالجات المستجيب (responder handlers) المُقدَّم من نظام مستجيب الإيماءات(gesture responder system) ، حيث تعطي لكلّ معالجٍ كائنًا جديدًا gestureState
بجانب كائن الحدَث الأصيل:
onPanResponderMove: (event, gestureState) => {}
الحدَث الأصيل هو عبارة عن حدَث لمسةٍ مصطنَعةٍ (synthetic) على شكل كائن PressEvent
.
يتضمَّن الكائن gestureState
ما يلي:
stateID
: مُعرِّف (ID) الكائنgestureState
، ويبقى ما دامت هنالك لمسة واحدة على الأقلّ على الشّاشة.moveX
: الإحداثيات الأفقيّة الأخيرة على الشّاشة للَّمسة المتحركة حديثًا.moveY
: الإحداثيات العموديّة الأخيرة على الشّاشة للّمسة المتحركة حديثًا.x0
: الإحداثيات الأفقيّة على الشّاشة لمكان منح (grant) المستجيب.y0
: الإحداثيات العموديّة على الشّاشة لمكان منح المستجيب.dx
: المسافة الأفقيّة المجمَّعة للإيماءة من لحظة بدء اللّمسة.dy
: المسافة العموديّة المجمَّعة للإيماءة من لحظة بدء اللّمسة.vx
: السّرعة الأفقية الحاليّة للإيماءة.vy
: السّرعة العموديّة الحاليّة للإيماءة.numberActiveTouches
: عدد اللّمسات الحالية على الشّاشة.
نموذج الاستخدام
const ExampleComponent = () => {
const panResponder = React.useRef(
PanResponder.create({
// طلب المكوِّن ليكون المستجيب
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) =>
true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
true,
onPanResponderGrant: (evt, gestureState) => {
// بدأت الإيماءة. أظهر مراجعة مرئية ليعلم المستخدم ما يحدث
//بالقيمة الصفرية gestureState.d{x,y} سيتم الآن تهيئة
},
onPanResponderMove: (evt, gestureState) => {
// gestureState.move{X,Y}آخر مسافة محدَّثة للحركة
//المسافة المجمَّعة للإيماءة منذ أن أصبح المكون مستجيبا
// gestureState.d{x,y}
},
onPanResponderTerminationRequest: (evt, gestureState) =>
true,
onPanResponderRelease: (evt, gestureState) => {
// حررَ المستخدم جميع اللمسات عند ظهور المستجيب
// مما يدل عمليًا على نجاح الإيماءة
},
onPanResponderTerminate: (evt, gestureState) => {
// أصبح مكوِّن آخر هو المستجيب
// لذا سيتم إنهاء هذه الإيماءة
},
onShouldBlockNativeResponder: (evt, gestureState) => {
// عند منعَ المكون المكونات الأصيلة من true إرجاع قيمة
// true والقيمة الافتراضية هي، JS أن تصبح مستجيب
// فقط Android مدعومة حاليا في نظام
return true;
}
})
).current;
return <View {...panResponder.panHandlers} />;
};
مثال
تُستخدم panresponder
مع الواجهة البرمجية (API) Animated
للمساعدة في إنشاء إيماءاتٍ معقّدةٍ في واجهة المستخدم (UI)، ويحتوي المثال التالي على المكون المتحرّك View
، والذي يمكن سحبه بحريّةٍ عبر الشّاشة:
- مثال لمكون الدّالة (Function Component)
const ExampleComponent = () => {
const panResponder = React.useRef(
PanResponder.create({
// طلب المكوِّن ليكون المستجيب
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) =>
true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
true,
onPanResponderGrant: (evt, gestureState) => {
// بدأت الإيماءة. أظهر مراجعة مرئية ليعلم المستخدم ما يحدث
//بالقيمة الصفرية gestureState.d{x,y} سيتم الآن تهيئة
},
onPanResponderMove: (evt, gestureState) => {
// gestureState.move{X,Y}آخر مسافة محدَّثة للحركة
//المسافة المجمَّعة للإيماءة منذ أن أصبح المكون مستجيبا
// gestureState.d{x,y}
},
onPanResponderTerminationRequest: (evt, gestureState) =>
true,
onPanResponderRelease: (evt, gestureState) => {
// حررَ المستخدم جميع اللمسات عند ظهور المستجيب
// مما يدل عمليًا على نجاح الإيماءة
},
onPanResponderTerminate: (evt, gestureState) => {
// أصبح مكوِّن آخر هو المستجيب
// لذا سيتم إنهاء هذه الإيماءة
},
onShouldBlockNativeResponder: (evt, gestureState) => {
// عند منعَ المكون المكونات الأصيلة من true إرجاع قيمة
// true والقيمة الافتراضية هي، JS أن تصبح مستجيب
// فقط Android مدعومة حاليا في نظام
return true;
}
})
).current;
return <View {...panResponder.panHandlers} />;
};
- مثال لمكون الصّنف (Class Component)
const ExampleComponent = () => {
const panResponder = React.useRef(
PanResponder.create({
// طلب المكوِّن ليكون المستجيب
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) =>
true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
true,
onPanResponderGrant: (evt, gestureState) => {
// بدأت الإيماءة. أظهر مراجعة مرئية ليعلم المستخدم ما يحدث
//بالقيمة الصفرية gestureState.d{x,y} سيتم الآن تهيئة
},
onPanResponderMove: (evt, gestureState) => {
// gestureState.move{X,Y}آخر مسافة محدَّثة للحركة
//المسافة المجمَّعة للإيماءة منذ أن أصبح المكون مستجيبا
// gestureState.d{x,y}
},
onPanResponderTerminationRequest: (evt, gestureState) =>
true,
onPanResponderRelease: (evt, gestureState) => {
// حررَ المستخدم جميع اللمسات عند ظهور المستجيب
// مما يدل عمليًا على نجاح الإيماءة
},
onPanResponderTerminate: (evt, gestureState) => {
// أصبح مكوِّن آخر هو المستجيب
// لذا سيتم إنهاء هذه الإيماءة
},
onShouldBlockNativeResponder: (evt, gestureState) => {
// عند منعَ المكون المكونات الأصيلة من true إرجاع قيمة
// true والقيمة الافتراضية هي، JS أن تصبح مستجيب
// فقط Android مدعومة حاليا في نظام
return true;
}
})
).current;
return <View {...panResponder.panHandlers} />;
};
جرِّب مثال PanResponder في RNTester.
التوابع
create()
static create(config)
المعاملات
الاسم | النوع | مطلوب | الوصف |
---|---|---|---|
config
|
كائن (object) | نعم | الشرح في الأسفل |
يُقدِّم الكائن config
إصدارات محسَّنة لجميع ردود نداء المستجيب (responder callbacks)، والذي بدوره لا يُقدِّم PressEvent
فقط بل حالة الإيماءات PanResponder
أيضًا، وذلك باستبدال الكلمة Responder
بالكلمة PanResponder
في كل استجابة نموذجيّةٍ onResponder*
. كمثال على ذلك سيبدو الكائن config
كما يلي:
onMoveShouldSetPanResponder: (e, gestureState) => {...}
onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}
onStartShouldSetPanResponder: (e, gestureState) => {...}
onStartShouldSetPanResponderCapture: (e, gestureState) => {...}
onPanResponderReject: (e, gestureState) => {...}
onPanResponderGrant: (e, gestureState) => {...}
onPanResponderStart: (e, gestureState) => {...}
onPanResponderEnd: (e, gestureState) => {...}
onPanResponderRelease: (e, gestureState) => {...}
onPanResponderMove: (e, gestureState) => {...}
onPanResponderTerminate: (e, gestureState) => {...}
onPanResponderTerminationRequest: (e, gestureState) => {...}
onShouldBlockNativeResponder: (e, gestureState) => {...}
وبالنسبة للأحداث التي لها مكافئات في طور الالتقاط (أي طور إنتشار الحدث من العنصر الجذر وحتى العنصر الهدف capture phase)، نُحدِّث gestureState
مرةً واحدةً فقط أثناء طور الالتقاط (capture phase) مباشرةً، ويمكن استخدامه في طور الانتشار (bubble phase، أو طور الغليان أو الفوران حيث ينتشر الحدث من العنصر الهدف وحتى الأعلى باتجاه العنصر الجذر) أيضًا.
يجب الانتباه عند التعامل مع الاستجابات onStartShould*
لأنّها تعكس gestureState
لأحداث البدء، أو الانتهاء لطوري العقدة (الفقاعة أو الالتقاط)، فعندما تصبح العقدة هي المستجيب يمكن الوثوق بأن الإيماءة تعالج كلّ حدث بدءٍ، أو انتهاءٍ، ويحدَّث gestureState
تبعًا لذلك، وقد لا يكون numberActiveTouches
دقيقًا تمامًا إلّا إذا كنت أنت المستجيب.