2012-04-21 122 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