ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android] Tab Layout 구현 (Tab 선택 시, icon & text 색상 변경)
    안드로이드 2024. 5. 16. 09:39

    ✏️ TIL(Today I Learned)

    하단에 Tab Layout을 만들어서, 클릭 시 선택된 탭의 아이콘과 텍스트의 색이 변경되면서 프래그먼트가 전환되도록 했다.

     

     

    레이아웃부터 만들어준다.

    상단에 툴바, 가운데에 뷰페이저, 하단에 탭으로 구성했다.

     

    그리고 한 가지 주의해야할 점이있다.

    메인 엑티비티에서 클릭된 탭의 텍스트 색을 변경하려고 아무리 해도 적용되지 않았는데, 

    xml의 TabLayout에 tabSelectedTextColor 속성을 추가하니 적용되었다...

     

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.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=".presentation.main.MainActivity">
    
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/tb_main"
            android:layout_width="match_parent"
            android:layout_height="56dp"
            android:background="@color/mainRed"
            app:titleTextColor="@color/white"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent">
    
            <ImageView
                android:id="@+id/tb_logo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:adjustViewBounds="true"
                android:scaleType="fitCenter"
                android:padding="12dp"
                android:src="@drawable/ic_logo" />
    
            <TextView
                android:id="@+id/tb_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="8dp"
                android:text="@string/main_toolbar_title"
                android:textColor="@color/white"
                android:textStyle="bold"
                android:textSize="22dp"/>
    
        </androidx.appcompat.widget.Toolbar>
    
        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/vp_main"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintBottom_toTopOf="@+id/tl_main"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/tb_main" />
    
        <com.google.android.material.tabs.TabLayout
            android:id="@+id/tl_main"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:tabIndicatorHeight="0dp"
            style="@style/tabLayout"
            app:tabSelectedTextColor="@color/white"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

     

     

    그리고 TabModel을 만든다.

    프래그먼트, 타이틀 리소스 ID, 아이콘 리소스 ID를 필드로 가진다.

    data class MainTabModel(
        val fragment: Fragment,
        @StringRes val title: Int,
        @DrawableRes val icon: Int
    )

     

     

    그 다음, ViewPagerAdapter를 만들었다.

    FragmentStateAdapter를 상속받는 어댑터 클래스로, MainActivityViewPager2에 연결한다.

    • MainTabModel 객체의 리스트
    • getItemCount() 함수를 통해 전체 탭의 개수를 반환
    • createFragment() 함수를 통해 해당 위치에 해당하는 프래그먼트를 생성
    • getTitle(), getTabIcon()를 통해 각 탭의 제목과 아이콘을 반환
    class MainViewPagerAdapter(
        fragmentActivity: FragmentActivity
    ) : FragmentStateAdapter(fragmentActivity) {
    
        private val fragments = listOf(
            MainTabModel(SearchFragment.newInstance(), R.string.main_tab_search_title, R.drawable.ic_search),
            MainTabModel(HomeFragment.newInstance(), R.string.main_tab_home_title, R.drawable.ic_home),
            MainTabModel(VideoDetailFragment.newInstance(), R.string.main_tab_myvideos_title, R.drawable.ic_my_videos),
        )
    
        override fun getItemCount(): Int = fragments.size
    
        override fun createFragment(position: Int): Fragment = fragments[position].fragment
    
        fun getTitle(position: Int): Int = fragments[position].title
    
        fun getTabIcon(position: Int): Int = fragments[position].icon
    }

     

     

    마지막으로, MainActivity이다.

    • ActivityMainBinding을 사용하여 레이아웃과의 바인딩을 처리
    • viewPagerAdapter를 초기화
    • onCreate()에서 화면을 설정하고 initView()를 호출
    • initView():
      ViewPager2와 TabLayout을 연결하고, 각 탭에 대한 아이콘 및 텍스트를 설정
      addOnTabSelectedListener를 통해, 탭 선택에 따라 아이콘의 색상을 변경
    class MainActivity : AppCompatActivity() {
        private val binding: ActivityMainBinding by lazy {
            ActivityMainBinding.inflate(layoutInflater)
        }
    
        private val viewPagerAdapter by lazy {
            MainViewPagerAdapter(this)
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(binding.root)
    
            initView()
        }
    
        private fun initView() = with(binding) {
            // TabLayout x ViewPager2
            vpMain.adapter = viewPagerAdapter
            vpMain.offscreenPageLimit = viewPagerAdapter.itemCount
    
            TabLayoutMediator(tlMain, vpMain) { tab, position ->
                tab.setText(viewPagerAdapter.getTitle(position))
                tab.setIcon(viewPagerAdapter.getTabIcon(position))
            }.attach()
    
            tlMain.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
                override fun onTabSelected(tab: TabLayout.Tab?) {
                    tab?.let {
                        it.icon?.setTint(getColor(R.color.white))
                    }
                }
    
                override fun onTabUnselected(tab: TabLayout.Tab?) {
                    tab?.let {
                        it.icon?.setTint(getColor(R.color.darkRed))
                    }
                }
    
                override fun onTabReselected(tab: TabLayout.Tab?) {
                    // 재선택 시
                }
            })
            tlMain.getTabAt(1)?.select() // Home을 default로 설정
        }
    }

     

Designed by Tistory.