2012-04-21 52 views
8

我想要实现一个自定义文本界面,通过触摸+拖动选择文本和键盘不被触发,与长按提示的默认行为CCP菜单和键盘。我的理解暗示我需要这样的方法:android:如何从触摸事件中获取文本位置

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()。有没有办法做到这一点?我在其他办公应用程序中看到了我想要的行为。

此外,我会如何停止键盘出现,直到手动要求?

回答

12

“mText.setInputType(InputType.TYPE_NULL)”将压制软键盘,但它也会禁用Android 3.0及更高版本下的EditText框中的闪烁光标。我编写了一个onTouchListener,并返回true以禁用键盘,然后必须从运动事件中获取触摸位置,以将光标设置到正确的位置。您可以在ACTION_MOVE动作事件中使用此选项来选择要拖动的文本。

这里是我使用的代码:

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); 
+2

我得到了空指针异常行:::“int offset = layout.getOffsetForHorizo​​ntal(0,x);” – 2014-07-31 05:44:38

10

感谢韦恩凯尔分享起始码,但只处理该事件的“X”轴。为的EditText,还必须:

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; 
} 
}); 
+0

感谢这帮助我...... :) – ADT 2014-02-15 07:50:31

+0

我得到空指针异常的布局,为什么?我不知道。 – Dharmishtha 2017-04-26 09:33:54

+0

布局我做了这样的事情。 ViewTreeObserver vto = edittext.getViewTreeObserver(); vto.addOnGlobalLayoutListener(新ViewTreeObserver.OnGlobalLayoutListener(){ @Override 公共无效onGlobalLayout(){ 布局= edittext.getLayout();} }); – Dharmishtha 2017-05-01 07:14:53

2

对于我的应用程序需要得到一个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; 
     } 
    }); 
4

我也面临同样的问题。当我尝试使用“int offset = layout.getOffsetForHorizo​​ntal(0,x);”就像Wayne Kail所说的,在这条线上也得到了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); 
+0

不适合我。 – Dharmishtha 2017-04-26 09:32:40