جشنواره نوروزی سون لرن

آموزش Motion Layout در برنامه نویسی اندروید - قسمت دوم

دسته بندی: اندروید
زمان مطالعه: 13 دقیقه
۰۲ فروردین ۱۳۹۹

در قسمت اول مقاله در مورد کلیات چگونگی استفاده از موشن‌ لایوت صحبت کردیم. در مورد کاربردها و چگونگی ایجاد MotionScene  و اجزای آن صحبت کردیم. همچنین یک نمونه بسیار ساده استفاده از آن را انجام دادیم.

در این مقاله به ویژگی‌های دیگری از موشن‌ لایوت خواهیم پرداخت. و به مثال قسمت اول انیمیشن‌های بیشتر و جذاب‌تری اضافه خواهیم کرد و با استفاده ترکیبی انیمیشن‌ها با استفاده از موشن‌ لایوت آشنا خواهیم شد.

فهرست محتوای این مقاله

نقاط کلیدی (Keyframes):

در قسمت اول دیدیم که برای داشتن یک انیمیشن با موش لایوت باید صفات هر المان را در نقطه‌ی شروع و نقطه‌ی پایان انیمیشن مشخص کنیم. المان در طول اجرای انیمیشن، از نقطه‌ی شروع در یک مسیر خطی حرکت می‌کند و به نقطه‌ی پایان می‌رسد. حال اگر بخواهیم حرکت المان را از حالت خطی خارج کنیم و مسیری سفارشی به آن بدهیم یا در میانه‌ی راه ویژگی خاصی از المان( مثل رنگ و اندازه و...) را تغییر بدهیم، باید از Keyframeها استفاده کنیم.

شکل 1

کی فریم‌ها انواع مختلفی دارند که در بعضی ویژگی‌ها با هم مشترک هستند. با وجود این اشتراکات هر کدام ویژگی‌ها و رفتارهای خاص خود را هم دارند. در ادامه‌ی مقاله به معرفی و بررسی هر یک از آنها خواهیم پرداخت. انواع کی فریم (keyframe) عبارت‌اند از:

  • KeyPosition: کی‌ فریم موقعیت (Position keyframe)
  • KeyAttribute: کی فریم صفات (Attribute keyframe)
  • KeyCycle: کی‌ فریم چرخه (Cycle keyframe)
  • KeyTimeCycle: کی‌ فریم چرخه‌ی زمان (TimeCycle keyframe)

توجه داشته باشید که هر کدام از کی فریم‌ها از سایرین مستقل است. یعنی اگر می‌خواهید در یک نقطه خاص کی فریمی تعریف کنید، لازم نیست همه‌ی آنها را تعریف کنید.

ویژگی‌های مشترک کی‌ فریم‌ها:

ابتدا قبل از بررسی انواع کی فریم‌ها (موقعیت ، ویژگی ، چرخه ، چرخه زمان) به بررسی ویژگی‌های مشترک آنها می‌پردازیم : framePosition: زمانی که این ویژگی را برای کی فریم مشخص می‌کنیم باید عددی بین 0 تا 100 را برای آن تعیین کنیم. و در واقع تعیین می‌کنیم کی فریم ما، در چه زمانی از اجرای انیمیشن (بر حسب درصد) باید اعمال شود. target: با تعریف هدف (target) مشخص می‌کنیم که این کی فریم روی کدام المان در طرح‌مان باید اعمال شود. transitionEasing: در حالت پیش‌فرض حرکت بین نقاط به‌صورت خطی است. حال اگر بخواهیم این جابجایی به صورت منحنی باشد از transitionEasing استفاده می‌کنیم.

کی‌ فریم موقعیت (Position keyframe):

در بین انواع کی فریم‌ها، رایج‌ترین نوع کی فریم موقعیت است که به شما امکان می‌دهد مسیری را که المان در طول انتقال روی صفحه نمایش طی می‌کند را تغییر دهید.

به عنوان مثال، در قسمت اول طرحی را پیاده کردیم که در آن یک المان از سمت چپ به سمت راست حرکت می‌کرد. حال می‌خواهیم مطابق ویدیو بالا، حرکت این جابجایی را از حالت خطی خارج کنیم و المان به صورت منحنی حرکت کند و زمانی که به وسط جابجایی (50درصد) رسید ارتفاع آن به میزان یک چهارم ارتفاع طرح (25 درصد) بالاتر بیاید. برای پیاده سازی این انیمیشن باید کد زیر را به مثال قبل اضافه کنیم :

<Transition ...>
    <KeyFrameSet>
        <KeyPosition
            motion:keyPositionType="parentRelative"
            motion:percentY="0.25"
            motion:framePosition="50"
            motion:target="@+id/button"/>
    </KeyFrameSet>
</Transition>

 

مطابق توضیحاتی که دادیم کد "motion:target="@+id/button مشخص می‌کند که ما قصد داریم این کی فریم را روی المان button اعمال کنیم. "motion:framePosition="50 نیز مشخص می‌کند که ما قصد داریم این کی فریم در وسط جابجایی اعمال شود. "motion:percentY="0.25 مشخص کننده‌ی این موضوع است که در زمان اعمال کی فریم button باید به اندازه یک چهارم والدش (25 درصد طرح اصلی ) قرار بگیرد. "motion:keyPositionType="parentRelative نیز مشخص می‌کند کی فریم تعریف شده باید از نوع parentRelative باشد. (در ادامه مقاله به معرفی انواع آن خواهیم پرداخت.)

با اعمال این بخش به کدهای قسمت اول، در نهایت کدها به شکل زیر تغییر می‌کند.

لایوت activity_main.xml: کدهای لایوت activity_main.xml بدون تغییر باقی می‌ماند.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.MotionLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/motionLayout"
    app:layoutDescription="@xml/scene_06"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View
        android:id="@+id/button"
        android:background="@color/colorAccent"
        android:layout_width="64dp"
        android:layout_height="64dp" />

</android.support.constraint.motion.MotionLayout>

 

کدهای scene_01 :

<?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"
        motion:interpolator="linear">
        <OnSwipe
            motion:touchAnchorId="@+id/button"
            motion:touchAnchorSide="right"
            motion:dragDirection="dragRight" />

        <KeyFrameSet>
            <KeyPosition
                motion:keyPositionType="parentRelative"
                motion:percentY="0.25"
                motion:framePosition="50"
                motion:target="@+id/button"/>
        </KeyFrameSet>
    </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">
            <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>

</MotionScene>

 

انواع کی فریم موقعیت:

در مثال قبل دیدم که هنگام استفاده از کی فریم موقعیت می‌توانیم مختصات المان را با استفاده از percentY و percentX تعریف کنیم و در حقیقت با تعریف همین percentY و percentX است که حرکت المان به صورت منحنی در می‌آید. یکی از صفاتی که در کی فریم موقعیت باید مشخص شود keyPositionType است که مشخص می‌کند مرجع درصدهایی که برای x وy مشخص می‌کنیم بر اساس چه مختصاتی باشد. در ادامه به بررسی انواع این مراجع مختصات می‌پردازیم.

parentRelative:

زمانی که مقدار parentRelative را برای keyPositionType مشخص کنید مختصات لایوت والد به عنوان مختصات مرجع تعریف می‌شود. همان‌طور که شکل 2 مشاهده می‌کنید. نسبت مختصات بر اساس اندازه و مختصات طرح کلی (parent) تعریف می‌شود.

این نوع مختصات دهی رایج‌ترین نوع از بین سایرین هست و روشی بسیار ساده و شهودی برای بیان جایگاه کی فریم است. معمولاً از این روش برای جابجایی‌های بزرگی که در کل طرح حرکت می‌کنند، استفاده می‌شود.

deltaRelative:

دومین نوع سیستم مختصات دهی به کی فریم deltaRelative است، که مختصات دهی بر اساس نقاط شروع و پایان انجام می‌شود. در واقع مختصاتی که تعریف می‌کنید، درصدی از فاصله‌ی بین موقعیت‌های شروع و پایان است. در این حالت نقطه‌ی شروع مبدا مختصات و نقطه‌ی پایان حد نهایی محورهای x وy  هستند.

از این نوع مختصات زمانی استفاده می‌شود که شما قصد دارید نسبت به فاصله بین دو نقطه شروع و پایان تغییری را تعریف کنید. نکته‌ی مهمی در استفاده از این نوع مختصات دهی وجود دارد، همان‌طور که گفتیم دیگر مختصات تعریف شده به مختصات طرح والد وابستگی ندارد و درصدها بر اساس دو نقطه‌ی شروع و پایان محاسبه می‌شوند، اگر در یکی از محورها تفاوت بین این دو نقطه بسیار کم (یا صفر) باشد، موقعیت کلید فریم در محور تغییر نمی‌کند. به عنوان مثال، در مثالی که قبلا بررسی کردیم چون المان از سمت چپ به راست بر روی صفحه نمایش حرکت می‌کند و ارتفاع بین دو نقطه یکسان هست، اگر از deltaRelative استفاده کنیم و position=0.25 را تعریف کنیم، ارتفاع المان هیچ تغییری نخواهد داشت.

pathRelative:

pathRelative هم مانند deltaRelative بر اساس نقاط شروع و پایان مختصات را مشخص می‌کند. در حالت قبل نقطه‌ی شروع مبدا مختصات و نقطه‌ی پایان حد نهایی محورهای x وy  بودند ولی در  pathRelative مطابق با شکل پایین، مسیر مستقیمی بین دو نقطه‌ی شروع و پایان محور افقی مختصات را تشکیل می‌دهد. در نوع مختصات دهی از اعداد منفی نیز پشتیبانی می‌کند و می‌توانید از اعداد منفی نیز استفاده کنید.

کی فریم صفات (Attribute keyframe):

کی فریم صفات شبیه به کی فریم‌های موقعیت هستند، اما به جای موقعیت المان روی صفات المان کار می‌کنند. کی فریم صفات این امکان را به شما می‌دهد که در طول جابجایی از نقطه‌ی شروع به نقطه‌ی پایان انیمیشن ، در یک نقطه‌ی معین . ویژگی‌های خاصی از یک المان را مانند رنگ،اندازه،مقیاس و... تغییر بدهید.

در مثال قبل المان تعریف شده، زمانی که به وسط جابجایی می‌رسید ارتفاع آن به میزان یک چهارم ارتفاع والدش بالاتر می‌رفت، حال می‌خواهیم در همان نقطه علاوه بر تغییر ارتفاع، مقیاس المان بزرگ‌تر شود و به اندازه‌ی 45 درجه نیز بچرخد.برای انجام این کار علاوه بر کی فریم موقعیت، از Attribute keyframe نیز استفاده می‌کنیم و KeyFrameSet را به صورت زیر تغییر می‌دهیم:

<KeyFrameSet>
    <KeyAttribute
        android:rotation="-45"
        android:scaleX="2"
        android:scaleY="2"
        motion:framePosition="50"
        motion:target="@id/button" />
    <KeyPosition
        motion:framePosition="50"
        motion:keyPositionType="screenRelative"
        motion:percentY="0.2"
        motion:target="@id/button" />
</KeyFrameSet>

 

در نهایت فایل MotionScene به صورت زیر تغییر خواهد کرد و خروجی کار مشابه با ویدیو شماره 2 خواهد شد.

<?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"
        motion:interpolator="linear">
        <OnSwipe
            motion:touchAnchorId="@+id/button"
            motion:touchAnchorSide="right"
            motion:dragDirection="dragRight" />

        <KeyFrameSet>
            <KeyAttribute
                android:scaleX="2"
                android:scaleY="2"
                android:rotation="-45"
                motion:framePosition="50"
                motion:target="@id/button" />
            <KeyPosition
                motion:keyPositionType="screenRelative"
                motion:percentY="0.2"
                motion:framePosition="50"
                motion:target="@id/button"/>
        </KeyFrameSet>
    </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">
            <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>

</MotionScene>

 

صفات قابل تغییر:

در هنگام استفاده از کی فریم صفات شما مجازید هر یک از صفات زیر را به صورت دلخواه تغییر بدهید:

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

نکته: مشابه آنچه در ConstraintSet داشتیم ، در کی فریم‌ها نیز شما می‌توانید با افزودن <CustomAttribute> ویژگی‌های سفارشی را برای کی فریم‌ خود تعریف کنید و صفاتی را علاوه بر موارد بالا در المان مورد نظرتان تغییر بدهید.

جمع بندی

در این مقاله سعی کردیم به مهم‌ترین موضوعات و نکات هنگام استفاده از موشن لایوت بپردازیم. شما می‌توانید با ترکیب موضوعات بیان شده و استفاده ترکیبی موشن لایوت و viewPager ,CoordinatorLayout , DrawerLayout طرح‌های بسیار جذابی را پیاده سازی کنید.

نمونه طرح‌های پیاده شده زیادی با عنوان MotionLayout / Constraint Layout Samples در سایت Github وجود دارد که می‌توانید  به‌عنوان مرجع از آنها استفاده کنید.

 

 

چه امتیازی به این مقاله می دید؟
نویسنده علیرضا اسلمی

نظرات کاربران

اولین دیدگاه این پست رو تو بنویس !

ارسال دیدگاه
خوشحال میشیم دیدگاه و یا تجربیات خودتون رو با ما در میون بذارید :