"Home"、"Category"、"My" タブを含む TabBar を作成し、切り替え機能を実装します。これは通常、TabLayout と ViewPager または ViewPager2 を組み合わせて使用することで実現できます。ここでは、Kotlin と XML を使用してこの機能を実装する方法を示す基本的な例を示します。
デモ: https://github.com/Gamin-fzym/GAAndroidTestDemo
1. build.gradle に依存関係を追加します。
dependencies {
// ...
implementation("com.google.android.material:material:1.8.0")
implementation("androidx.viewpager2:viewpager2:1.0.0")
}
2. レイアウト XML ファイルで TabLayout と ViewPager2 を定義します。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabIndicatorHeight="0dp" />
</LinearLayout>
3. アクティビティに ViewPager2 と TabLayout を設定します
package com.example.gatestdemol.tabbar
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.gatestdemol.databinding.ActivityTabBarBinding
import com.google.android.material.tabs.TabLayoutMediator
class TabBarActivity : AppCompatActivity() {
private lateinit var binding: ActivityTabBarBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// setContentView(R.layout.activity_tab_bar)
binding = ActivityTabBarBinding.inflate(layoutInflater)
setContentView(binding.root)
val adapter = ViewPagerAdapter(this)
binding.viewPager.adapter = adapter
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
tab.text = when(position) {
0 -> "首页"
1 -> "分类"
2 -> "我的"
else -> null
}
}.attach()
}
private inner class ViewPagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
override fun getItemCount(): Int {
return 3
}
override fun createFragment(position: Int): Fragment {
return when(position) {
0 -> HomeFragment()
1 -> CategoryFragment()
2 -> ProfileFragment()
else -> Fragment()
}
}
}
}
上記のコードでは、FragmentStateAdapter を継承する ViewPagerAdapter クラスを作成し、getItemCount メソッドと createFragment メソッドをオーバーライドして、タブの数と対応する Fragment をそれぞれ返します。TabLayoutMediator は、TabLayout と ViewPager2 をバインドし、各タブのタイトルを設定するために使用されます。
4. 対応する Fragment クラスを作成します
package com.example.gatestdemol.tabbar
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.gatestdemol.databinding.FragmentHomeBinding
class HomeFragment: Fragment() {
private var binding: FragmentHomeBinding? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentHomeBinding.inflate(inflater,container,false)
return binding?.root
}
override fun onDestroy() {
super.onDestroy()
binding = null
}
}
class CategoryFragment : Fragment() {
// 实现分类Fragment的布局和逻辑
}
class ProfileFragment : Fragment() {
// 实现我的Fragment的布局和逻辑
}
各フラグメントはページに対応しており、独自のレイアウトとビジネス ロジックを実装できます。
これは基本的な TabBar 実装であり、必要に応じてアイコンやカスタム スタイルなどを追加できます。
単純なタブバー図:
5.TabBar添加Icon
package com.example.gatestdemol.tabbar
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.gatestdemol.R
import com.example.gatestdemol.databinding.ActivityTabBarBinding
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
class TabBarActivity : AppCompatActivity() {
private lateinit var binding: ActivityTabBarBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityTabBarBinding.inflate(layoutInflater)
setContentView(binding.root)
val adapter = ViewPagerAdapter(this)
binding.viewPager.adapter = adapter
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
tab.text = when(position) {
0 -> "首页"
1 -> "分类"
2 -> "我的"
else -> null
}
tab.icon = when(position) {
0 -> ContextCompat.getDrawable(this@TabBarActivity, R.drawable.ic_home_default)
1 -> ContextCompat.getDrawable(this@TabBarActivity, R.drawable.ic_category_default)
2 -> ContextCompat.getDrawable(this@TabBarActivity, R.drawable.ic_profile_default)
else -> null
}
}.attach()
binding.tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
// 一套Icon时用这种方式
//tab?.icon?.setTint(ContextCompat.getColor(applicationContext, R.color.your_selected_text_color))
// 两套Icon时用这种方式,XML中不要配置app:tabIconTint="@color/your_icon_tint_color"
tab?.icon = when(tab?.position) {
0 -> ContextCompat.getDrawable(this@TabBarActivity, R.drawable.ic_home_selected)
1 -> ContextCompat.getDrawable(this@TabBarActivity, R.drawable.ic_category_selected)
2 -> ContextCompat.getDrawable(this@TabBarActivity, R.drawable.ic_profile_selected)
else -> null
}
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
// 一套Icon时用这种方式
//tab?.icon?.setTint(ContextCompat.getColor(applicationContext, R.color.your_icon_tint_color))
// 两套Icon时用这种方式,XML中不要配置app:tabIconTint="@color/your_icon_tint_color"
tab?.icon = when(tab?.position) {
0 -> ContextCompat.getDrawable(this@TabBarActivity, R.drawable.ic_home_default)
1 -> ContextCompat.getDrawable(this@TabBarActivity, R.drawable.ic_category_default)
2 -> ContextCompat.getDrawable(this@TabBarActivity, R.drawable.ic_profile_default)
else -> null
}
}
override fun onTabReselected(tab: TabLayout.Tab?) {
// Do nothing
}
})
}
private inner class ViewPagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
override fun getItemCount(): Int {
return 3
}
override fun createFragment(position: Int): Fragment {
return when(position) {
0 -> HomeFragment()
1 -> CategoryFragment()
2 -> ProfileFragment()
else -> Fragment()
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="@color/your_indicator_color"
app:tabSelectedTextColor="@color/your_selected_text_color"
app:tabTextColor="@color/your_default_text_color"
app:tabIconTint="@color/your_icon_tint_color"
app:tabMode="fixed"
app:tabGravity="fill"
app:tabIndicatorHeight="0dp"
app:tabRippleColor="@android:color/transparent" />
</LinearLayout>
<resources>
......
<color name="your_indicator_color">#FF0000</color>
<color name="your_selected_text_color">#FF3700B3</color>
<color name="your_default_text_color">#FFBB86FC</color>
<color name="your_icon_tint_color">#FFBB86FC</color>
</resources>
回路図: