android:如何从触摸事件中获取文本位置
我想实现一个定制的文本界面,通过触摸+拖动选择文本,并且键盘不会弹出,这与长时间点击打开CCP菜单和键盘的默认行为形成对比。我的理解表明我需要这种方法:android:如何从触摸事件中获取文本位置,android,android-edittext,selection,Android,Android Edittext,Selection,我想实现一个定制的文本界面,通过触摸+拖动选择文本,并且键盘不会弹出,这与长时间点击打开CCP菜单和键盘的默认行为形成对比。我的理解表明我需要这种方法: onTouchEvent(event){ case touch_down: get START text position case drag get END text position set selection range from START to END } 我已经了解了所有关于getSelectSt
onTouchEvent(event){
case touch_down:
get START text position
case drag
get END text position
set selection range from START to END
}
我已经了解了所有关于getSelectStart()和设置范围等的各种方法,但是我找不到如何基于触摸事件getX()和getY()获取文本位置。有没有办法做到这一点?我在其他office应用程序中看到了我想要的行为
另外,在手动请求之前,如何停止键盘显示?“mText.setInputType(InputType.TYPE_NULL)”将抑制软键盘,但它也会禁用Android 3.0及更高版本下编辑文本框中的闪烁光标。我编写了一个onTouchListener并返回true以禁用键盘,然后必须从运动事件中获取触摸位置,以将光标设置到正确的位置。您可以在“动作”\u“移动”事件中使用此选项来选择要拖动的文本
以下是我使用的代码:
mText = (EditText) findViewById(R.id.editText1);
OnTouchListener otl = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Layout layout = ((EditText) v).getLayout();
float x = event.getX() + mText.getScrollX();
int offset = layout.getOffsetForHorizontal(0, x);
if(offset>0)
if(x>layout.getLineMax(0))
mText.setSelection(offset); // touch was at end of text
else
mText.setSelection(offset - 1);
break;
}
return true;
}
};
mText.setOnTouchListener(otl);
感谢Waine Kail分享开始代码,但它只处理事件的“x”轴。对于多行编辑文本,您还必须: 1-计算垂直位置(y):
2-获得垂直位置的线偏移量
3-使用直线和水平位置获取文本偏移
EditText et = (EditText) findViewById(R.id.editText1);
long offset = -1; //text position will be corrected when touching.
et.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
Layout layout = ((EditText) v).getLayout();
float x = event.getX() + et.getScrollX();
float y = event.getY() + et.getScrollY();
int line = layout.getLineForVertical((int) y);
// Here is what you wanted:
offset = layout.getOffsetForHorizontal( line, x);
break;
}
return false;
}
});
对于我的应用程序,我需要获得touchlistener中的位置,但上面的解决方案似乎没有给出精确的位置。对我来说,相对于文本光标,它通常被关闭1-2个字符。下面的代码解决了这个问题。实现这一点的关键是使用post()将代码延迟到光标位置更新之后。因此,我得到的位置保证与EditText一致,代码也更简单
setOnTouchListener(new OnTouchListener()
{
@Override
public boolean onTouch(View view, MotionEvent event)
{
if(event.getAction()==MotionEvent.ACTION_UP)
{
//At this point the selection has not been updated. So post an
//event at the end of the event queue to check where cursor
//has been moved
post(new Runnable()
{
public void run()
{
Editable sb=getText();
int currentPos=getSelectionStart();
//TODO
}
});
}
return false;
}
});
我也面临同样的问题。当我尝试使用“int offset=layout.getOffsetForHorizontal(0,x);”时,就像前面所说的,这一行也得到了NPE。所以我试着最后写下这样的话:
mText = (EditText) findViewById(R.id.editText1);
OnTouchListener otl = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
EditText editText = (EditText) v;
float x = event.getX();
float y = event.getY();
int touchPosition = editText.getOffsetForPosition(x, y);
if (touchPosition>0){
editText.setSelection(touchPosition);
}
return true;
}
};
mText.setOnTouchListener(otl);
在EditText中,中的onTouch事件被调用两次:for ACTION\u DOWN和ACTION\u UP。这就是getLayout导致null的原因。我将在这里发布代码,需要验证和处理
@Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouch(View view, MotionEvent motionEvent) {
final EditText editText = (EditText) view;
final int editTextSelectionStart = editText.getSelectionStart();
final int editTextSelectionEnd = editText.getSelectionEnd();
final Layout layout = editText.getLayout();
final int inType = editText.getInputType(); // Backup the input type.
editText.setInputType(InputType.TYPE_NULL); // Disable standard keyboard.
editText.onTouchEvent(motionEvent); // Call native handler.
editText.setInputType(inType);// Restore input type.
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
float x = motionEvent.getX() + editText.getScrollX();
if (layout != null) {
int offset = layout.getOffsetForHorizontal(0, x);
if (offset > 0) {
if (x > layout.getLineMax(0)) {
editText.setSelection(offset);
} else {
editText.setSelection(offset - 1);
}
}
}
break;
case MotionEvent.ACTION_UP:
editText.setSelection(editTextSelectionStart, editTextSelectionEnd);
break;
}
return true; // Consume touch event.
}
谢谢这个帮助我…:)我得到布局的空指针异常,为什么?我不知道。对于布局,我做过类似的事情。ViewTreeObserver vto=edittext.getViewTreeObserver();vto.addOnGlobalLayoutListener(新ViewTreeObserver.OnGlobalLayoutListener(){@Override public void onGlobalLayout(){layout=edittext.getLayout();}});第行出现空指针异常:“int offset=layout.getOffsetForHorizontal(0,x);”