Skip to content

Instantly share code, notes, and snippets.

@Kolyall
Last active February 2, 2022 16:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kolyall/f030f540efe25845e7b9abf9735dbe0b to your computer and use it in GitHub Desktop.
Save Kolyall/f030f540efe25845e7b9abf9735dbe0b to your computer and use it in GitHub Desktop.
FragmentStatePagerAdapter
class FavMainAdapter constructor(
val context: Context?,
fragmentManager: FragmentManager
) : BaseFragmentPagerAdapter(fragmentManager) {
override fun createItem(position: Int): BaseFragment {
return when (position) {
0 -> MyCollectionsFragment()
1 -> MyPlaylistsFragment()
else -> throw IndexOutOfBoundsException("IndexOutOfBounds $position")
}
}
override fun getCount(): Int {
return 2
}
override fun getPageTitle(position: Int): CharSequence? {
val item = FavMainPagerItem.values()[position]
return context?.getString(item.titleId)
}
}
class FavMainFragment
pagerAdapter override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupViewPager()
tabLayout.setViewPager(viewPager)
}
private fun setupViewPager() {
pagerAdapter = FavMainAdapter(activity, childFragmentManager)
viewPager.isStopScrollWhenTouch = false
viewPager.adapter = pagerAdapter
viewPager.currentItem = FavMainPagerItem.COLLECTIONS.ordinal
}
abstract class BaseFragmentPagerAdapter(
open val fragmentManager: FragmentManager
) : FragmentStatePagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
/**
* State key for the fragment super state.
*/
private val ADS_FRAGMENT_STATE_SUPER_STATE = "superState"
/**
* State key for the fragment pages.
*/
private val ADS_FRAGMENT_STATE_PAGES_COUNT = "pages_count"
/**
* A list of fragments displayed by this adapter.
*/
private val pages = SparseArray<BaseFragment>()
fun addFragment(fragment: BaseFragment, position: Int = -1) {
val index = if (position == -1) pages.size() else position
pages.put(index, fragment)
}
override fun getItem(position: Int): Fragment {
val fragment = createItem(position)
addFragment(fragment, position)
return fragment
}
override fun getItemPosition(item: Any): Int {
// Causes adapter to reload all Fragments when
// notifyDataSetChanged is called
return PagerAdapter.POSITION_NONE
}
abstract fun createItem(position: Int): BaseFragment
override fun destroyItem(container: ViewGroup, position: Int, item: Any) {
if (pages.indexOfKey(position) >= 0) {
pages.remove(position)
}
super.destroyItem(container, position, item)
}
override fun saveState(): Parcelable? {
val parcelable = super.saveState()
val bundle = Bundle()
bundle.putParcelable(ADS_FRAGMENT_STATE_SUPER_STATE, parcelable)
bundle.putInt(ADS_FRAGMENT_STATE_PAGES_COUNT, pages.size())
if (count > 0) {
for (i in 0 until count) {
val position = pages.keyAt(i)
bundle.putInt(i.cacheIndex(), position)
val fragment = pages.get(position)
fragmentManager.putFragment(bundle, position.cacheKey(), fragment)
}
}
return bundle
}
override fun restoreState(state: Parcelable?, loader: ClassLoader?) {
try {
val bundle = state as? Bundle ?: return
val pageCount = bundle.getInt(ADS_FRAGMENT_STATE_PAGES_COUNT)
if (pageCount > 0) {
for (i in 0 until pageCount) {
val position = bundle.getInt(i.cacheIndex())
val fragment = fragmentManager.getFragment(bundle, position.cacheKey()) as BaseFragment
addFragment(fragment, position)
}
}
val parcelable = bundle.getParcelable<Parcelable?>(ADS_FRAGMENT_STATE_SUPER_STATE)
super.restoreState(parcelable, loader)
} catch (e: Exception) {
Log.e("TAG", "Error Restore State of Fragment : " + e.message, e)
}
}
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
for (i in 0 until count) {
val fragment = pages.get(i) ?: continue
fragment.onActivityResult(requestCode, resultCode, data)
}
}
fun onHandleBackPress(): Boolean {
var handled = false
for (i in 0 until count) {
val fragment = pages.get(i) ?: continue
if (fragment.onHandleBackPress()) handled = true
}
return handled
}
fun setRestoredFromBackstack(restoredFromBackstack: Boolean) {
for (i in 0 until count) {
val fragment = pages.get(i) ?: continue
fragment.isRestoredFromBackstack = restoredFromBackstack
}
}
fun setRetainInstance(retain: Boolean) {
for (i in 0 until count) {
val fragment = pages.get(i) ?: continue
fragment.retainInstance = retain
}
}
}
/**
* Create an index string for caching fragment pages.
*
* @param index The index of the item in the adapter.
*
* @return The key string for caching fragment pages.
*/
private fun Int.cacheIndex(): String {
return "pageIndex:$this"
}
/**
* Create a key string for caching fragment pages.
*
* @param position The position of the item in the adapter.
*
* @return The key string for caching fragment pages.
*/
private fun Int.cacheKey(): String {
return "page:$this"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment