因为项目需要,点击的时候,根据相应的条件判断,如果条件成立,滑块滚动,否则不滚动。然后网上查了一圈,没有什么好的办法,只能看源码,解决这个问题。思路是这样的,我找了一下那个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)
}
}
对于该类可以继续扩展,比如滑动啊,我这里做的处理是禁止滑动,你也可以根据自己的情况,让它滑动。