开发者

View switches: how to block user interaction in-between?

I use a view switcher to switch between views in a way that is similar to standard activities switching in a task. For example, the current view in the switcher might have a button that, when clicked, initiates the view switch: the current view, which is now obsolete, slides out, and is replaced by the new current view, which slides in.

The animated switch is fine only for one thing: I cannot find a correct way to tell the sliding out view to stop processing user events, like touch events. 开发者_JAVA技巧So what happens is, if done fast enough, and it doesn't have to be that fast, the user can click on the button that initiates the view switch more than once, which is bad. Once a click (or any user action) has initiated a view switch, I would like to invalidate and ignore all other user events on the sliding out view.

Is there a clean, standard way to do so? I've tried setEnabled(false) on the sliding out view, but it seems click listeners in child views are still handled afterward. The thing I want to avoid is looking for all event handlers and adding verification code that ensures that nothing is done if the view is actually sliding out.


I had a similar problem and want to share my solution. I override the Activity.dispatchTouchEvent method as noted here. In doing so I intercept all touch events before they are dispatched to the other views.

public boolean mDisplayBlocked = false;

@Override
public boolean dispatchTouchEvent(MotionEvent pEvent) {
    if (!mDisplayBlocked) {
        return super.dispatchTouchEvent(pEvent);
    }
    return mDisplayBlocked;
}


In your click listener, before you initiate a view switch, I believe you should be able to disable the listener.

I imagine other UI interactions will still be possible though. Perhaps you need a masterDisable method, which will disable all UI interactions on that View, which you can call before you make the view switch.


There is no method to tell a parent to disable all of it children's events. And also, calling setEnabled(false) on a parent does not disable it's children.

Probably the easiest way to do this is to call setEnabled(false) on the button.


May be, If you set the visibility to GONE for the child controls of the fading out view, you can check the same in the listener and handle events only for the visible views.


Well, it was painful, but I think I finally found the right way to achieve what I wanted, and you really have to find out how the Android API wants you to do it. So here is how I manage the child view that is sliding out:

childView.startAnimation(animation);
parentView.removeView(childView); // makes childView a "disappearing child" of parentView

That may seems strange, but when you do that, childView is still drawn in its parent, even though it is not "physically" there anymore (it doesn't receive user inputs anymore, which is the behavior I was after in the first place). Hence, childView becomes a "disappearing child" of parentView, a very special case implemented in ViewGroup. And when the animation ends (through AnimationListener), you must do:

parentView.clearDisappearingChildren();

otherwise parentView will still draw the pixels of not-animated-anymore childView.

Note that the first thing I tried was:

childView.startAnimation(animation);

And when the animation ended:

parentView.removeView(childView);

Even though that way of doing seemed natural to me, all hell started to break loose! I started getting NullPointerException deep in ViewGroup.dispatchDraw. All of this because AnimationListener.onAnimationEnd was called during the execution of ViewGroup.dispatchDraw, and changing the list of child views is a very bad idea at that point...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜