إدارة الصور المتحركة والتطبيقات المصغّرة باستخدام MotionLayout

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

يعمل MotionLayout على سدّ الفجوة بين انتقالات التصميم والتعامل مع الحركة المعقّدة، ما يوفّر مزيجًا من الميزات بين إطار عمل الصور المتحركة للمواقع وTransitionManager و CoordinatorLayout.

الشكل 1. الحركة الأساسية التي يتم التحكم فيها باللمس.

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

MotionLayout هو مصطلح معبّر تمامًا، ما يعني أنّه يمكنك وصف أي عمليات انتقال في XML مهما كانت معقدة.

اعتبارات التصميم

MotionLayout مخصص لنقل عناصر واجهة المستخدم وتغيير حجمها وتحريكها التي يتفاعل معها المستخدمون، مثل الأزرار وأشرطة العناوين. لا تستخدم الحركة في تطبيقك كتأثير خاص غير مبرر. استخدمها لمساعدة المستخدمين في فهم وظيفة تطبيقك. لمزيد من المعلومات حول تصميم تطبيقك باستخدام الحركة، راجع قسم "التصميم المتعدد الأبعاد" فهم الحركة.

البدء

اتّبِع هذه الخطوات لبدء استخدام "MotionLayout" في مشروعك.

  1. إضافة التبعية ConstraintLayout: لاستخدام MotionLayout في مشروعك، أضِف تبعية ConstraintLayout 2.0 إلى ملف build.gradle لتطبيقك. إذا كنت تستخدم AndroidX، أضِف التبعية التالية:

    رائع

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.0-alpha13"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13"
    }
    

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.0-alpha13")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.0-alpha13")
    }
    
  2. إنشاء ملف MotionLayout: MotionLayout هي فئة فرعية من ConstraintLayout، لذا يمكنك تحويل أي ConstraintLayout حالية إلى MotionLayout عن طريق استبدال اسم الفئة في ملف مورد التنسيق، كما هو موضّح في الأمثلة التالية:

    AndroidX

    <!-- before: ConstraintLayout -->
    <androidx.constraintlayout.widget.ConstraintLayout .../>
    <!-- after: MotionLayout -->
    <androidx.constraintlayout.motion.widget.MotionLayout .../>
              

    مكتبة الدعم

    <!-- before: ConstraintLayout -->
    <android.support.constraint.ConstraintLayout .../>
    <!-- after: MotionLayout -->
    <android.support.constraint.motion.MotionLayout .../>
              

    في ما يلي مثال كامل على ملف MotionLayout يحدّد التنسيق الموضّح في الشكل 1:

    AndroidX

    <?xml version="1.0" encoding="utf-8"?>
    <!-- activity_main.xml -->
    <androidx.constraintlayout.motion.widget.MotionLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/motionLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutDescription="@xml/scene_01"
        tools:showPaths="true">
    
        <View
            android:id="@+id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:background="@color/colorAccent"
            android:text="Button" />
    
    </androidx.constraintlayout.motion.widget.MotionLayout>
            

    مكتبة الدعم

    <?xml version="1.0" encoding="utf-8"?>
    <!-- activity_main.xml -->
    <android.support.constraint.motion.MotionLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/motionLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutDescription="@xml/scene_01"
        tools:showPaths="true">
    
        <View
            android:id="@+id/button"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:background="@color/colorAccent"
            android:text="Button" />
    
    </android.support.constraint.motion.MotionLayout>
            
  3. إنشاء MotionScene: في المثال MotionLayout السابق، تشير السمة app:layoutDescription إلى مشهد حركة. مشهد الحركة هو ملف موارد XML. في العنصر الجذر <MotionScene>، يحتوي مشهد الحركة على جميع أوصاف الحركة للتنسيق المقابل. للحفاظ على معلومات التصميم منفصلة عن أوصاف الحركة، تشير كل سمة MotionLayout إلى مشهد حركة منفصل. وتحظى التعريفات في مشهد الحركة بالأولوية على أي تعريفات مشابهة واردة في MotionLayout.

    في ما يلي مثال على ملف مشهد للحركة يصف الحركة الأفقية الأساسية في الشكل 1:

    <?xml version="1.0" encoding="utf-8"?>
    <MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:motion="http://schemas.android.com/apk/res-auto">
    
        <Transition
            motion:constraintSetStart="@+id/start"
            motion:constraintSetEnd="@+id/end"
            motion:duration="1000">
            <OnSwipe
                motion:touchAnchorId="@+id/button"
                motion:touchAnchorSide="right"
                motion:dragDirection="dragRight" />
        </Transition>
    
        <ConstraintSet android:id="@+id/start">
            <Constraint
                android:id="@+id/button"
                android:layout_width="64dp"
                android:layout_height="64dp"
                android:layout_marginStart="8dp"
                motion:layout_constraintBottom_toBottomOf="parent"
                motion:layout_constraintStart_toStartOf="parent"
                motion:layout_constraintTop_toTopOf="parent" />
        </ConstraintSet>
    
        <ConstraintSet android:id="@+id/end">
            <Constraint
                android:id="@+id/button"
                android:layout_width="64dp"
                android:layout_height="64dp"
                android:layout_marginEnd="8dp"
                motion:layout_constraintBottom_toBottomOf="parent"
                motion:layout_constraintEnd_toEndOf="parent"
                motion:layout_constraintTop_toTopOf="parent" />
        </ConstraintSet>
    
    </MotionScene>
        

    لاحظ ما يلي:

    • تتضمن السمة <Transition> التعريف الأساسي للحركة.

      • motion:constraintSetStart وmotion:constraintSetEnd هما إشارات إلى نقطتَي نهاية الحركة. يتم تحديد نقاط النهاية هذه في عناصر <ConstraintSet> لاحقًا في مشهد الحركة.

      • تحدّد السمة motion:duration عدد المللي ثانية التي يستغرقها اكتمال الحركة.

    • يتيح لك <OnSwipe> إنشاء عنصر تحكّم باللمس للحركة.

      • يشير motion:touchAnchorId إلى العرض الذي يمكن للمستخدم التمرير السريع عليه وسحبه.

      • تعني العلامة motion:touchAnchorSide أنّه يتم سحب طريقة العرض من الجانب الأيسر.

      • تشير السمة motion:dragDirection إلى اتجاه التقدّم في السحب. على سبيل المثال، تعني السمة motion:dragDirection="dragRight" زيادة مستوى التقدّم عند سحب طريقة العرض إلى اليسار.

    • تمثّل السمة <ConstraintSet> المكان الذي تحدّد فيه القيود المختلفة التي تصف حركتك. في هذا المثال، يتم تحديد <ConstraintSet> واحدة لكل نقطة نهاية في الحركة. يتم توسيط نقطتَي النهاية هاتين عموديًا باستخدام app:layout_constraintTop_toTopOf="parent" وapp:layout_constraintBottom_toBottomOf="parent". أفقيًا، تقع نقطتا النهاية في أقصى الجانبين الأيمن والأيسر من الشاشة.

    لإلقاء نظرة أكثر تفصيلاً على العناصر المتنوعة التي يتيحها مشهد الحركة، يمكنك الاطّلاع على أمثلة MotionLayout.

السمات المضاف إليها

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

  • alpha
  • visibility
  • elevation
  • rotation وrotationX وrotationY
  • translationX وtranslationY وtranslationZ
  • scaleX، scaleY

سمات مخصصة

ضمن <Constraint>، يمكنك استخدام العنصر <CustomAttribute> لتحديد انتقال للسمات التي لا ترتبط ببساطة بسمات الموضع أو View.

<Constraint
    android:id="@+id/button" ...>
    <CustomAttribute
        motion:attributeName="backgroundColor"
        motion:customColorValue="#D81B60"/>
</Constraint>

يحتوي <CustomAttribute> على سمتَين خاصتَين:

  • إنّ السمة motion:attributeName مطلوبة ويجب أن تطابق كائنًا باستخدام طريقتَي getter وsetter. يجب أن تتطابق قيم getter وsetter مع نمط معيّن. على سبيل المثال، يمكن استخدام backgroundColor لأن العرض يتضمن طريقتين getBackgroundColor() وsetBackgroundColor() أساسيتين.
  • تستند السمة الأخرى التي يجب تقديمها إلى نوع القيمة. اختَر من بين الأنواع المتوافقة التالية:
    • motion:customColorValue للألوان
    • motion:customIntegerValue للأعداد الصحيحة
    • motion:customFloatValue للأعداد العشرية
    • motion:customStringValue للسلاسل
    • motion:customDimension للسمات
    • motion:customBoolean للقيم المنطقية

عند تحديد سمة مخصّصة، عليك تحديد قيم نقطة النهاية في عنصرَي <ConstraintSet> للبداية والنهاية.

تغيير لون الخلفية

بناءً على المثال السابق، افترض أنك تريد تغيير ألوان العرض كجزء من حركته، كما هو موضح في الشكل 2.

الشكل 2. يتغير لون الخلفية أثناء تحرك العرض.

أضِف عنصر <CustomAttribute> إلى كل عنصر ConstraintSet، كما هو موضّح في مقتطف الرمز التالي:

<ConstraintSet android:id="@+id/start">
    <Constraint
        android:id="@+id/button"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_marginStart="8dp"
        motion:layout_constraintBottom_toBottomOf="parent"
        motion:layout_constraintStart_toStartOf="parent"
        motion:layout_constraintTop_toTopOf="parent">
        <CustomAttribute
            motion:attributeName="backgroundColor"
            motion:customColorValue="#D81B60" />
    </Constraint>
</ConstraintSet>

<ConstraintSet android:id="@+id/end">
    <Constraint
        android:id="@+id/button"
        android:layout_width="64dp"
        android:layout_height="64dp"
        android:layout_marginEnd="8dp"
        motion:layout_constraintBottom_toBottomOf="parent"
        motion:layout_constraintEnd_toEndOf="parent"
        motion:layout_constraintTop_toTopOf="parent">
        <CustomAttribute
            motion:attributeName="backgroundColor"
            motion:customColorValue="#9999FF" />
    </Constraint>
</ConstraintSet>

سمات MotionLayout الإضافية

بالإضافة إلى السمات في المثال السابق، تتضمن السمة MotionLayout سمات أخرى قد تحتاج إلى تحديدها:

  • تحدّد السمة app:applyMotionScene="boolean" ما إذا كان سيتم تطبيق مشهد الحركة. تكون القيمة التلقائية لهذه السمة هي true.
  • app:showPaths="boolean" تحدد ما إذا كان سيتم عرض مسارات الحركة أثناء كون الحركة قيد التشغيل. تكون القيمة التلقائية لهذه السمة هي false.
  • يتيح لك app:progress="float" تحديد مدى تقدُّم عملية النقل بوضوح. يمكنك استخدام أي قيمة نقطة عائمة من 0 (بداية الانتقال) إلى 1 (نهاية الانتقال).
  • تتيح لك السمة app:currentState="reference" تحديد سمة ConstraintSet معيّنة.
  • يتيح لك app:motionDebug عرض معلومات تصحيح أخطاء إضافية حول الحركة. والقيم المحتملة هي "SHOW_PROGRESS" أو "SHOW_PATH" أو "SHOW_ALL".

مراجع إضافية

لمزيد من المعلومات عن MotionLayout، اطّلِع على المراجع التالية: