با استفاده از ViewPager2 بین قطعات اسلاید کنید

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

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

شکل ۱. انیمیشن اسلاید صفحه نمایش.

اگر می‌خواهید جلوتر بروید و یک مثال کامل ببینید، این برنامه نمونه را در GitHub مشاهده کنید .

برای استفاده از ViewPager2 ، باید برخی از وابستگی‌های AndroidX را به پروژه خود اضافه کنید. سپس مراحل ذکر شده در بخش‌های بعدی را دنبال کنید.

نماها را ایجاد کنید

یک فایل طرح‌بندی ایجاد کنید تا بعداً برای محتوای یک قطعه کد از آن استفاده کنید. همچنین باید یک رشته برای محتوای قطعه کد تعریف کنید. مثال زیر شامل یک نمای متن است که مقداری متن را نمایش می‌دهد:

<!-- fragment_screen_slide_page.xml -->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView style="?android:textAppearanceMedium"
        android:padding="16dp"
        android:lineSpacingMultiplier="1.2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/lorem_ipsum" />
</ScrollView>

قطعه را ایجاد کنید

یک کلاس Fragment ایجاد کنید که طرح‌بندی ایجاد شده در متد onCreateView() را برگرداند. سپس می‌توانید هر زمان که به صفحه جدیدی برای نمایش به کاربر نیاز دارید، نمونه‌هایی از این fragment را در activity والد ایجاد کنید:

کاتلین

import androidx.fragment.app.Fragment

class ScreenSlidePageFragment : Fragment() {

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View = inflater.inflate(R.layout.fragment_screen_slide_page, container, false)
}

جاوا

import androidx.fragment.app.Fragment;
...
public class ScreenSlidePageFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        return (ViewGroup) inflater.inflate(
                R.layout.fragment_screen_slide_page, container, false);
    }
}

افزودن ViewPager2

اشیاء ViewPager2 دارای حرکات کشیدن انگشت (swipe) داخلی برای جابجایی بین صفحات هستند و به طور پیش‌فرض انیمیشن‌های اسلاید صفحه را نمایش می‌دهند، بنابراین نیازی نیست انیمیشن خودتان را بسازید. ViewPager2 از اشیاء FragmentStateAdapter به عنوان منبعی برای نمایش صفحات جدید استفاده می‌کند، بنابراین FragmentStateAdapter از کلاس fragment که شما ایجاد کرده‌اید استفاده می‌کند.

برای شروع، یک طرح‌بندی ایجاد کنید که شامل یک شیء ViewPager2 باشد:

<!-- activity_screen_slide.xml -->
<androidx.viewpager2.widget.ViewPager2
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

یک فعالیت (activity) ایجاد کنید که موارد زیر را انجام دهد:

  • نمای محتوا را به عنوان طرح‌بندی با ViewPager2 تنظیم می‌کند.
  • کلاسی ایجاد می‌کند که کلاس انتزاعی FragmentStateAdapter ارث‌بری می‌کند و متد createFragment() را برای ارائه نمونه‌هایی از ScreenSlidePageFragment به عنوان صفحات جدید پیاده‌سازی می‌کند. شما باید متد getItemCount() را برای آداپتور صفحه‌بند پیاده‌سازی کنید، که تعداد صفحاتی را که آداپتور ایجاد می‌کند، برمی‌گرداند. در این مثال پنج عدد وجود دارد.
  • FragmentStateAdapter را به اشیاء ViewPager2 متصل می‌کند.

کاتلین

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
...
/**
 * The number of pages (wizard steps) to show in this demo.
 */
private const val NUM_PAGES = 5

class ScreenSlidePagerActivity : FragmentActivity() {

    /**
     * The pager widget, which handles animation and allows swiping horizontally
     * to access previous and next wizard steps.
     */
    private lateinit var viewPager: ViewPager2

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_screen_slide)

        // Instantiate a ViewPager2 and a PagerAdapter.
        viewPager = findViewById(R.id.pager)

        // The pager adapter, which provides the pages to the view pager widget.
        val pagerAdapter = ScreenSlidePagerAdapter(this)
        viewPager.adapter = pagerAdapter
    }

    override fun onBackPressed() {
        if (viewPager.currentItem == 0) {
            // If the user is currently looking at the first step, allow the system to handle
            // the Back button. This calls finish() on this activity and pops the back stack.
            super.onBackPressed()
        } else {
            // Otherwise, select the previous step.
            viewPager.currentItem = viewPager.currentItem - 1
        }
    }

    /**
     * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
     * sequence.
     */
    private inner class ScreenSlidePagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
        override fun getItemCount(): Int = NUM_PAGES

        override fun createFragment(position: Int): Fragment = ScreenSlidePageFragment()
    }
}

جاوا

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
...
public class ScreenSlidePagerActivity extends FragmentActivity {
    /**
     * The number of pages (wizard steps) to show in this demo.
     */
    private static final int NUM_PAGES = 5;

    /**
     * The pager widget, which handles animation and allows swiping horizontally to access previous
     * and next wizard steps.
     */
    private ViewPager2 viewPager;

    /**
     * The pager adapter, which provides the pages to the view pager widget.
     */
    private FragmentStateAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_screen_slide);

        // Instantiate a ViewPager2 and a PagerAdapter.
        viewPager = findViewById(R.id.pager);
        pagerAdapter = new ScreenSlidePagerAdapter(this);
        viewPager.setAdapter(pagerAdapter);
    }

    @Override
    public void onBackPressed() {
        if (viewPager.getCurrentItem() == 0) {
            // If the user is currently looking at the first step, allow the system to handle the
            // Back button. This calls finish() on this activity and pops the back stack.
            super.onBackPressed();
        } else {
            // Otherwise, select the previous step.
            viewPager.setCurrentItem(viewPager.getCurrentItem() - 1);
        }
    }

    /**
     * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
     * sequence.
     */
    private class ScreenSlidePagerAdapter extends FragmentStateAdapter {
        public ScreenSlidePagerAdapter(FragmentActivity fa) {
            super(fa);
        }

        @Override
        public Fragment createFragment(int position) {
            return new ScreenSlidePageFragment();
        }

        @Override
        public int getItemCount() {
            return NUM_PAGES;
        }
    }
}

سفارشی‌سازی انیمیشن با استفاده از PageTransformer

برای نمایش یک انیمیشن متفاوت از انیمیشن اسلاید پیش‌فرض صفحه، رابط ViewPager2.PageTransformer را پیاده‌سازی کرده و آن را به شیء ViewPager2 ارائه دهید. این رابط یک متد واحد به transformPage() را در معرض نمایش قرار می‌دهد. در هر نقطه از انتقال صفحه، این متد برای هر صفحه قابل مشاهده - معمولاً فقط یک صفحه قابل مشاهده وجود دارد - و برای صفحات مجاور خارج از صفحه، یک بار فراخوانی می‌شود. به عنوان مثال، اگر صفحه سه قابل مشاهده باشد و کاربر به سمت صفحه چهار بکشد، transformPage() برای صفحات دو، سه و چهار در هر مرحله از حرکت فراخوانی می‌شود.

در پیاده‌سازی تابع transformPage() ، می‌توانید با تعیین صفحاتی که باید تغییر شکل داده شوند، بر اساس موقعیت صفحه روی صفحه، انیمیشن‌های اسلاید سفارشی ایجاد کنید. موقعیت صفحه را از پارامتر position متد transformPage() به دست آورید.

پارامتر position نشان می‌دهد که یک صفحه مشخص نسبت به مرکز صفحه نمایش در کجا قرار دارد. این پارامتر یک ویژگی پویا است که با اسکرول کردن کاربر در مجموعه‌ای از صفحات تغییر می‌کند. وقتی یک صفحه تمام صفحه را پر می‌کند، مقدار موقعیت آن 0 است. وقتی صفحه‌ای از سمت راست صفحه نمایش کشیده می‌شود، مقدار موقعیت آن 1 است. اگر کاربر بین صفحات یک و دو در نیمه راه اسکرول کند، صفحه اول موقعیت -0.5 و صفحه دوم موقعیت 0.5 را دارد. بر اساس موقعیت صفحات روی صفحه، می‌توانید با تنظیم ویژگی‌های صفحه با روش‌هایی مانند setAlpha() ، setTranslationX() یا setScaleY() انیمیشن‌های اسلاید سفارشی ایجاد کنید.

وقتی پیاده‌سازی‌ای از PageTransformer دارید، برای اعمال انیمیشن‌های سفارشی خود، تابع setPageTransformer() را همراه با پیاده‌سازی خود فراخوانی کنید. برای مثال، اگر یک PageTransformer با نام ZoomOutPageTransformer دارید، می‌توانید انیمیشن‌های سفارشی خود را به این صورت تنظیم کنید:

کاتلین

val viewPager: ViewPager2 = findViewById(R.id.pager)
...
viewPager.setPageTransformer(ZoomOutPageTransformer())

جاوا

ViewPager2 viewPager = findViewById(R.id.pager);
...
viewPager.setPageTransformer(new ZoomOutPageTransformer());

برای مثال‌هایی از PageTransformer به بخش‌های Zoom-out page transformer و Depth page transformer مراجعه کنید.

ترانسفورماتور صفحه کوچک‌نمایی

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

شکل ۲. مثال ZoomOutPageTransformer .

کاتلین

private const val MIN_SCALE = 0.85f
private const val MIN_ALPHA = 0.5f

class ZoomOutPageTransformer : ViewPager2.PageTransformer {

    override fun transformPage(view: View, position: Float) {
        view.apply {
            val pageWidth = width
            val pageHeight = height
            when {
                position < -1 -> { // [-Infinity,-1)
                    // This page is way off-screen to the left.
                    alpha = 0f
                }
                position <= 1 -> { // [-1,1]
                    // Modify the default slide transition to shrink the page as well.
                    val scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position))
                    val vertMargin = pageHeight * (1 - scaleFactor) / 2
                    val horzMargin = pageWidth * (1 - scaleFactor) / 2
                    translationX = if (position < 0) {
                        horzMargin - vertMargin / 2
                    } else {
                        horzMargin + vertMargin / 2
                    }

                    // Scale the page down (between MIN_SCALE and 1).
                    scaleX = scaleFactor
                    scaleY = scaleFactor

                    // Fade the page relative to its size.
                    alpha = (MIN_ALPHA +
                            (((scaleFactor - MIN_SCALE) / (1 - MIN_SCALE)) * (1 - MIN_ALPHA)))
                }
                else -> { // (1,+Infinity]
                    // This page is way off-screen to the right.
                    alpha = 0f
                }
            }
        }
    }
}

جاوا

public class ZoomOutPageTransformer implements ViewPager2.PageTransformer {
    private static final float MIN_SCALE = 0.85f;
    private static final float MIN_ALPHA = 0.5f;

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        int pageHeight = view.getHeight();

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0f);

        } else if (position <= 1) { // [-1,1]
            // Modify the default slide transition to shrink the page as well.
            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
            if (position < 0) {
                view.setTranslationX(horzMargin - vertMargin / 2);
            } else {
                view.setTranslationX(-horzMargin + vertMargin / 2);
            }

            // Scale the page down (between MIN_SCALE and 1).
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

            // Fade the page relative to its size.
            view.setAlpha(MIN_ALPHA +
                    (scaleFactor - MIN_SCALE) /
                    (1 - MIN_SCALE) * (1 - MIN_ALPHA));

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0f);
        }
    }
}

ترانسفورماتور صفحه عمق

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

شکل ۳. مثال DepthPageTransformer .

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

کاتلین

view.translationX = -1 * view.width * position

جاوا

view.setTranslationX(-1 * view.getWidth() * position);

مثال زیر نحوه خنثی کردن انیمیشن اسلاید صفحه پیش‌فرض در یک مبدل صفحه کاری را نشان می‌دهد:

کاتلین

private const val MIN_SCALE = 0.75f

@RequiresApi(21)
class DepthPageTransformer : ViewPager2.PageTransformer {

    override fun transformPage(view: View, position: Float) {
        view.apply {
            val pageWidth = width
            when {
                position < -1 -> { // [-Infinity,-1)
                    // This page is way off-screen to the left.
                    alpha = 0f
                }
                position <= 0 -> { // [-1,0]
                    // Use the default slide transition when moving to the left page.
                    alpha = 1f
                    translationX = 0f
                    translationZ = 0f
                    scaleX = 1f
                    scaleY = 1f
                }
                position <= 1 -> { // (0,1]
                    // Fade the page out.
                    alpha = 1 - position

                    // Counteract the default slide transition.
                    translationX = pageWidth * -position
                    // Move it behind the left page.
                    translationZ = -1f

                    // Scale the page down (between MIN_SCALE and 1).
                    val scaleFactor = (MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)))
                    scaleX = scaleFactor
                    scaleY = scaleFactor
                }
                else -> { // (1,+Infinity]
                    // This page is way off-screen to the right.
                    alpha = 0f
                }
            }
        }
    }
}

جاوا

@RequiresApi(21)
public class DepthPageTransformer implements ViewPager2.PageTransformer {
    private static final float MIN_SCALE = 0.75f;

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();

        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0f);

        } else if (position <= 0) { // [-1,0]
            // Use the default slide transition when moving to the left page.
            view.setAlpha(1f);
            view.setTranslationX(0f);
            view.setTranslationZ(0f);
            view.setScaleX(1f);
            view.setScaleY(1f);

        } else if (position <= 1) { // (0,1]
            // Fade the page out.
            view.setAlpha(1 - position);

            // Counteract the default slide transition.
            view.setTranslationX(pageWidth * -position);
            // Move it behind the left page
            view.setTranslationZ(-1f);

            // Scale the page down (between MIN_SCALE and 1).
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0f);
        }
    }
}

منابع اضافی

برای کسب اطلاعات بیشتر در مورد ViewPager2 ، به منابع اضافی زیر مراجعه کنید.

نمونه‌ها

ویدیوها