التنقل بالإيماءات — كيف يعمل، أنواعه وتنفيذه

المؤلف: IT Sectr نُشر: 2026-06-10 وقت القراءة: 10 دق

التنقل بالإيماءات هو نظام للتحكم في تطبيق المحمول من خلال الإيماءات اللمسية، ليحل محل الأزرار المادية في معظم الهواتف الذكية الحديثة. وفقًا لـ Android Developers (2024)، أصبح التنقل بالإيماءات هو المعيار بدءًا من Android 10، بينما انتقلت Apple إلى الإيماءات مع iPhone X في عام 2017. يشمل النظام السحب والقرص والنقر المزدوج والضغط المطول — كل إيماءة لها غرض محدد في سياق الشاشة. فهم بنية التنقل بالإيماءات ضروري لإنشاء واجهات بديهية وسريعة الاستجابة.

النقاط الرئيسية

  • التنقل بالإيماءات — التحكم في التطبيق من خلال الإيماءات اللمسية بدلاً من الأزرار
  • ثلاثة أنواع من الإيماءات: إيماءات التنقل والتلاعب والسياقية
  • Android 10+ و iOS 7+ يستخدمان الإيماءات كطريقة تنقل للنظام
  • GestureDetector — الفئة الأساسية لمعالجة الإيماءات في Android View
  • UIGestureRecognizer — الفئة المجردة لجميع الإيماءات في iOS UIKit

ما هو التنقل بالإيماءات

التنقل بالإيماءات هو أسلوب تفاعل المستخدم مع جهاز محمول من خلال تسلسلات من اللمسات والحركات والضغطات التي تتعرف عليها الشاشة اللمسية. على عكس الأزرار التقليدية، ليس للإيماءات موضع ثابت على الشاشة ويتم التعرف عليها من خلال أنماط الحركة: السحب من الحافة، القرص بإصبعين، الضغط المطول.

الانتقال إلى التنقل بالإيماءات بدأ مع iPhone X (2017)، حيث أزالت Apple زر الصفحة الرئيسية تمامًا، مستبدلة إياه بسحب من الحافة السفلية. تبعت Google الاتجاه في Android 10 (2020)، مما قدم للمستخدمين خيارًا: التنقل بثلاثة أزرار، التنقل بزرين، والتنقل الكامل بالإيماءات. وفقًا لـ StatCounter (2025)، أكثر من 75% من أجهزة Android و 95% من أجهزة iOS تستخدم التنقل بالإيماءات.

من الناحية المعمارية، التعرف على الإيماءات يتكون من ثلاث مراحل: الالتقاط (التقاط أحداث اللمس)، التعرف (تحديد نمط الحركة)، والإجراء (تنفيذ الإجراء المعين). على مستوى النظام، يحتوي Android و iOS على معالجات مدمجة لإيماءات التنقل الأساسية — السحب للخلف، الانتقال إلى الشاشة الرئيسية، فتح مبدل التطبيقات. يحتاج المطور فقط إلى دمج إيماءاته الخاصة بشكل صحيح في هذا النظام.

أنواع الإيماءات في التنقل المحمول

جميع الإيماءات اللمسية يمكن تقسيمها إلى ثلاث فئات حسب الغرض وطريقة التنفيذ. كل نوع له قواعد معالجة خاصة به وتوصيات للاستخدام في الواجهة.

إيماءات التنقل

إيماءات التنقل تتحكم في الحركة بين الشاشات: السحب من الحافة اليسرى للعودة (iOS)، السحب لأعلى لفتح مبدل التطبيقات، السحب من الحافة السفلية للعودة إلى الشاشة الرئيسية. هذه الإيماءات يتم معالجتها بواسطة النظام على مستوى النافذة ولا يجب أن تتعارض مع الإيماءات المخصصة داخل التطبيق.

إيماءات التلاعب

إيماءات التلاعب تغير موضع أو حجم أو اتجاه الكائنات على الشاشة. القرص (التكبير بإصبعين)، التدوير، السحب، التمرير السريع — كل هذه الإيماءات تتم معالجتها على مستوى View أو Composable ولا تؤثر على التنقل النظامي.

الإيماءات السياقية

الإيماءات السياقية تنشط وظائف إضافية دون الانتقال إلى شاشة أخرى. الضغط المطول (لقائمة السياق)، النقر المزدوج (للإعجاب أو التكبير)، السحب من الحافة (لفتح Drawer). هذه الإيماءات تتطلب التنفيذ الأكثر دقة لأنها قد تتداخل مع إيماءات التنقل النظامية.

نوع الإيماءةمثالمستوى المعالجةتعارض مع النظام
التنقلالسحب للخلفالنافذة / النظامأساسي
التلاعبالقرص للتكبيرViewلا
سياقيةالضغط المطولViewممكن

التنقل بالإيماءات على Android: GestureDetector و MotionEvent

Android SDK يوفر نظام معالجة إيماءات متعدد المستويات، بدءًا من MotionEvent منخفض المستوى إلى GestureDetector و GestureOverlayView عالي المستوى. اختيار المستوى الصحيح يعتمد على تعقيد الإيماءة ومتطلبات الأداء.

GestureDetector — الفئة الأساسية

GestureDetector هي فئة عالية المستوى تحول تسلسل MotionEvent إلى إيماءات محددة: onDown و onShowPress و onSingleTapUp و onScroll و onLongPress و onFling. يقوم المطور بتجاوز الطرق المطلوبة من GestureDetector.SimpleOnGestureListener ويستقبل حدثًا تم التعرف عليه جاهزًا. يُوصى بـ GestureDetector لجميع الإيماءات القياسية باستثناء التحجيم — لذلك يوجد ScaleGestureDetector.

kotlin
val gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
    override fun onFling(
        e1: MotionEvent?, e2: MotionEvent,
        velocityX: Float, velocityY: Float
    ): Boolean {
        val deltaX = e2.x - (e1?.x ?: 0f)
        return if (Math.abs(deltaX) > Math.abs(e2.y - (e1?.y ?: 0f))) {
            if (deltaX > 0) onSwipeRight() else onSwipeLeft()
            true
        } else false
    }
})

view.setOnTouchListener { _, event -> gestureDetector.onTouchEvent(event) }

TouchDelegate للأهداف المخصصة

TouchDelegate هو آلية لتوسيع منطقة اللمس لـ View. يُستخدم عندما يكون العنصر الهدف أصغر من الحد الأدنى لحجم اللمس 48dp. على سبيل المثال، زر صغير "إغلاق" في زاوية الشاشة يحصل على TouchDelegate يوسع منطقة تأثيره دون تغيير الحجم المرئي. توصي Google بـ TouchDelegate لجميع العناصر التفاعلية الأصغر من 48x48dp.

الإيماءات في Jetpack Compose

Compose يوفر معدّلات لمعالجة الإيماءات: clickable و draggable و swipeable و combinedClickable (للنقر المزدوج والضغط المطول). داخليًا، يستخدم Compose PointerInputScope للمعالجة منخفضة المستوى، لكن معظم المطورين يحتاجون فقط إلى المعدّلات عالية المستوى. للإيماءات المخصصة، استخدم pointerInput مع awaitPointerEvent.

التنقل بالإيماءات على iOS: UIGestureRecognizer و SwiftUI

iOS SDK يستخدم بنية UIGestureRecognizer — فئة أساسية مجردة تحلل تسلسل UITouch وتحدد ما إذا كان يطابق إيماءة معروفة. توصي Apple باستخدام المعرفات القياسية حيثما أمكن، وإنشاء فئات فرعية مخصصة فقط للإيماءات الفريدة.

UIGestureRecognizer في UIKit

UIKit يوفر مجموعة من المعرفات الجاهزة: UITapGestureRecognizer و UISwipeGestureRecognizer و UIPanGestureRecognizer و UIPinchGestureRecognizer و UIRotationGestureRecognizer و UILongPressGestureRecognizer. كل معرف له حالات (possible و began و changed و ended و cancelled و failed) — يتتبع المطور الحالة للتفاعل في مراحل مختلفة من الإيماءة.

swift
let swipeBack = UISwipeGestureRecognizer(
    target: self,
    action: #selector(handleSwipeBack)
)
swipeBack.direction = .right
view.addGestureRecognizer(swipeBack)

@objc func handleSwipeBack() {
    navigationController?.popViewController(animated: true)
}

الإيماءات في SwiftUI

SwiftUI يستخدم معدّلات إيماءات تصريحية، مشابهة لـ Compose: onTapGesture و onLongPressGesture و MagnificationGesture و RotationGesture و DragGesture. يعالج SwiftUI تلقائيًا التعارضات بين الإيماءات من خلال simultaneousGesture و sequencedGesture و exclusiveGesture — معدّلات تحدد أولوية الإيماءة عند التشغيل المتزامن.

swift
Image("photo")
    .gesture(
        MagnificationGesture()
            .onChanged { scale in
                self.currentScale = scale
            }
            .sequenced(before: DragGesture())
    )

InteractivePopGestureRecognizer

InteractivePopGestureRecognizer هو معرف نظامي يتحكم في إيماءة السحب للخلف في UINavigationController. افتراضيًا، يكون نشطًا لجميع الشاشات باستثناء الشاشة الجذرية. إذا كان تطبيقك يستخدم NavigationBar مخصصًا، فقد يتوقف interactivePopGestureRecognizer عن العمل — ستحتاج إلى تنشيطه برمجيًا عبر navigationController.interactivePopGestureRecognizer?.delegate.

تعارض الإيماءات النظامية والمخصصة

تعارض الإيماءات هو أحد أصعب المشكلات في التنقل بالإيماءات. عندما تتزامن إيماءة مخصصة (مثل فتح Drawer بالسحب من الحافة اليسرى) مع إيماءة نظامية (السحب للخلف على iOS أو Android)، يجب على النظام تحديد أي إيماءة لها الأولوية. معالجة هذا التعارض بشكل صحيح أمر بالغ الأهمية لتجربة المستخدم.

الحل على Android: Insets و SystemGestureExclusionRects

Android 10+ يسمح للتطبيق بحجز مناطق من الشاشة لإيماءاته الخاصة عبر WindowInsets. استخدم ViewCompat.setSystemGestureExclusionRects لتحديد المناطق التي لا يجب أن تعمل فيها إيماءات النظام. على سبيل المثال، لـ Drawer على اليسار، يمكنك استبعاد الحافة اليسرى للشاشة (بعرض يصل إلى 200dp) من السحب النظامي للخلف. حددت Google حدًا: يمكن استبعاد ما يصل إلى 200dp على كل جانب.

kotlin
val exclusionRect = Rect(0, 0, 200, height)
ViewCompat.setSystemGestureExclusionRects(
    drawerView,
    listOf(SystemGestureExclusionRect(exclusionRect))
)

الحل على iOS: UIGestureRecognizerDelegate

iOS يوفر الطريقة gestureRecognizerShouldBegin في UIGestureRecognizerDelegate، والتي تسمح للمعرف المخصص بتقرير ما إذا كان يجب أن يبدأ التعرف. لسحب Drawer من الحافة اليسرى، يمكنك التحقق من موضع اللمس: إذا كان المستخدم يسحب Drawer (المسافة تتجاوز العتبة)، تلتقط الإيماءة المخصصة التحكم. إذا لم يتم التعرف على الإيماءة، يعيد النظام التحكم إلى InteractivePopGestureRecognizer.

الأخطاء الشائعة وأفضل الممارسات

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

خطأ: تجاهل مناطق التعارض على حواف الشاشة

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

خطأ: سرعة تعرف مختلفة على Android و iOS

معلمات الإيماءات (عتبة السرعة، الحد الأدنى للمسافة) تختلف افتراضيًا بين المنصات. إذا كان تطبيقك متعدد المنصات، لا تنسخ المعلمات من منصة إلى أخرى — اختبر كل إيماءة بشكل منفصل على Android و iOS. يقوم Flutter و React Native بتكييف بعض المعلمات تلقائيًا، ولكن ليس كلها.

أفضل ممارسة: التغذية الراجعة البصرية

كل إيماءة يجب أن تكون مصحوبة بتغذية راجعة بصرية: تغيير اللون، التحويل، الرسوم المتحركة. يجب أن يفهم المستخدم أن الإيماءة تم التعرف عليها والإجراء قيد التنفيذ. على iOS، توفر المعرفات النظامية تغذية راجعة لمسية تلقائيًا؛ على Android يجب إضافتها عبر HapticFeedbackConstants.

أفضل ممارسة: إمكانية الوصول للإيماءات

ليس كل المستخدمين يمكنهم تنفيذ الإيماءات — الأشخاص ذوو المهارات الحركية المحدودة يستخدمون VoiceOver و TalkBack للتنقل. يجب أن يكون لكل إيماءة بديل زر. تطلب Google و Apple تكرار جميع إجراءات الإيماءات بعناصر تحكم متاحة لإمكانية الوصول.

الأسئلة الشائعة

ما هي المنصة التي أدخلت التنقل بالإيماءات أولاً؟

iOS — أدخلت Apple التنقل بالإيماءات مع iPhone X في عام 2017، مستبدلة زر الصفحة الرئيسية بسحب من الحافة السفلية. اتبعت Android المثال في Android 10 (2020)، مقدمة الإيماءات كبديل للأزرار.

كيف أميز بين السحب والتمرير في تطبيق مخصص؟

السحب هو حركة سريعة بسرعة عالية (بكسل/ثانية) ومتقطع. التمرير هو حركة بطيئة بسرعة منخفضة ومستمر. استخدم velocityX/Y للتمييز: العتبة عادة 500—1000 بكسل/ثانية حسب المنصة.

هل يمكن تعطيل التنقل بالإيماءات النظامي في التطبيق؟

لا — لا يسمح Android و iOS للتطبيق بتعطيل التنقل بالإيماءات النظامي. يمكنك فقط حجز مناطق الشاشة عبر exclusion rects (Android) أو gestureRecognizerShouldBegin (iOS).

كيف أختبر الإيماءات على المحاكي؟

محاكي Android يدعم اللمس المتعدد عبر Ctrl+نقرة (إضافة إصبع ثانٍ). محاكي iOS يستخدم Option+نقرة لإصبعين. يستخدم Flutter test WidgetTester.timedDrag لمحاكاة السحبات في اختبارات الوحدة.

ما هي حرب الإيماءات وكيف أتجنبها؟

حرب الإيماءات (Gesture War) هي تعارض بين معرفين عندما يحاول كلاهما معالجة نفس اللمسة. تجنبها من خلال الأولويات: في iOS استخدم require(toFail:)، في Compose استخدم sequentialGesture و exclusiveGesture. يستخدم Flutter GestureArena للحل التلقائي.

الخلاصة

  • التنقل بالإيماءات — التحكم في التطبيق من خلال الإيماءات اللمسية، معيار على Android 10+ و iOS 7+
  • ثلاث فئات من الإيماءات: التنقل (السحبات)، التلاعب (القرص، التدوير)، والسياقية (الضغط المطول)
  • GestureDetector على Android و UIGestureRecognizer على iOS — الفئات الأساسية لمعالجة الإيماءات
  • Jetpack Compose و SwiftUI يوفران معدّلات تصريحية لجميع الإيماءات القياسية
  • تعارض الإيماءات يُحل عبر exclusion rects (Android) و gestureRecognizerShouldBegin (iOS)
  • التغذية الراجعة البصرية وإمكانية الوصول — متطلبات إلزامية للتنقل بالإيماءات
  • معلمات الإيماءات تختلف بين المنصات — لا تنسخ العتبة والسرعة مباشرة

سنقوم بتطوير تطبيق جوال جاهز

تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.

مناقشة المشروع

اقرأ أيضًا