理解できれば比較的簡単です。
スマホでは横スワイプで画面を切り替えるような画面がある。ほとんどはタブと連動していて上部または下部にあるタブを選択しても画面を切り替えることができる。AndroidではTabLayoutとViewPagerを利用すると比較的簡単に実装できる。
この機能ではFragmentを利用する必要がある。なので、まずはFragmentを作成する。今回は試しにTextViewとButtonだけを設置した簡単なものを用意した。以下が用意したFragmentである。
まずはレイアウトがこちら。シンプルにボタンとテキストビューを設置してあるだけ。
その次にメインとなるアクティビティのUI部品のレイアウトを設置する。ToolbarやNavigationDrawerと併用するパターンが多いと思うが、今回は簡単にTabLayoutとViewPagerを設置してあるだけである。
ここからが少し実装が難しくなる。
ViewPagerにFragmentを実装するために、FragmentPagerAdapterというどのようにVirePagerにFragmentを実装するのか挙動を記述したアダプターが必要になる。
最低限の実装としては、タブの数を返すgetCountと、どのタブにどのFragmentを実装するのかを記述するgetItemだけを記述してあげればいい。
ここまでできれば、あとは比較的簡単に処理できる。
ViewPagerに先ほど作成したAdapterのインスタンスを渡してあければ横スワイプの機能を実装できるし、そのViewPagerのインスタンスをTabLayoutに渡してあげるだけでタブが自動的に認識してタブを生成してくれる。なお、TabLayoutのsetupWithViewPagerで設定すると、それまでのTabへの設定がクリアされてしまうので、そこからタブ名などを設定する場合には、後から処理をしてあげる必要がある。
この機能ではFragmentを利用する必要がある。なので、まずはFragmentを作成する。今回は試しにTextViewとButtonだけを設置した簡単なものを用意した。以下が用意したFragmentである。
まずはレイアウトがこちら。シンプルにボタンとテキストビューを設置してあるだけ。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tvTextView01"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toTopOf="@id/btnButton01"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnButton01"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvTextView01" />
</android.support.constraint.ConstraintLayout>
Fragmentにおける実装がこちら。レイアウトファイルを読み込むのと、ボタンクリック時にテキストビューの表示を切り替えるだけの簡単な処理を記述しただけのもの。
class Page01Fragment : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onAttachFragment(childFragment: Fragment?) {
super.onAttachFragment(childFragment)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view: View = inflater.inflate(R.layout.page01_fragment, null)
view?.findViewById<Button>(R.id.btnButton01)?.setOnClickListener {
view?.findViewById<TextView>(R.id.tvTextView01)?.text = "nullpo"
}
return view
}
その次にメインとなるアクティビティのUI部品のレイアウトを設置する。ToolbarやNavigationDrawerと併用するパターンが多いと思うが、今回は簡単にTabLayoutとViewPagerを設置してあるだけである。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.TabLayout
android:id="@+id/tabTab01"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/vpViewPager01"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v4.view.ViewPager
android:id="@+id/vpViewPager01"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tabTab01" />
</android.support.constraint.ConstraintLayout>
ここからが少し実装が難しくなる。
ViewPagerにFragmentを実装するために、FragmentPagerAdapterというどのようにVirePagerにFragmentを実装するのか挙動を記述したアダプターが必要になる。
最低限の実装としては、タブの数を返すgetCountと、どのタブにどのFragmentを実装するのかを記述するgetItemだけを記述してあげればいい。
//FragmentPagerAdapterを継承したクラスを作成する
class TestPagerAdapter(fm: FragmentManager, context: Context) : FragmentPagerAdapter(fm) {
//どのタブにどのFragmentを実装するか記述する
//今回はテストなのですべて同じFragmentを実装している。
override fun getItem(position: Int): Fragment {
when (position) {
0 -> {
return Page01Fragment()
}
1 -> {
return Page01Fragment()
}
2 -> {
return Page01Fragment()
}
3 -> {
return Page01Fragment()
}
else -> {
return Page01Fragment()
}
}
}
//今回はテストなので4つのタブ固定にしている
//実際のアプリではタブの数などを管理することもあるだろう
override fun getCount(): Int {
return 4
}
}
ここまでできれば、あとは比較的簡単に処理できる。
ViewPagerに先ほど作成したAdapterのインスタンスを渡してあければ横スワイプの機能を実装できるし、そのViewPagerのインスタンスをTabLayoutに渡してあげるだけでタブが自動的に認識してタブを生成してくれる。なお、TabLayoutのsetupWithViewPagerで設定すると、それまでのTabへの設定がクリアされてしまうので、そこからタブ名などを設定する場合には、後から処理をしてあげる必要がある。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//ViewPagerに先ほど作成したAdapterのインスタンスを渡してあげる
vpViewPager01.adapter = TestPagerAdapter(supportFragmentManager, this)
//TabLayoutにViewPagerのインスタンスを渡すと自動的に実装してくれる
tabTab01.setupWithViewPager(vpViewPager01)
//Tabへの処理はsetupWithViewPagerをした後だったら可能
//ここではタブ名とアイコンを設定している
for (i: Int in 0..tabTab01.tabCount) {
tabTab01.getTabAt(i)?.also {
it.setIcon(R.mipmap.ic_launcher)
it.text = "TAB" + i.toString()
}
}
}
}