我目前正在处理多行编辑文本,该文本可能在其文本中包含占位符。为了绕过这些占位符的修改,我在EditText小部件中添加了一个onClickListener,用于检查光标位置是否在这样的占位符中。在这种情况下,应选择占位符,以防止任何修改,除非完全删除它。
这在我的Android 2.3设备上完全正常,但在Android 4.x上,选择在onClick事件后被修改,光标显示在占位符的开头而没有选择。
onClickListener的源代码。
protected void textClickListener(EditText v) {
Pattern p = Pattern.compile(placeholderRegex);
Matcher matcher = p.matcher(v.getText());
int sel_start = v.getSelectionStart();
int sel_end = v.getSelectionEnd();
if (sel_start == -1) {
return;
}
while (matcher.find()) {
int pattern_start = matcher.start();
int pattern_end = pattern_start + 25;
if (pattern_start > sel_end) {
continue;
}
if (pattern_end < sel_start) {
continue;
}
v.setSelection(Math.min(sel_start, pattern_start), Math.max(sel_end, pattern_end));
return;
}
}
此代码工作正常,使用正确的值调用setSelection,并且实际设置了选择。我在Selection.setSelection方法上设置了一个断点,发现它是从PositionListener调用的,它是android.widget.editor的内部类,它将选择长度设置为0.以下是此setSelection调用的堆栈跟踪:
Selection.setSelection(Spannable, int) line: 87
Editor$InsertionHandleView.updateSelection(int) line: 3271
Editor$InsertionHandleView(Editor$HandleView).positionAtCursorOffset(int, boolean) line: 3045
Editor$InsertionHandleView(Editor$HandleView).updatePosition(int, int, boolean, boolean) line: 3064
Editor$PositionListener.onPreDraw() line: 2047
ViewTreeObserver.dispatchOnPreDraw() line: 671
ViewRootImpl.performTraversals() line: 1820
ViewRootImpl.doTraversal() line: 1000
ViewRootImpl$TraversalRunnable.run() line: 4214
Choreographer$CallbackRecord.run(long) line: 725
Choreographer.doCallbacks(int, long) line: 555
Choreographer.doFrame(long, int) line: 525
Choreographer$FrameDisplayEventReceiver.run() line: 711
Handler.handleCallback(Message) line: 615
Choreographer$FrameHandler(Handler).dispatchMessage(Message) line: 92
Looper.loop() line: 137
ActivityThread.main(String[]) line: 4745
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 511
ZygoteInit$MethodAndArgsCaller.run() line: 786
ZygoteInit.main(String[]) line: 553
NativeStart.main(String[]) line: not available [native method]
如何防止此操作或如何在此PositionListener操作后设置选择?
答案 0 :(得分:1)
从问题迁移
最后我发现,您必须在OnTouchListener
中修改选择。为了使其更加复杂,您必须在该侦听器的两次调用中修改选择(ACTION_DOWN
,ACTION_UP
)。如果你只做一次(因为我出于性能原因),它也不会工作。所以最终工作的代码是:
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
protected boolean textTouchListener(EditText v, MotionEvent event) {
placeholder_selected = false;
Pattern p = Pattern.compile(placeHolderRegex);
Matcher matcher = p.matcher(v.getText());
int click_position = v.getOffsetForPosition(event.getX(), event.getY());
int sel_start = click_position;
int sel_end = click_position;
if (sel_start == -1) {
return false;
}
while (matcher.find()) {
int pattern_start = matcher.start();
int pattern_end = pattern_start + 25;
if (pattern_start > sel_end) {
continue;
}
if (pattern_end < sel_start) {
continue;
}
v.setSelection(Math.min(sel_start, pattern_start), Math.max(sel_end, pattern_end));
placeholder_selected = true;
return true;
}
return false;
}
出于兼容性原因,仍然需要OnClickListener
,因为方法getOffsetForPosition
不适用于低于11的API级别(Honeycomb)。根据使用的API,只需要执行两个侦听器中的一个。