Android的clickable与事件分发关系详解

Posted 怪兽N

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android的clickable与事件分发关系详解相关的知识,希望对你有一定的参考价值。

android的clickable与事件分发关系详解

简介

Android里的View都可以通过clickable设置是否可以点击,对于点击及Android事件分发及处理理解有非常重要的作用。长话短说,开始吧。

设置影响

clickable是用于设置是否允许view的点击事件的配置标识,如果clickable=true那么"pressed"状态会被触发。如果需要显示点击效果,那么要设置clickable=true。这就是为什么像对TextView或LinearLayout等等这些View设置水纹点击效果时,需要添加clickable=true的原因。

/**
 * Enables or disables click events for this view. When a view
 * is clickable it will change its state to "pressed" on every click.
 * Subclasses should set the view clickable to visually react to
 * user's clicks.
 *
 * @param clickable true to make the view clickable, false otherwise
 *
 * @see #isClickable()
 * @attr ref android.R.styleable#View_clickable
 */
public void setClickable(boolean clickable) {
    setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
}

当然我们也可以看到setOnClickListener也会将setClickable(true)

public void setOnClickListener(@Nullable OnClickListener l) {
    if (!isClickable()) {
        setClickable(true);
    }
    getListenerInfo().mOnClickListener = l;
}

设置Clickable与onTouchEvent(MotionEvent event)的关系

首先要也要留意下Enabled,设置View是否可用,注意可不可用都是可见的,比如Button设置不可用时Button是点击不了了,但是还是可见的呢。

/**
 * Set the enabled state of this view. The interpretation of the enabled
 * state varies by subclass.
 *
 * @param enabled True if this view is enabled, false otherwise.
 */
@RemotableViewMethod
public void setEnabled(boolean enabled) {
	.....
}

下面看看onTouchEvent是怎么处理点击事件

    public boolean onTouchEvent(MotionEvent event) {
        final float x = event.getX();
        final float y = event.getY();
        final int viewFlags = mViewFlags;
        final int action = event.getAction();

        //是否可以点击的判断 包括点击 长按
        final boolean clickable = ((viewFlags & CLICKABLE) == CLICKABLE
                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;

        if ((viewFlags & ENABLED_MASK) == DISABLED) {
            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
                setPressed(false);
            }
            mPrivateFlags3 &= ~PFLAG3_FINGER_DOWN;
            // A disabled view that is clickable still consumes the touch
            // events, it just doesn't respond to them.
            //不可用还是根据clickable确定是否会处理触摸事件
            return clickable;
        }
        if (mTouchDelegate != null) {
            if (mTouchDelegate.onTouchEvent(event)) {
                return true;
            }
        }

        //是否可点击或设置了提示文本, 如果符合这两个条件,最后一定返回true,则会处理处理事件
        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                	.....
                    break;

                case MotionEvent.ACTION_DOWN:
					....
                    break;

                case MotionEvent.ACTION_CANCEL:
					.....
                    break;

                case MotionEvent.ACTION_MOVE:
					.....
                    break;
            }
            
            return true;
        }
		//默认返回false
        return false;
    }

通过分析onTouchEvent(MotionEvent event)可以得到下面几点信息:

1 可以通过setClickable或者setOnClickableListener使View是否可以点击

2 要显示点击效果,那么要clickable=true

3 enable=false,clickable也生效

4 clickable=true那么会在onTouchEvent返回True,那么点击事件将被消费

总结

clickable的设置影响onTouchEvent的返回值,及press状态,对事件分发的处理有重大的影响。

以上是关于Android的clickable与事件分发关系详解的主要内容,如果未能解决你的问题,请参考以下文章

Android事件分发总结

Android面试View的事件分发

Android 编程下 Touch 事件的分发和消费机制

android中touch事件的分发机制

android中touch事件的分发机制

Android 编程下 Touch 事件的分发和消费机制