如何使用ViewPager(kotlin)

如何使用ViewPager(kotlin)

情境

如果你需要快速地翻閱一些連續的頁面,那麼就可以透過 ViewPager 這個元件達成這樣的效果,它是一個常見且廣泛使用的元件,簡單易懂程式碼在很多 App 上都可以看到。

程式碼下載

你可以到 GitHub 上面觀看或下載完整的程式碼。

程式碼說明

一開始我們先佈置整塊畫面就是 ViewPager,因此要將元件設定成 ViewPager,這邊要注意的是,目前採用 AndroidX 的引入函式庫方式,因此,元件名稱為 androidx.viewpager.widget.ViewPager

<?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:layout_width="match_parent"  
 android:layout_height="match_parent"  
 android:paddingBottom="@dimen/activity_vertical_margin"  
 android:paddingLeft="@dimen/activity_horizontal_margin"  
 android:paddingRight="@dimen/activity_horizontal_margin"  
 android:paddingTop="@dimen/activity_vertical_margin"  
 tools:context=".MainActivity">  

 <androidx.viewpager.widget.ViewPager 
  android:id="@+id/pager"  
  android:layout_width="wrap_content"  
  android:layout_height="wrap_content" />  
</RelativeLayout>

在 MainActivity 中初始化 ViewPager 以及建立三個 PagerView 的子類別,分別為 OneView、TwoView 和 ThreeView。

class MainActivity : AppCompatActivity() {  
    private lateinit var pageList: MutableList<PageView>  
    override fun onCreate(savedInstanceState: Bundle?) {  
        super.onCreate(savedInstanceState)  
        setContentView(R.layout.activity_main)  
        initData()  
        initView()  
    }  
  
    private fun initView() {  
        pager.adapter = SamplePagerAdapter(pageList)  
    }  
  
    private fun initData() {  
        pageList = ArrayList()  
        pageList.add(PageOneView(this@MainActivity))  
        pageList.add(PageTwoView(this@MainActivity))  
        pageList.add(PageThreeView(this@MainActivity))  
    }  
}

首先會發現有另外宣告一個 SamplePagerAdapter 類別,ViewPager 跟很多元件類似,可以透過 Adapter 來操作,我們宣告了一個 List 裡面裝了 View,由於要把 View 塞進 ViewPager ,因此,我宣告了一個很單純的 View 來規劃。

abstract class PageView(context: Context) : RelativeLayout(context) {  
    abstract fun refreshView()  
}

接著根據 ViewPager 想要加入多少個 View 就繼承 PageView,如此一來,我們在 MainActivity 內就可以利用陣列來操作所有的 View 了。

class PageOneView(context: Context) : PageView(context) {  
    init {  
        val view = LayoutInflater.from(context).inflate(R.layout.page_content, null)  
        val textView = view.findViewById(R.id.text) as TextView  
        textView.text = "Page one"  
  addView(view)  
    }  
    override fun refreshView() {}  
}

我們加入了三個 View,並且使用同一個 Layout。(只是範例, 如果你需要不同的 layout 可以自行定義)

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/text"
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</RelativeLayout>

可以發現我們的 view_content 只有一個很單純 TextView,在 initData() 方法被呼叫的時候,把這些 View 加進去。

pageList = ArrayList()  
pageList.add(PageOneView(this@MainActivity))  
pageList.add(PageTwoView(this@MainActivity))  
pageList.add(PageThreeView(this@MainActivity))

為什麼要讓每個 View 去繼承 PageView 呢? 理由很簡單,假設我每個 View 做了某些事情,需要重新整理,要一個一個寫 refreshview 的方法嗎?透過統一的介面處理,我們只需要在 PageView 新增一個虛擬方法 refresh,就可以讓所有 view 都去覆寫它了,這樣一來,就可以把重新整理的方法透過迴圈讓所有的 view 全部重整。

for (view in pageList) {  
    view.refreshView()  
}

這樣一來就很方便可以管理了。

效果如下圖。