معرفی اولیه ViewPager 2

نمیدونم اطلاع دارید یا نه اما گوگل 7 فوریه (18 بهمن) نسخه جدید ViewPager رو با نام ViewPager 2 معرفی کرد و خب خالی از لطف نیست اگر بعضی از تغییرات این نسخه با نسخه قبلی رو با هم بررسی کنیم

معرفی اولیه ViewPager 2
معرفی اولیه ViewPager 2

ویژگی های جدید
- قابلیت راست به چپ کردن لایه ها
- ساپورت کردن از Orientation عمودی
- PageChangeListener بهتر

چه چیزایی تغییر کرده؟
- PagerAdapter جایگزین شده با RecyclerView.Adapter (فوق العاده نیست؟!!!)
- FragmentStatePagerAdapter هم جایگزین شده با FragmentStateAdapter

نکته مهم
ViewPager 2 در واقع برای Android X معرفی شده و برای استفاده از اون باید پروژه تون رو با کامپونتت های Android X سازگار کنید؛ حالا چجوری باید به Android X مهاجرت کرد؟(کلیک کنید)

نصب
برای استفاده از ViewPager 2 باید ابتدا کتابخونه اون رو به فایل Build.gradle ماژول اپ وارد

dependencies {
 implementation "androidx.viewpager2:viewpager2:1.0.0-alpha01"
}

پروژه رو Sync کنید تا کتابخونه دانلود بشه(نیاز به VPN)

پیاده سازی
- ViewPager 2 رو به لایه xml صفحه ای که میخواید داخلش از اون استفاده کنید، اضافه کنید

<androidx.viewpager2.widget.ViewPager2
 android:id="@+id/viewPager2"
 android:layout_width="match_parent"
 android:layout_height="match_parent"/>

- همونطوری که در بالا گفتم حالا میتونید برای اداپتر ViewPager 2 از RecyclerView استفاده کنید که یه چیز فوق العاده لذت بخشه! برای این کار باید اول لایوت هر آیتم ViewPager 2 رو بسازیم(مثلا نام لایه ما item_page.xml هستش) :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/container"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <androidx.appcompat.widget.AppCompatTextView
 android:id="@+id/tvTitle"
 android:textColor="@android:color/white"
 android:layout_width="wrap_content"
 android:layout_centerInParent="true"
 tools:text= "item"
 android:textSize="32sp"
 android:layout_height="wrap_content" />

</RelativeLayout>

- حالا ما نیاز داریم یک آداپتر برای ویو پیجرمون بسازیم (دقیقا مثل RecyclerView)؛ کلاس آداپترمون ViewPagerAdapter.kt:

class ViewPagerAdapter : RecyclerView.Adapter<PagerVH>() {

 privateval colors = intArrayOf(
 android.R.color.black,
 android.R.color.holo_red_light,
 android.R.color.holo_blue_dark,
 android.R.color.holo_purple
 )

 override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerVH =
 PagerVH(LayoutInflater.from(parent.context).inflate(R.layout.item_page, parent, false))

 override fun getItemCount(): Int = colors.size

 override fun onBindViewHolder(holder: PagerVH, position: Int) = holder.itemView.run {
 tvTitle.text = "item $position"
 container.setBackgroundResource(colors[position])
 }
}

class PagerVH(itemView: View) : RecyclerView.ViewHolder(itemView)

- حالا در مرحله آخر کافیه آداپترمون رو روی ViewPager ــی که در لایوت صفحه اصلیمون اضافه کردیم ست بکنیم.

class MainActivity : AppCompatActivity() {

 override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 setContentView(R.layout.activity_main)
 viewPager2.adapter = ViewPagerAdapter()
 }
}

و در نهایت خروجی کار به این صورت خواهد بود:

نتیجه کار
نتیجه کار

اسکرول عمودی
حالا میرسیم به قسمت جدید و کاربردی اسکرول عمودی در ViewPager

viewPager2.orientation = ViewPager2.ORIENTATION_VERTICAL

نتیجه به این شکل خواهد بود:

نتیجه اسکرول عمودی
نتیجه اسکرول عمودی

استفاده از FragmentStateAdapter
شما همچنین میتونید فرگمنت هارو با روش قدیمی ViewPager هم بسازید؛ برای این کار باید از FragmentStateAdapter استفاده کنیم:
- ابتدا فرگمنت رو میسازیم:

class PagerFragment : Fragment() {

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

 override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
 arguments?.let {
 container.setBackgroundResource(it.getInt("color"))
 tvTitle.text = "Item ${it.getInt("position")}"
 }
 }
}

- حالا باید یک آداپتر برای مدیریت فرگمنت (ها) مون بسازیم:

class ViewPagerFragmentStateAdapter(fm: FragmentManager) : FragmentStateAdapter(fm){

    privateval colors = intArrayOf(
        android.R.color.black,
        android.R.color.holo_red_light,
        android.R.color.holo_blue_dark,
        android.R.color.holo_purple
    )

    override fun getItem(position: Int): Fragment = PagerFragment().apply {
        arguments = bundleOf(
            "color" to colors[position],
            "position" to position
        )
    }

    override fun getItemCount(): Int = colors.size
}

- و در مرحله آخر باید آداپترمون رو روی ViewPager ست کنیم:

viewPager2.adapter = ViewPagerFragmentStateAdapter(supportFragmentManager)


متد ChangeCallback خیلی آسان
در ViewPager نسخه قبل ما با استفاده از متد ChangeListener کار های مثل تغییرات Page یا Event های Scroll شدن رو مدیریت می کردیم این کار مشکلاتی داشت مثلا ما مجبور بودیم همه متد های ScrollStateChanged، dScrolled و Selected رو پیاده سازی می کردیم فارغ از اینکه با کدومشون کار داریم!! مثل زیر:

oldViewPager.addChangeListener(object:ViewPager.ChangeListener{
 override fun ScrollStateChanged(state: Int) {
 // useless
 }

 override fun Scrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
 // useless too
 }

 override fun Selected(position: Int) {
 // useful
 }
})

خبر خوب اینه که این روزا رفتن و دیگه نیازی به این کار نیست :) ما حالا با استفاده از ViewPager 2 و با متد ChangeCallback که یک abstract class هستش و البته شامل متد های non-abstract هست.
یعنی چی؟ یعنی اینکه ما فقط متدی رو پیاده سازی میکنیم که نیاز داریم:

viewPager2.registerChangeCallback(object : ViewPager2.ChangeCallback() {
 override fun Selected(position: Int) {
 super.Selected(position)
 // No boilerplate, only useful
 }
})

هشدار
کتابخونه ViewPager 2 هنوز در نسخه alpha(غیر stable) هستش؛ بعضی از ویژگی های نسخه قبلی در نسخه جدید به درستی کار نمیکنن یا ناقص هستند و خب بزودی و در نسخه Stable احتمالا این مشکلات برطرف میشن؛ خود داکیومنت گوگل این موارد رو معرفی کرده:
- ClipToPadding
- No implementation for integrating with TabLayout
- no offscreen limit control
- (no pageWidth setter (forced 100%/100%
اطلاعات بیشتر در اینجا

منبع