SwitchCompact拦截点击事件

因为项目需要,点击的时候,根据相应的条件判断,如果条件成立,滑块滚动,否则不滚动。然后网上查了一圈,没有什么好的办法,只能看源码,解决这个问题。思路是这样的,我找了一下那个check的改变位置,找到两处,一个是toggle方法,另外一个是setCheck方法。我们知道setCheck方法是我们可以自己设置,这个显示不是点击的时候,做的事,然后我就跟踪toggle方法,看谁调用了它。这个是switchcompact的toggle方法源码

 public void toggle() {
        this.setChecked(!this.isChecked());
    }

那谁调用了呢?SwitchCompact没有调用,应该是父类调用了这个方法,父类是谁呢CompoundButton,它也有toggle方法,

@Override
    public void toggle() {
        setChecked(!mChecked);
    }

发现该类的performClick方法调用,这个不是点击事件嘛?

    @Override
    public boolean performClick() {
        toggle();

        final boolean handled = super.performClick();
        if (!handled) {
            // View only makes a sound effect if the onClickListener was
            // called, so we'll need to make one here instead.
            playSoundEffect(SoundEffectConstants.CLICK);
        }

        return handled;
    }

这个谁调用了呢?经过查找在它的父类TextView里面调用,

    private boolean performAccessibilityActionClick(Bundle arguments) {
        boolean handled = false;

        if (!isEnabled()) {
            return false;
        }

        if (isClickable() || isLongClickable()) {
            // Simulate View.onTouchEvent for an ACTION_UP event
            if (isFocusable() && !isFocused()) {
                requestFocus();
            }

            performClick();
            handled = true;
        }

        // Show the IME, except when selecting in read-only text.
        if ((mMovement != null || onCheckIsTextEditor()) && hasSpannableText() && mLayout != null
                && (isTextEditable() || isTextSelectable()) && isFocused()) {
            final InputMethodManager imm = InputMethodManager.peekInstance();
            viewClicked(imm);
            if (!isTextSelectable() && mEditor.mShowSoftInputOnFocus && imm != null) {
                handled |= imm.showSoftInput(this, 0);
            }
        }

        return handled;
    }

这个是谁调用的呢?继续跟中

  @Override
    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
        if (mEditor != null
                && mEditor.mProcessTextIntentActionsHandler.performAccessibilityAction(action)) {
            return true;
        }
        switch (action) {
            case AccessibilityNodeInfo.ACTION_CLICK: {
                return performAccessibilityActionClick(arguments);
            }
            case AccessibilityNodeInfo.ACTION_COPY: {
                if (isFocused() && canCopy()) {
                    if (onTextContextMenuItem(ID_COPY)) {
                        return true;
                    }
                }
            } return false;
            case AccessibilityNodeInfo.ACTION_PASTE: {
                if (isFocused() && canPaste()) {
                    if (onTextContextMenuItem(ID_PASTE)) {
                        return true;
                    }
                }
            } return false;
            case AccessibilityNodeInfo.ACTION_CUT: {
                if (isFocused() && canCut()) {
                    if (onTextContextMenuItem(ID_CUT)) {
                        return true;
                    }
                }
            } return false;
            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
                ensureIterableTextForAccessibilitySelectable();
                CharSequence text = getIterableTextForAccessibility();
                if (text == null) {
                    return false;
                }
                final int start = (arguments != null) ? arguments.getInt(
                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
                final int end = (arguments != null) ? arguments.getInt(
                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
                if ((getSelectionStart() != start || getSelectionEnd() != end)) {
                    // No arguments clears the selection.
                    if (start == end && end == -1) {
                        Selection.removeSelection((Spannable) text);
                        return true;
                    }
                    if (start >= 0 && start <= end && end <= text.length()) {
                        Selection.setSelection((Spannable) text, start, end);
                        // Make sure selection mode is engaged.
                        if (mEditor != null) {
                            mEditor.startSelectionActionModeAsync(false);
                        }
                        return true;
                    }
                }
            } return false;
            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
                ensureIterableTextForAccessibilitySelectable();
                return super.performAccessibilityActionInternal(action, arguments);
            }
            case ACCESSIBILITY_ACTION_SHARE: {
                if (isFocused() && canShare()) {
                    if (onTextContextMenuItem(ID_SHARE)) {
                        return true;
                    }
                }
            } return false;
            case AccessibilityNodeInfo.ACTION_SET_TEXT: {
                if (!isEnabled() || (mBufferType != BufferType.EDITABLE)) {
                    return false;
                }
                CharSequence text = (arguments != null) ? arguments.getCharSequence(
                        AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE) : null;
                setText(text);
                if (mText != null) {
                    int updatedTextLength = mText.length();
                    if (updatedTextLength > 0) {
                        Selection.setSelection(mSpannable, updatedTextLength);
                    }
                }
            } return true;
            default: {
                return super.performAccessibilityActionInternal(action, arguments);
            }
        }
    }

action_click这个不是click事件嘛,知道了缘由,就好解决了,我们要在重写toggle方法就可以了,一下是代码

class CustomSwitch : SwitchCompat {

    private var action: (() -> Boolean)? = null

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    var canClick: Boolean = false

    private var lastClickTime: Long = 0


    fun setClickAction(clickAction: () -> Boolean) {
        action = clickAction
    }

    override fun toggle() {
        //两次点击间隔超过300ms才给执行performClick时间
        val currentTime = System.currentTimeMillis()
        if (Math.abs(currentTime - lastClickTime) > 300) {
            lastClickTime = currentTime
            if (action == null) {
                super.toggle()
            } else {
                action?.invoke()?.apply {
                    if (this && !canClick) {
                        canClick = true
                        super.toggle()
                    }
                }
            }
        } else {
            lastClickTime = currentTime
        }
    }


    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        action = null
    }


    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        //过滤move事件
        if (ev?.action == MotionEvent.ACTION_MOVE) return false
        return super.onTouchEvent(ev)
    }


}

对于该类可以继续扩展,比如滑动啊,我这里做的处理是禁止滑动,你也可以根据自己的情况,让它滑动。

你可能感兴趣的:(android,switchCompact,switch)