Reputation: 6629
I want my fragment to not receive any clicks on the views while the fragment transition animation is not yet finished. It is just a simple fade. But things get wonky when I immediately press any view while the next fragment is fading in.
Any thoughts how to achieve this?
Upvotes: 3
Views: 2052
Reputation: 8211
This is actually used in my own app. The idea is very simple, it just works, but needs quite a lot of additional coding.
The idea is very simple, use a boolean variable to maintain whether the screen should be locked, let's call it screenLocked
. I do not actually block the click, but let the click do nothing.
For those actions which takes time, set screenLocked
to true before start working, and set it back to false when the task is finished. Also you have to add checking on screenLocked
before any action is done.
Another difficulty of the this method is that you need to have clear end point of your tasks. Using Fragment transition as an example, if the backstack is poped, there has no actual callback notifying you, for this case. To handle this, I would set another flag releaseOnResume
before starting Fragment transition, and in onResume
, I would use this flag to check if I should set screenLocked
back to false.
Other solutions I have tried but not used:
Before I settled with the method I just mentioned, I have tried setEnabled
, setClickable
, or any UI based blocking, e.g. add a FrameLayout on top and capture all touch events.
These methods are not bad, especially given that they are easy to implement.
The only problem is that, onClick
events can be queued due to double tapping, when you are handling the first onClick
event, actually there could be another one queued up, even if you do any UI changes immediately to block any further clicks, you can't stop the next onClick
event to come because it is queued already.
Hope this helps.
Upvotes: 2
Reputation: 6629
In the end I used something like this. I created a parent class for all my fragments and overriden the OnCreateAnimation
method which is called on every animation.
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
//Check if the superclass already created the animation
Animation anim = super.onCreateAnimation(transit, enter, nextAnim);
//If not, and an animation is defined, load it now
if (anim == null && nextAnim != 0) {
anim = AnimationUtils.loadAnimation(getActivity(), nextAnim);
}
//If there is an animation for this fragment, add a listener.
if (anim != null) {
anim.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
isAnimationFinished = false;
}
@Override
public void onAnimationEnd(Animation animation) {
isAnimationFinished = true;
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
return anim;
}
The isAnimationFinished
variable is a public variable that can be used by the calling activity and the child classes
Upvotes: 1
Reputation:
I use a countdown timer. I manage this through the ontouch listener.
I create a method that manages the creation of the timer. I call it in the ontouch event. I use two methods (this is optional, but good for extensibility) to handle button enabling and disabling. I then use these methods with the timer to enable and disable the button.
See my code snippet.
In oncreate:
@Override protected void onCreate(Bundle savedInstanceState) {
/.../
button.setOnTouchListener(new View.OnTouchListener() {
@Override public boolean onTouch(View v, MotionEvent event) {
disableButton(button);
countDwn1();
/... time to do whatever you need..
// custom methods...
fragment = new MyFragAddFragment();
replaceFragment(fragment);
return false;
}
});
Methods:
public void countDwn1() {
CountDownTimer countDownTimer = new CountDownTimer(2000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
enableButton(button);
}
}.start();
}
public void disableButton(Button button) {
button.setEnabled(false);
}
public void enableButton(Button button) {
button.setEnabled(true);
}
You can extend this method to include passing the button as a parameter into the timer, for extensibility.
Upvotes: 1