一、代码实现
同时屏蔽双击选中 和 长按选中:
mEditText.setMovementMethod(new BaseMovementMethod());
只屏蔽长按选中:
<EditText
android:longClickable="false"
/>
二、分析、实现过程
双击或长按都是 Touch事件,所以先看EditText的onTouchEvent
方法,EditText中 没有 onTouchEvent方法,而 class EditText extends TextView
,所以查看TextView 的 onTouchEvent 方法。
// TextView.java
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getActionMasked();
if (mEditor != null) {
mEditor.onTouchEvent(event);
......
}
// Editor.java
void onTouchEvent(MotionEvent event) {
final boolean filterOutEvent = shouldFilterOutTouchEvent(event);
mLastButtonState = event.getButtonState();
if (filterOutEvent) {
if (event.getActionMasked() == MotionEvent.ACTION_UP) {
mDiscardNextActionUp = true;
}
return;
}
updateTapState(event);
updateFloatingToolbarVisibility(event);
// 重点:如果有SelectionController就使用它来处理 event
if (hasSelectionController()) {
getSelectionController().onTouchEvent(event);
}
class SelectionModifierCursorController implements CursorController {
public void onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_UP:
updateSelection(event);
updateSelection() --> updateSelectionInternal() --> Selection.setSelection((Spannable) mTextView.getText(), selectionStart, selectionEnd);
回到 Editor.java 中,
if (hasSelectionController()) {
getSelectionController().onTouchEvent(event);
}
getSelectionController().onTouchEvent(event);
中处理了选中的相关逻辑,也就是不走这行代码,就不会执行选中操作,只要想办法让 hasSelectionController()
返回 false 即可。
// Editor.java
boolean hasSelectionController() {
return mSelectionControllerEnabled;
}
void prepareCursorControllers() {
mSelectionControllerEnabled = enabled && mTextView.textCanBeSelected();
enable肯定为true,那只有将mTextView.textCanBeSelected() == false
// TextView.java
boolean textCanBeSelected() {
if (mMovement == null || !mMovement.canSelectArbitrarily()) return false;
return isTextEditable()
|| (isTextSelectable() && mText instanceof Spannable && isEnabled());
}
return 语句中,isTextEditable()
肯定为true,如果走到了return这句就肯定不行了。
所以只有让程序走到这里去if (mMovement == null || !mMovement.canSelectArbitrarily()) return false;
就ok了
看一下 MovementMethod 接口:
public interface MovementMethod {
/**
* Returns true if this movement method allows arbitrary selection
* of any text; false if it has no selection (like a movement method
* that only scrolls) or a constrained selection (for example
* limited to links. The "Select All" menu item is disabled
* if arbitrary selection is not allowed.
*/
public boolean canSelectArbitrarily();
}
意思就是,是否允许任意选择文本。
// EditText.java
@Override
protected MovementMethod getDefaultMovementMethod() {
return ArrowKeyMovementMethod.getInstance();
}
EditText的默认实现是 ArrowKeyMovementMethod 这玩意:
public class ArrowKeyMovementMethod extends BaseMovementMethod implements MovementMethod {
@Override
public boolean canSelectArbitrarily() {
return true;
}
那只要让canSelectArbitrarily()
返回false即可,查看MovementMethod
的实现类后,我们可以使用
public class BaseMovementMethod implements MovementMethod {
@Override
public boolean canSelectArbitrarily() {
return false;
}
进行替代。
最终,使用 mEditText.setMovementMethod(new BaseMovementMethod());
解决问题。
实际验证,效果也是OK的,既不能长按也不能双击选择文本。