اسلایدهای صفحه نمایش، انتقال بین یک صفحه کامل به صفحه دیگر هستند و در رابطهای کاربری مانند ویزاردهای راهاندازی یا اسلایدشوها رایج هستند. این درس به شما نشان میدهد که چگونه اسلایدهای صفحه نمایش را با 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() ایجاد کردهاید، برمیگرداند. سپس میتوانید هر زمان که به صفحه جدیدی برای نمایش به کاربر نیاز دارید، نمونههایی از این fragment را در activity والد ایجاد کنید:
کاتلین
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 دارای حرکات کشیدن انگشت (swipe) داخلی برای جابجایی بین صفحات هستند و به طور پیشفرض انیمیشنهای اسلاید صفحه را نمایش میدهند، بنابراین نیازی نیست انیمیشن خودتان را بسازید. ViewPager از اشیاء PagerAdapter به عنوان منبعی برای نمایش صفحات جدید استفاده میکند، بنابراین PagerAdapter از کلاس fragment که قبلاً ایجاد کردهاید استفاده خواهد کرد.
برای شروع، یک طرحبندی ایجاد کنید که شامل یک 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" />
یک فعالیت (activity) ایجاد کنید که موارد زیر را انجام دهد:
- نمای محتوا را به عنوان طرحبندی با
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 را پیادهسازی کرده و آن را به صفحهبند view ارائه دهید. این رابط یک متد واحد به transformPage() را در معرض نمایش قرار میدهد. در هر نقطه از انتقال صفحه، این متد برای هر صفحه قابل مشاهده (معمولاً فقط یک صفحه قابل مشاهده وجود دارد) و برای صفحات مجاور که کمی خارج از صفحه هستند، یک بار فراخوانی میشود. به عنوان مثال، اگر صفحه سه قابل مشاهده باشد و کاربر به سمت صفحه چهار بکشد، transformPage() برای صفحات دو، سه و چهار در هر مرحله از حرکت فراخوانی میشود.
در پیادهسازی تابع transformPage() ، میتوانید با تعیین اینکه کدام صفحات باید بر اساس موقعیت صفحه روی صفحه نمایش تبدیل شوند، انیمیشنهای اسلاید سفارشی ایجاد کنید. این موقعیت از پارامتر position متد transformPage() به دست میآید.
پارامتر position (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 به بخشهای Zoom-out page transformer و Depth page transformer مراجعه کنید.
ترانسفورماتور صفحه کوچکنمایی
این مبدل صفحه، هنگام پیمایش بین صفحات مجاور، صفحات را کوچک و محو میکند. با نزدیک شدن یک صفحه به مرکز، به اندازه طبیعی خود برمیگردد و محو میشود.
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); } } }
