Skip to content

Instantly share code, notes, and snippets.

@webserveis
Created July 7, 2022 15:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webserveis/4dd94566f9146bc7f018067e4c6b60f1 to your computer and use it in GitHub Desktop.
Save webserveis/4dd94566f9146bc7f018067e4c6b60f1 to your computer and use it in GitHub Desktop.
TabLayout MVVM Kotlin
class FirstFragment : Fragment() {
private var _binding: FragmentFirstBinding? = null
private val binding get() = _binding!!
val viewModel by activityViewModels<MyViewModel>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentFirstBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
initViewPager()
viewModel.getCountList.observe(viewLifecycleOwner, Observer { sparseArray ->
val size: Int = sparseArray.size()
for (i in 0 until size) {
val key: Int = sparseArray.keyAt(i)
val value: Int = sparseArray.valueAt(i)
Log.i("TAG", "key: $key value: $value")
val title = when (key) {
0 -> "In: $value"
1 -> "Out: $value"
else -> "?"
}
changeTabTitle(key, title)
}
})
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
private fun initViewPager() {
val pagerAdapter = CustomPagerAdapter(requireActivity())
val oneFragment = ListOneFragment().apply {
arguments = Bundle().apply {
putInt(MyConstants.ARG_POSITION, 0)
}
}
val twoFragment = ListTwoFragment().apply {
arguments = Bundle().apply {
putInt(MyConstants.ARG_POSITION, 1)
}
}
pagerAdapter.addFragment(oneFragment, "In: 0")
pagerAdapter.addFragment(twoFragment, "Out: 0")
binding.viewPager.adapter = pagerAdapter
TabLayoutMediator(binding.tabLayout, binding.viewPager) { tab, position ->
tab.text = pagerAdapter.getPageTitle(position) //"${position + 1}"
}.attach()
}
private fun changeTabTitle(position: Int, title: String) {
val tabLayout = binding.tabLayout
val tab0 = tabLayout.getTabAt(position)
tab0?.text = title
}
private inner class CustomPagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
private val mFragmentList = ArrayList<Fragment>()
private val mFragmentTitleList = ArrayList<String>()
override fun getItemCount(): Int {
return mFragmentList.size
}
override fun createFragment(position: Int): Fragment {
return mFragmentList[position]
}
fun getPageTitle(position: Int): CharSequence {
return mFragmentTitleList[position]
}
fun addFragment(fragment: Fragment, title: String) {
mFragmentList.add(fragment)
mFragmentTitleList.add(title)
}
}
}
<?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=".FirstFragment">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/second_fragment_label"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tab_layout" />
</androidx.constraintlayout.widget.ConstraintLayout>
<?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=".ListOneFragment">
<TextView
android:id="@+id/textview_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/button_second"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button_second"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/previous"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textview_second" />
</androidx.constraintlayout.widget.ConstraintLayout>
class ListOneFragment : Fragment() {
companion object {
private const val TAG = "ListOneFragment"
}
private var _binding: FragmentSecondBinding? = null
private val binding get() = _binding!!
val viewModel by activityViewModels<MyViewModel>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentSecondBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
arguments?.takeIf { it.containsKey(MyConstants.ARG_POSITION) }?.apply {
binding.textviewSecond.text = getInt(MyConstants.ARG_POSITION).toString()
}
viewModel.getListOne.observe(viewLifecycleOwner, Observer { data ->
binding.textviewSecond.text = data.toString()
})
binding.buttonSecond.setOnClickListener {
viewModel.fetchListOne()
}
}
}
class ListTwoFragment : Fragment() {
companion object {
private const val TAG = "ListTwoFragment"
}
private var _binding: FragmentSecondBinding? = null
private val binding get() = _binding!!
private val viewModel by activityViewModels<MyViewModel>()
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
_binding = FragmentSecondBinding.inflate(inflater, container, false)
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
arguments?.takeIf { it.containsKey(MyConstants.ARG_POSITION) }?.apply {
binding.textviewSecond.text = getInt(MyConstants.ARG_POSITION).toString()
}
viewModel.getListTwo.observe(viewLifecycleOwner, Observer { data ->
binding.textviewSecond.text = data.toString()
})
binding.buttonSecond.setOnClickListener {
viewModel.fetchListTwo()
}
}
}
class MyViewModel : ViewModel() {
companion object {
private const val TAG = "MyViewModel"
}
private val _mListOne: MutableLiveData<List<String>> = MutableLiveData()
val getListOne: LiveData<List<String>>
get() = _mListOne
private val _mListTwo: MutableLiveData<List<String>> = MutableLiveData()
val getListTwo: LiveData<List<String>>
get() = _mListTwo
private val _mCountList: SparseArray<Int> = SparseArray()
private val _countList: MutableLiveData<SparseArray<Int>> = MutableLiveData()
val getCountList: LiveData<SparseArray<Int>>
get() = _countList
fun fetchListOne() {
Log.d(TAG, "fetchListOne: ")
val mList: MutableList<String> = arrayListOf()
for (i in 1..15) {
mList.add("In $i")
}
_mListOne.value = mList
_mCountList.put(0, mList.count())
_countList.value = _mCountList
}
fun fetchListTwo() {
Log.d(TAG, "fetchListTwo: ")
val mList: MutableList<String> = arrayListOf()
for (i in 1..25) {
mList.add("Out $i")
}
_mListTwo.value = mList
_mCountList.put(1, mList.count())
_countList.value = _mCountList
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment