亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

深入了解ViewPager2的使用

 更新時(shí)間:2020年12月30日 09:30:34   作者:我賭一包辣條  
這篇文章主要介紹了ViewPager2 使用的相關(guān)資料,幫助大家更好的進(jìn)行Android開發(fā),感興趣的朋友可以了解下

一、ViewPager2的新特性

ViewPager2從名字就可以看出來它是ViewPager的升級(jí)版,既然是升級(jí)版那么它相比ViewPager有哪些新功能和哪些API變化呢?我們接著往下看。

1.ViewPager2新特性

  • 基于RecyclerView實(shí)現(xiàn)。這意味著RecyclerView的優(yōu)點(diǎn)將會(huì)被ViewPager2所繼承。
  • 支持豎直滑動(dòng)。只需要一個(gè)參數(shù)就可以改變滑動(dòng)方向。
  • 支持關(guān)閉用戶輸入。通過setUserInputEnabled來設(shè)置是否禁止用戶滑動(dòng)頁面。
  • 支持通過編程方式滾動(dòng)。通過fakeDragBy(offsetPx)代碼模擬用戶滑動(dòng)頁面。
  • CompositePageTransformer 支持同時(shí)添加多個(gè)PageTransformer。
  • 支持DiffUtil ,可以添加數(shù)據(jù)集合改變的item動(dòng)畫。
  • 支持RTL (right-to-left)布局。我覺得這個(gè)功能對(duì)國內(nèi)開發(fā)者來說可能用處不大..

2.相比ViewPager變化的API

ViewPager2相比ViewPager做了哪些改變呢?研究了一番之后我大概列出以下幾點(diǎn):

  • ViewPager2與ViewPager同是繼承自ViewGrop,但是ViewPager2被聲明成了final。意味著我們不可能再像ViewPager一樣通過繼承來修改ViewPager2的代碼。
  • FragmentStatePagerAdapter被FragmentStateAdapter 替代
  • PagerAdapter被RecyclerView.Adapter替代
  • addPageChangeListener被registerOnPageChangeCallback。我們知道ViewPager的addPageChangeListener接收的是一個(gè)OnPageChangeListener的接口,而這個(gè)接口中有三個(gè)方法,當(dāng)想要監(jiān)聽頁面變化時(shí)需要重寫這三個(gè)方法。而ViewPager2的registerOnPageChangeCallback方法接收的是一個(gè)叫OnPageChangeCallback的抽象類,因此我們可以選擇性的重寫需要的方法即可。
  • 移除了setPargeMargin方法。

以上所羅列的新特性和API可能并不完整,如有疏漏可以留言補(bǔ)充。

二、開啟ViewPager2之旅

ViewPager2位于androidx包下,也就是它不像ViewPager一樣被內(nèi)置在系統(tǒng)源碼中。因此,使用ViewPager2需要額外的添加依賴庫。另外,android support中不包含ViewPager,也就是要使用ViewPager2必須遷移到androidx才可以。

1.添加依賴,目前ViewPager2的最新版本是1.0.0:

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

2.ViewPager2布局文件:

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

3.ViewPager2的Adapter

因?yàn)閂iewPager2內(nèi)部封裝的是RecyclerView,因此它的Adapter也就是RecyclerView的Adapter。

class MyAdapter : RecyclerView.Adapter<MyAdapter.PagerViewHolder>() {
  private var mList: List<Int> = ArrayList()
  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PagerViewHolder {
    val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_page, parent, false)
    return PagerViewHolder(itemView)
  }

  override fun onBindViewHolder(holder: PagerViewHolder, position: Int) {
    holder.bindData(mList[position])
  }

  fun setList(list: List<Int>) {
    mList = list
  }

  override fun getItemCount(): Int {
    return mList.size
  }
	//	ViewHolder需要繼承RecycleView.ViewHolder
  class PagerViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
    private val mTextView: TextView = itemView.findViewById(R.id.tv_text)
    private var colors = arrayOf("#CCFF99","#41F1E5","#8D41F1","#FF99CC")

    fun bindData(i: Int) {
      mTextView.text = i.toString()
      mTextView.setBackgroundColor(Color.parseColor(colors[i]))
    }
  }
}

item_page中代碼如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:gravity="center">

  <TextView
    android:id="@+id/tv_text"
    android:background="@color/colorPrimaryDark"
    android:layout_width="match_parent"
    android:layout_height="280dp"
    android:gravity="center"
    android:textColor="#ffffff"
    android:textSize="22sp" />
</LinearLayout>

4.在Activity中為ViewPager設(shè)置Adapter

很簡單就完成了一個(gè)ViewPager的功能,來看下效果怎么樣:

5.ViewPager2豎直滑動(dòng)

接下來我們通過一行代碼為其設(shè)置豎直滑動(dòng)

viewPager2.orientation = ViewPager2.ORIENTATION_VERTICAL

豎直滑動(dòng)用ViewPager是很難實(shí)現(xiàn)的,而通過ViewPager2只需要設(shè)置一個(gè)參數(shù)即可。來看下效果:

6.頁面滑動(dòng)事件監(jiān)聽

上文已經(jīng)提到過了,我們?yōu)閂iewPager設(shè)置頁面滑動(dòng)的監(jiān)聽事件需要重寫三個(gè)方法,而為ViewPager2設(shè)置監(jiān)聽事件只需要重寫需要的方法即可,因?yàn)閂iewPager2中OnPageChangeCallback是一個(gè)抽象類。

viewPager2.registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
      override fun onPageSelected(position: Int) {
        super.onPageSelected(position)
        Toast.makeText(this@MainActivity, "page selected $position", Toast.LENGTH_SHORT).show()
      }
    })

7.setUserInputEnabled與fakeDragBy

我們知道,在使用ViewPager的時(shí)候想要禁止用戶滑動(dòng)需要重寫ViewPager的onInterceptTouchEvent。而ViewPager2被聲明為了final,我們無法再去繼承ViewPager2。那么我們應(yīng)該怎么禁止ViewPager2的滑動(dòng)呢?其實(shí)在ViewPager2中已經(jīng)為我們提供了這個(gè)功能,只需要通過setUserInputEnabled即可實(shí)現(xiàn)。

viewPager2.isUserInputEnabled = false

同時(shí)ViewPager2新增了一個(gè)fakeDragBy的方法。通過這個(gè)方法可以來模擬拖拽。在使用fakeDragBy前需要先beginFakeDrag方法來開啟模擬拖拽。fakeDragBy會(huì)返回一個(gè)boolean值,true表示有fake drag正在執(zhí)行,而返回false表示當(dāng)前沒有fake drag在執(zhí)行。我們通過代碼來嘗試下:

fun fakeDragBy(view: View) {
    viewPager2.beginFakeDrag()
    if (viewPager2.fakeDragBy(-310f))
      viewPager2.endFakeDrag()
  }

需要注意到是fakeDragBy接受一個(gè)float的參數(shù),當(dāng)參數(shù)值為正數(shù)時(shí)表示向前一個(gè)頁面滑動(dòng),當(dāng)值為負(fù)數(shù)時(shí)表示向下一個(gè)頁面滑動(dòng)。
下面來看下效果圖:

演示圖中禁止了用戶輸入,通過按鈕點(diǎn)擊可以模擬用戶滑動(dòng)。

三、ViewPager2的PageTransformer

相比ViewPager,ViewPager2的Transformer功能有了很大的擴(kuò)展。ViewPager2不僅可以通過PageTransformer用來設(shè)置頁面動(dòng)畫,還可以用PageTransformer設(shè)置頁面間距以及同時(shí)添加多個(gè)PageTransformer。接下來我們就來認(rèn)識(shí)下ViewPager2的PageTransformer吧!

1.setPageMargin

在第一章中我們提到了ViewPager2移除了setPageMargin方法,那么怎么為ViewPager2設(shè)置頁面間距呢?其實(shí)在ViewPager2中為我們提供了MarginPageTransformer,我們可以通過ViewPager2的setPageTransformer方法來設(shè)置頁面間距。代碼如下:

viewPager2.setPageTransformer(MarginPageTransformer(resources.getDimension(R.dimen.dp_10).toInt()))

上述代碼我們?yōu)閂iewPager2設(shè)置了10dp的頁面間距。效果如下:

2.認(rèn)識(shí)CompositePageTransformer

這個(gè)時(shí)候我們應(yīng)該有個(gè)疑問,為ViewPager2設(shè)置了頁面間距后如果還想設(shè)置頁面動(dòng)畫的Transformer怎么辦呢?這時(shí)候就該CompositePageTransformer出場(chǎng)了。從名字上也可以看出來它是一個(gè)組合的PageTransformer。沒錯(cuò),CompositePageTransformer實(shí)現(xiàn)了PageTransformer接口,同時(shí)在其內(nèi)部維護(hù)了一個(gè)List集合,我們可以將多個(gè)PageTransformer添加到CompositePageTransformer中。

val compositePageTransformer = CompositePageTransformer()
    compositePageTransformer.addTransformer(ScaleInTransformer())
    compositePageTransformer.addTransformer(MarginPageTransformer(resources.getDimension(R.dimen.dp_10).toInt()))
    viewPager2.setPageTransformer(compositePageTransformer)

上述代碼中我們通過CompositePageTransformer為ViewPager設(shè)置了MarginPageTransformer和一個(gè)頁面縮放的ScaleInTransformer。來看下效果:

3.ViewPager2中的PageTransformer

PageTransformer是一個(gè)位于ViewPager2中的接口,因此ViewPager2的PageTransformer是獨(dú)立于ViewPager的,它與ViewPager的PageTransformer沒有任何關(guān)系。雖然如此,卻不必?fù)?dān)心。因?yàn)閂iewPager2的PageTransformer和ViewPager的PageTransformer實(shí)現(xiàn)方式一模一樣。我們看下上一小節(jié)中用到的ScaleInTransformer:

class ScaleInTransformer : ViewPager2.PageTransformer {
  private val mMinScale = DEFAULT_MIN_SCALE
  override fun transformPage(view: View, position: Float) {
    view.elevation = -abs(position)
    val pageWidth = view.width
    val pageHeight = view.height

    view.pivotY = (pageHeight / 2).toFloat()
    view.pivotX = (pageWidth / 2).toFloat()
    if (position < -1) {
      view.scaleX = mMinScale
      view.scaleY = mMinScale
      view.pivotX = pageWidth.toFloat()
    } else if (position <= 1) {
      if (position < 0) {
        val scaleFactor = (1 + position) * (1 - mMinScale) + mMinScale
        view.scaleX = scaleFactor
        view.scaleY = scaleFactor
        view.pivotX = pageWidth * (DEFAULT_CENTER + DEFAULT_CENTER * -position)
      } else {
        val scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale
        view.scaleX = scaleFactor
        view.scaleY = scaleFactor
        view.pivotX = pageWidth * ((1 - position) * DEFAULT_CENTER)
      }
    } else {
      view.pivotX = 0f
      view.scaleX = mMinScale
      view.scaleY = mMinScale
    }
  }

  companion object {

    const val DEFAULT_MIN_SCALE = 0.85f
    const val DEFAULT_CENTER = 0.5f
  }
}

4.ViewPager2的一屏多頁效果

在ViewPager2的官方Sample上看到了ViewPager2的一屏多頁可以通過為RecyclerView設(shè)置Padding來實(shí)現(xiàn)。代碼如下:

viewPager2.apply { 
      offscreenPageLimit=1
      val recyclerView= getChildAt(0) as RecyclerView
      recyclerView.apply {
        val padding = resources.getDimensionPixelOffset(R.dimen.dp_10) +
            resources.getDimensionPixelOffset(R.dimen.dp_10)
        // setting padding on inner RecyclerView puts overscroll effect in the right place
        setPadding(padding, 0, padding, 0)
        clipToPadding = false
      }
    }
val compositePageTransformer = CompositePageTransformer()
compositePageTransformer.addTransformer(ScaleInTransformer())
compositePageTransformer.addTransformer(MarginPageTransformer(resources.getDimension(R.dimen.dp_10).toInt()))
viewPager2.setPageTransformer(compositePageTransformer)

最后,我們來看下效果

四、ViewPager2與Fragment

我們前面也已經(jīng)提到了ViewPager2中新增的FragmentStateAdapter 替代了ViewPager的FragmentStatePagerAdapter。那么來我們就用ViewPager2來實(shí)現(xiàn)一個(gè)Activity中嵌套Fragment的實(shí)例。

1.Activity的layout中添加ViewPager2

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

2.實(shí)現(xiàn)FragmentStateAdapter

class AdapterFragmentPager(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {

  private val fragments: SparseArray<BaseFragment> = SparseArray()

  init {
    fragments.put(PAGE_HOME, HomeFragment.getInstance())
    fragments.put(PAGE_FIND, PageFragment.getInstance())
    fragments.put(PAGE_INDICATOR, IndicatorFragment.getInstance())
    fragments.put(PAGE_OTHERS, OthersFragment.getInstance())
  }

  override fun createFragment(position: Int): Fragment {
    var fragment: Fragment
    when (position) {
      PAGE_HOME -> {
        if (fragments.get(PAGE_HOME) == null) {
          fragment = HomeFragment.getInstance();
          fragments.put(PAGE_HOME, fragment)
        } else {
          fragment = fragments.get(PAGE_HOME)
        }
      }
      PAGE_FIND -> {
        if (fragments.get(PAGE_FIND) == null) {
          fragment = PageFragment.getInstance();
          fragments.put(PAGE_FIND, fragment)
        } else {
          fragment = fragments.get(PAGE_FIND)
        }
      }

      PAGE_INDICATOR -> {
        if (fragments.get(PAGE_INDICATOR) == null) {
          fragment = IndicatorFragment.getInstance();
          fragments.put(PAGE_INDICATOR, fragment)
        } else {
          fragment = fragments.get(PAGE_INDICATOR)
        }
      }

      PAGE_OTHERS -> {
        if (fragments.get(PAGE_OTHERS) == null) {
          fragment = OthersFragment.getInstance();
          fragments.put(PAGE_OTHERS, fragment)
        } else {
          fragment = fragments.get(PAGE_OTHERS)
        }
      }
      else -> {
        if (fragments.get(PAGE_HOME) == null) {
          fragment = HomeFragment.getInstance();
          fragments.put(PAGE_HOME, fragment)
        } else {
          fragment = fragments.get(PAGE_HOME)
        }
      }
    }
    return fragment
  }

  override fun getItemCount(): Int {
    return fragments.size()
  }

  companion object {

    const val PAGE_HOME = 0

    const val PAGE_FIND = 1

    const val PAGE_INDICATOR = 2

    const val PAGE_OTHERS = 3

  }

}

3.在Activity中為ViewPager2設(shè)置FragmentStateAdapter

vp_fragment.adapter = AdapterFragmentPager(this)
    vp_fragment.offscreenPageLimit = 3
    vp_fragment.isUserInputEnabled=false

五、ViewPager2與TabLayout

TabLayout也是項(xiàng)目中經(jīng)常用到的一個(gè)控件,它通常會(huì)與ViewPager一起出現(xiàn)。那么對(duì)于ViewPager2應(yīng)該怎么使用Tablayout呢?這需要我們認(rèn)識(shí)一個(gè)新類TabLayoutMediator,這個(gè)類是在material-1.2.0中新增的一個(gè)類,目前material包的最新版本是1.2.0-alpha03,因此需要我們單獨(dú)引入這個(gè)包,依賴如下:

implementation 'com.google.android.material:material:1.2.0-alpha03'

TabLayoutMediator的構(gòu)造方法接收三個(gè)參數(shù),第一個(gè)參數(shù)為TabLayout;第二個(gè)參數(shù)為ViewPager2;第三個(gè)參數(shù)是TabConfigurationStrategy,這是一個(gè)接口,該接口中有一個(gè)方法onConfigureTab(@NonNull TabLayout.Tab tab, int position),第一個(gè)參數(shù)是當(dāng)前Tab,第二個(gè)當(dāng)前position,源碼如下:

public interface TabConfigurationStrategy {
 /**
  * Called to configure the tab for the page at the specified position. Typically calls {@link
  * TabLayout.Tab#setText(CharSequence)}, but any form of styling can be applied.
  *
  * @param tab The Tab which should be configured to represent the title of the item at the given
  *   position in the data set.
  * @param position The position of the item within the adapter's data set.
  */
 void onConfigureTab(@NonNull TabLayout.Tab tab, int position);
}

接下來我們便可以通過TabLayoutMediator將TabLayout與ViewPager2關(guān)聯(lián)起來了:

TabLayoutMediator(tab_layout, view_pager) { tab, position ->
      // 為Tab設(shè)置Text
      tab.text = Card.DECK[position].toString()
    }.attach()

使用起來非常簡單,實(shí)現(xiàn)效果如下圖所示:

六、小結(jié)

本篇文章我們認(rèn)識(shí)了ViewPager2的新特性以及其用法。總得來說ViewPager2相比ViewPager不管在性能上還是在功能上都有了很大的提升。因此,我相信在不久的未來ViewPager2必定會(huì)取代ViewPager。那么,你是否已經(jīng)考慮將ViewPager2用到你的項(xiàng)目中了呢?

最后再來給大家推薦一下BannerViewPager。這是一個(gè)基于ViewPager實(shí)現(xiàn)的具有強(qiáng)大功能的無限輪播庫。在未來,我會(huì)在BannerViewPager 3.0版本中用ViewPager2來重構(gòu)代碼。歡迎大家到GitHub關(guān)注BannerViewPager 。

本文涉及源碼下載

第四節(jié)中ViewPager2與Fragment的代碼見:

BannerViewPager

以上就是深入了解ViewPager2的使用的詳細(xì)內(nèi)容,更多關(guān)于ViewPager2 使用教程的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android播放視頻的三種方式

    Android播放視頻的三種方式

    這篇文章主要為大家詳細(xì)介紹了Android播放視頻的三種方式,使用其自帶的播放器、VideoView、MediaPlayer類和SurfaceView來實(shí)現(xiàn),感興趣的小伙伴們可以參考一下
    2016-07-07
  • Android實(shí)現(xiàn)圖片九宮格

    Android實(shí)現(xiàn)圖片九宮格

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)圖片九宮格,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • android檢測(cè)網(wǎng)絡(luò)連接狀態(tài)示例講解

    android檢測(cè)網(wǎng)絡(luò)連接狀態(tài)示例講解

    網(wǎng)絡(luò)的時(shí)候,并不是每次都能連接到網(wǎng)絡(luò),因此在程序啟動(dòng)中需要對(duì)網(wǎng)絡(luò)的狀態(tài)進(jìn)行判斷,如果沒有網(wǎng)絡(luò)則提醒用戶進(jìn)行設(shè)置
    2014-02-02
  • Android編程之?dāng)?shù)據(jù)庫的創(chuàng)建方法詳解

    Android編程之?dāng)?shù)據(jù)庫的創(chuàng)建方法詳解

    這篇文章主要介紹了Android編程之?dāng)?shù)據(jù)庫的創(chuàng)建方法,結(jié)合實(shí)例形式分析了Android數(shù)據(jù)庫創(chuàng)建的步驟、實(shí)現(xiàn)技巧與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2017-08-08
  • Android raw 目錄下視頻的縮略圖的獲取

    Android raw 目錄下視頻的縮略圖的獲取

    這篇文章主要介紹了 Android raw 目錄下視頻的縮略圖的獲取的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • Android自定義PopupWindow仿點(diǎn)擊彈出分享功能

    Android自定義PopupWindow仿點(diǎn)擊彈出分享功能

    這篇文章主要為大家詳細(xì)介紹了Android自定義PopupWindow仿點(diǎn)擊彈出分享功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • Android 自定義標(biāo)題欄背景

    Android 自定義標(biāo)題欄背景

    最近在做android項(xiàng)目,需要做一個(gè)自定義的標(biāo)題欄(操作欄)。去網(wǎng)上找了很多demo,發(fā)現(xiàn)都有很多問題。例如使用自定義的style。下面來分享下個(gè)人最終的解決方案吧
    2016-01-01
  • Android解析json數(shù)據(jù)示例代碼(三種方式)

    Android解析json數(shù)據(jù)示例代碼(三種方式)

    本篇文章主要介紹了Android解析json數(shù)據(jù)示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • Android中去掉標(biāo)題欄的幾種方法(三種)

    Android中去掉標(biāo)題欄的幾種方法(三種)

    本文給大家?guī)砹巳Nandroid去掉標(biāo)題欄的方法,都非常不錯(cuò),對(duì)android 去掉標(biāo)題欄的方法感興趣的朋友一起通過本文學(xué)習(xí)吧
    2016-08-08
  • Android編程四大組件之Activity用法實(shí)例分析

    Android編程四大組件之Activity用法實(shí)例分析

    這篇文章主要介紹了Android編程四大組件之Activity用法,實(shí)例分析了Activity的創(chuàng)建,生命周期,內(nèi)存管理及啟動(dòng)模式等,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2016-01-01

最新評(píng)論