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

تجربة طريقة Compose
‫Jetpack Compose هي مجموعة أدوات واجهة المستخدم المقترَحة لنظام Android. تعرَّف على كيفية استخدام الصور المتحركة في Compose.

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

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

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

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

MotionLayout تعريفية بالكامل، ما يعني أنّه يمكنك وصف أي عمليات نقل بتنسيق XML، بغض النظر عن مدى تعقيدها.

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

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

البدء

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

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

    Groovy

    dependencies {
        implementation "androidx.constraintlayout:constraintlayout:2.2.1"
        // To use constraintlayout in compose
        implementation "androidx.constraintlayout:constraintlayout-compose:1.1.1"
    }

    Kotlin

    dependencies {
        implementation("androidx.constraintlayout:constraintlayout:2.2.1")
        // To use constraintlayout in compose
        implementation("androidx.constraintlayout:constraintlayout-compose:1.1.1")
    }
  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 .../>
              

    في ما يلي مثال كامل لمل0/ف 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، يُرجى الاطّلاع على المراجع التالية: