Skip to content Skip to sidebar Skip to footer

Prevent Views From Being Clicked Until Animation Added To Action Via Navigation Component Completes

Given 2 Fragments A and B, A moves to B (so A -> B), via navigation component action with enter animation has been added. How to prevent views in Fragment B being clickable whil

Solution 1:

You can start by having your views as disabled in xml android:enabled="false" then in your fragment's onViewCreated you can set a delay with the animation duration using coroutines:

overridefunonViewCreated(view: View, savedState: Bundle?) {
    super.onViewCreated(view, savedState)

    // Initialize views here. 


    lifecycleScope.launch {
        delay(resources.getInteger(R.integer.anim_duration).toLong())
        // Enable views here
        myView.isEnabled = true
    }
}

Solution 2:

While I originally solved the problem using coroutines I faced the same problem once again :] so I investigated a bit and stumbled upon this topic Disable clicks when fragment adding animation playing that helped me to figure out the right solution.

Apparently those action animations added through the navigation graph are set by FragmentTransaction.setCustomAnimation(enter, exit, popEnter, popExit) and these can be accessed by overriding onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int). Where nextAnim actually represents the action animations we added. For the fragment A it would be either exit or popEnter and for the fragment B it would be either enter or popExit.

The problem of views being clicked happens when fragment is entering (either enter or popEnter) so one can use an if statement to check enter and if true create Animation based on the nextAnim and then one can set listener to it. In case of home (starting) fragment one should exclude the case of nextAnim = 0 since it's also entering animation.

overridefunonCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
        if (nextAnim == 0 || !enter) returnsuper.onCreateAnimation(transit, enter, nextAnim)
        else {
            return AnimationUtils.loadAnimation(requireContext(), nextAnim).apply {
                setAnimationListener(object : Animation.AnimationListener {
                    overridefunonAnimationStart(animation: Animation?) {
                        disableClicking()
                    }

                    overridefunonAnimationEnd(animation: Animation?) {
                        enableClicking()
                    }

                    overridefunonAnimationRepeat(animation: Animation?) {
                    }
                })
            }
        }
    }

EDIT: For non-home fragments to avoid disabling clicks at the start of the animation, we can start with views being unclickable in xml layout and only enable clicking when the animation ends. To remove a bug where views remain unclickable if a device rotation happens we can introduce a boolean variable that we will set to true when animation ends and preserve it by overriding onSaveInstanceState(outState: Bundle) and reinstating it in onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) and check if it was true before device rotation to re-enable clicking once again.

Post a Comment for "Prevent Views From Being Clicked Until Animation Added To Action Via Navigation Component Completes"