Fragment Transition leads to crash

avatar
183    4 months ago

I change fragments with an animation by swiping the screen to the right or left. Here is the parent fragment:

class StatsFragment: Fragment() {

    private lateinit var tvSortCategories: TextView
    private lateinit var tvSortMonths: TextView
    private var x: Float? = null
    private val fragmentStatsCat = StatsCategoryFragment()
    private val fragmentStatsMon = StatsMonthFragment()


    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        val view: View = inflater.inflate(R.layout.fragment_stats, container, false)
        tvSortCategories = view.findViewById(R.id.tvStatsCategories)
        tvSortMonths = view.findViewById(R.id.tvStatsMonths)
        tvSortCategories.isSelected = true
        tvSortCategories.setOnClickListener {
            inflateCategory()
        }
        tvSortMonths.setOnClickListener {
            inflateMonth()
        }
        childFragmentManager.beginTransaction()
        .replace(R.id.stats_container, fragmentStatsCat)
        .commit()

        view.setOnTouchListener {_, event ->

            when(event.action) {
                MotionEvent.ACTION_DOWN -> {
                    x = event.x
                }
                MotionEvent.ACTION_MOVE -> {
                    if(x != null) {
                        val dx = event.x - x!!
                        if(dx > 200f) {
                            inflateCategory()
                            x = event.x
                        }
                        if (dx < -200f) {
                            inflateMonth()
                            x = event.x
                        }
                    }
                }
            }

            true
        }

        return view
    }

    private fun inflateCategory() {
        tvSortCategories.isSelected = true
        tvSortMonths.isSelected = false

        childFragmentManager.beginTransaction()
        .setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right)
        .replace(R.id.stats_container, fragmentStatsCat)
        .commit()
    }

    private fun inflateMonth() {
        tvSortCategories.isSelected = false
        tvSortMonths.isSelected = true

        childFragmentManager.beginTransaction()
        .setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)
        .replace(R.id.stats_container, fragmentStatsMon)
        .commit()
    }
}

This works fine, but with one exception. When I perform a fragmentTransaction, while the old fragmentTransaction has not finished, it crashes with a ´java.lang.IllegalStateException´: ´Restarter must be created only during owner's initialization stage´

Is there a way I can check if the old transaction has finished before performing a new one?

EDIT: To further explain what exactly I want to do:

Child Fragment 1

Child Fragment 2

I want to change between those two Child Fragments by either swiping over the creen to the other fragment or by touching on ´Sort by Categories/Months´.

Answers { 1 }
avatar
4 months ago

you cannot run a fragment transaction while another one is still ongoing. Base on what your code is doing, there will be multiple trigger as the user swipe on your view. This will trigger multiple fragment transaction in rapid succession and thats whats causing your crash.

In your usecase, you simple want to change between two fragment through swiping. There is actually a widget for that.

It is called ViewPager.

See some guide at the official android documentation site here.

You could also use, TabLayout with ViewPager to make exactly what your screenshot above is.