بااستفاده از ViewPager بین تکه‌برنامه‌ها بلغزانید

امتحان کردن روش «نوشتن»
Jetpack Compose جعبه‌ابزار واسط کاربر توصیه‌شده برای Android است. با نحوه استفاده از Pager در «نوشتن» آشنا شوید.

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

پویانمایی لغزنده صفحه
 

ViewPager بخشی از AndroidX است. برای اطلاعات بیشتر، به استفاده از 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() ساخته‌اید برمی‌گرداند. سپس می‌توانید هرگاه به صفحه جدیدی برای نمایش به کاربر نیاز داشتید، نمونه‌هایی از این قطعه را در فعالیت والد ایجاد کنید:

کاتلین

import android.support.v4.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 android.support.v4.app.Fragment;
...
public class ScreenSlidePageFragment extends Fragment {

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

        return rootView;
    }
}

افزودن ViewPager

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

برای شروع، طرح‌بندی‌ای ایجاد کنید که حاوی ViewPager باشد:

<!-- activity_screen_slide.xml -->
<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

فعالیتی ایجاد کنید که کارهای زیر را انجام دهد:

  • نمای محتوا را روی چیدمان با ViewPager تنظیم می‌کند.
  • کلاسی ایجاد می‌کند که کلاس انتزاعی FragmentStatePagerAdapter را گسترش می‌دهد و روش getItem() را برای ارائه نمونه‌های ScreenSlidePageFragment به‌عنوان صفحه‌های جدید پیاده‌سازی می‌کند. آداپتور صفحه‌بندی همچنین نیاز دارد که روش getCount() را پیاده‌سازی کنید که تعداد صفحاتی را که آداپتور ایجاد می‌کند برمی‌گرداند (پنج صفحه در مثال).
  • ‫PagerAdapter را به ViewPager متصل می‌کند.

کاتلین

import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager
...
/**
 * 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 mPager: ViewPager

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

        // Instantiate a ViewPager and a PagerAdapter.
        mPager = findViewById(R.id.pager)

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

    override fun onBackPressed() {
        if (mPager.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.
            mPager.currentItem = mPager.currentItem - 1
        }
    }

    /**
     * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in
     * sequence.
     */
    private inner class ScreenSlidePagerAdapter(fm: FragmentManager) : FragmentStatePagerAdapter(fm) {
        override fun getCount(): Int = NUM_PAGES

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

جاوا

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
...
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 ViewPager mPager;

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

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

        // Instantiate a ViewPager and a PagerAdapter.
        mPager = (ViewPager) findViewById(R.id.pager);
        pagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager());
        mPager.setAdapter(pagerAdapter);
    }

    @Override
    public void onBackPressed() {
        if (mPager.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.
            mPager.setCurrentItem(mPager.getCurrentItem() - 1);
        }
    }

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

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

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

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

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

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

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

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

کاتلین

val mPager: ViewPager = findViewById(R.id.pager)
...
mPager.setPageTransformer(true, ZoomOutPageTransformer())

جاوا

ViewPager mPager = (ViewPager) findViewById(R.id.pager);
...
mPager.setPageTransformer(true, new ZoomOutPageTransformer());

برای مشاهده نمونه‌ها و ویدیوهای PageTransformer، به بخش‌های تبدیل‌کننده صفحه کوچک‌نمایی و تبدیل‌کننده صفحه عمق مراجعه کنید.

تبدیل‌کننده صفحه زوم‌پس

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

‫ZoomOutPageTransformer مثال
 

کاتلین

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

class ZoomOutPageTransformer : ViewPager.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 ViewPager.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

class DepthPageTransformer : ViewPager.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
                    scaleX = 1f
                    scaleY = 1f
                }
                position <= 1 -> { // (0,1]
                    // Fade the page out.
                    alpha = 1 - position

                    // Counteract the default slide transition
                    translationX = pageWidth * -position

                    // 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
                }
            }
        }
    }
}

جاوا

public class DepthPageTransformer implements ViewPager.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.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);

            // 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);
        }
    }
}