چرخ فلک با MotionLayout

روش نوشتن را امتحان کنید
Jetpack Compose ابزار رابط کاربری پیشنهادی برای اندروید است. یاد بگیرید که چگونه یک چرخ فلک در Compose اضافه کنید.

Carousel یک شیء کمکی حرکت برای ساخت نماهای سفارشی carousel است که لیستی از عناصر را نشان می‌دهد که کاربر می‌تواند از آنها عبور کند. در مقایسه با سایر روش‌های پیاده‌سازی چنین نماهایی، این کمکی به شما امکان می‌دهد با بهره‌گیری از MotionLayout ، به سرعت تغییرات حرکتی و ابعادی پیچیده‌ای را برای Carousel خود ایجاد کنید.

ویجت Carousel از لیست‌هایی با شروع و پایان و همچنین لیست‌های دایره‌ای شکل پشتیبانی می‌کند.

نحوه کار Carousel با MotionLayout

فرض کنید می‌خواهید یک نمای Carousel افقی بسازید که آیتم مرکزی در آن بزرگ شده باشد:

این طرح اولیه شامل چندین نما است که نشان‌دهنده‌ی آیتم‌های Carousel هستند:

یک MotionLayout با سه وضعیت زیر ایجاد کنید و به آنها شناسه (ID) بدهید:

  • قبلی
  • شروع
  • بعدی

اگر حالت شروع با طرح پایه مطابقت داشته باشد، در حالت قبل و حالت بعد ، آیتم‌های Carousel به ترتیب یک واحد به چپ و یک واحد به راست منتقل می‌شوند.

برای مثال، پنج نما در شکل ۳ را در نظر بگیرید و فرض کنید که در حالت شروع ، نماهای B، C و D قابل مشاهده هستند و A و E خارج از صفحه نمایش هستند. حالت قبلی را طوری تنظیم کنید که موقعیت‌های A، B، C و D در جایی باشند که B، C، D و E قرار داشتند و نماها از چپ به راست حرکت کنند. در حالت بعدی ، عکس این اتفاق باید رخ دهد، یعنی B، C، D و E به جایی که A، B، C و D قرار داشتند حرکت کنند و نماها از راست به چپ حرکت کنند. این در شکل ۴ نشان داده شده است:

بسیار مهم است که نماها دقیقاً در جایی که نماهای اصلی شروع می‌شوند، قرار گیرند. Carousel با انتقال نماهای واقعی به جایی که بودند، اما با مقداردهی مجدد آنها با محتوای منطبق جدید، توهم مجموعه‌ای نامتناهی از عناصر را ایجاد می‌کند. نمودار زیر این مکانیسم را نشان می‌دهد. به مقادیر "item #" توجه کنید:

انتقال‌ها

با تعریف این سه مجموعه محدودیت در فایل صحنه حرکت خود، دو انتقال - رو به جلو و عقب - بین حالت‌های شروع و بعدی و حالت‌های شروع و قبلی ایجاد کنید. یک کنترل‌کننده OnSwipe اضافه کنید تا انتقال‌ها را در پاسخ به یک حرکت، همانطور که در مثال زیر نشان داده شده است، فعال کند:

    <Transition
        motion:constraintSetStart="@id/start"
        motion:constraintSetEnd="@+id/next"
        motion:duration="1000"
        android:id="@+id/forward">
        <OnSwipe
            motion:dragDirection="dragLeft"
            motion:touchAnchorSide="left" />
    </Transition>

    <Transition
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/previous"
        android:id="@+id/backward">
        <OnSwipe
            motion:dragDirection="dragRight"
            motion:touchAnchorSide="right" />
    </Transition>

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

ویژگی‌های زیر را برای تابع کمکی Carousel تنظیم کنید:

  • app:carousel_firstView : نمایی که اولین عنصر Carousel را نشان می‌دهد - در این مثال، C.
  • app:carousel_previousState : شناسه‌ی ConstraintSet مربوط به حالت قبلی .
  • app:carousel_nextState : شناسه ConstraintSet مربوط به حالت بعدی .
  • app:carousel_backwardTransition : شناسه‌ی Transition اعمال‌شده بین حالت‌های شروع و قبلی .
  • app:carousel_forwardTransition : شناسه‌ی Transition ID) که بین حالت‌های شروع و بعدی اعمال شده است.

برای مثال، شما چیزی شبیه به این در فایل XML طرح‌بندی خود دارید:

    <androidx.constraintlayout.motion.widget.MotionLayout ... >

        <ImageView  android:id="@+id/imageView0" .. />
        <ImageView  android:id="@+id/imageView1" .. />
        <ImageView  android:id="@+id/imageView2" .. />
        <ImageView  android:id="@+id/imageView3" .. />
        <ImageView  android:id="@+id/imageView4" .. />

        <androidx.constraintlayout.helper.widget.Carousel
            android:id="@+id/carousel"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:carousel_forwardTransition="@+id/forward"
            app:carousel_backwardTransition="@+id/backward"
            app:carousel_previousState="@+id/previous"
            app:carousel_nextState="@+id/next"
            app:carousel_infinite="true"
            app:carousel_firstView="@+id/imageView2"
            app:constraint_referenced_ids="imageView0,imageView1,imageView2,imageView3,imageView4" />

    </androidx.constraintlayout.motion.widget.MotionLayout>

یک آداپتور Carousel را در کد تنظیم کنید:

کاتلین

carousel.setAdapter(object : Carousel.Adapter {
            override fun count(): Int {
              // Return the number of items in the Carousel.
            }

            override fun populate(view: View, index: Int) {
                // Implement this to populate the view at the given index.
            }

            override fun onNewItem(index: Int) {
                // Called when an item is set.
            }
        })

جاوا

carousel.setAdapter(new Carousel.Adapter() {
            @Override
            public int count() {
                // Return the number of items in the Carousel.
            }

            @Override
            public void populate(View view, int index) {
                // Populate the view at the given index.
            }

            @Override
            public void onNewItem(int index) {
                 // Called when an item is set.
            }
        });

یادداشت‌های تکمیلی

بسته به آیتم فعلی "انتخاب شده" در Carousel ، ممکن است لازم باشد نماهایی که نشان‌دهنده‌ی آیتم‌های قبل یا بعد هستند، پنهان شوند تا شروع و پایان Carousel به درستی در نظر گرفته شود. کمک‌کننده‌ی Carousel این کار را به طور خودکار انجام می‌دهد. به طور پیش‌فرض، در این شرایط، آن نماها را به عنوان View.INVISIBLE علامت‌گذاری می‌کند، بنابراین طرح کلی تغییر نمی‌کند.

یک حالت جایگزین نیز وجود دارد که در آن تابع کمکی Carousel ، آن نماها را به عنوان View.GONE علامت‌گذاری می‌کند. می‌توانید این حالت را با استفاده از ویژگی زیر تنظیم کنید:

app:carousel_emptyViewsBehavior="gone"

مثال‌ها

برای مثال‌های بیشتر با استفاده از کمک‌کننده‌ی Carousel، به پروژه‌های نمونه در GitHub مراجعه کنید.