2012-04-21 20 views
8

Tôi muốn triển khai giao diện văn bản tùy chỉnh, với thao tác chạm + kéo văn bản và bàn phím không được nâng lên, trái ngược với hành vi mặc định của nhấp chuột dài menu ĐCSTQ và bàn phím. hiểu biết của tôi cho thấy tôi cần tiếp cận này:android: Cách nhận vị trí văn bản từ sự kiện chạm

onTouchEvent(event){ 
    case touch_down: 
    get START text position 

    case drag 
    get END text position 
    set selection range from START to END 
} 

Tôi đã phát hiện ra tất cả về getSelectStart() và các phương pháp khác nhau để thiết lập một phạm vi và như vậy, nhưng tôi không thể tìm thấy làm thế nào để có được vị trí văn bản dựa trên một sự kiện liên lạc getX() và getY(). Có cách nào để làm điều này không? Tôi đã nhìn thấy hành vi tôi muốn trong các ứng dụng văn phòng khác.

Ngoài ra, làm cách nào để dừng bàn phím xuất hiện cho đến khi được yêu cầu theo cách thủ công?

Trả lời

12

"mText.setInputType (InputType.TYPE_NULL)" sẽ tắt bàn phím mềm nhưng cũng tắt con trỏ nhấp nháy trong hộp EditText trong Android 3.0 trở lên. Tôi mã hóa một onTouchListener và trả về true để vô hiệu hóa bàn phím và sau đó đã có được vị trí cảm ứng từ sự kiện chuyển động để thiết lập con trỏ đến vị trí chính xác. Bạn có thể sử dụng tính năng này trên sự kiện chuyển động ACTION_MOVE để chọn văn bản để kéo.

Đây là mã tôi đã sử dụng:

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

tôi có Null Pointer Ngoại lệ trên dòng ::: "int offset = layout.getOffsetForHorizontal (0, x);" –

10

Cảm ơn Waine Kail cho việc chia sẻ mã bắt đầu, nhưng nó chỉ xử lý "x" trục của sự kiện. Đối với multiline EditText, bạn cũng phải:

1- Tính vị trí thẳng đứng (y):
2- Lấy dòng bù đắp bởi vị trí dọc
3 Lấy văn bản bù đắp bằng cách sử dụng dòng và vị trí nằm ngang

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

Cảm ơn điều này giúp tôi ... :) – ADT

+0

Tôi m nhận được con trỏ Null Ngoại lệ cho bố cục, tại sao? tôi không biết. – Dharmishtha

+0

để bố cục tôi đã làm một cái gì đó như thế này. ViewTreeObserver vto = edittext.getViewTreeObserver(); vto.addOnGlobalLayoutListener (ViewTreeObserver.OnGlobalLayoutListener mới() {@Override public void onGlobalLayout() { layout = edittext.getLayout();} }); – Dharmishtha

2

Đối với ứng dụng của tôi, tôi cần thiết để có được vị trí trong danh sách liên lạc nhưng giải pháp trên dường như không đưa ra vị trí chính xác. Đối với tôi nó thường xuyên hơn không được giảm 1-2 ký tự liên quan đến con trỏ văn bản. Mã dưới đây giải quyết vấn đề này. Chìa khóa để làm việc này là sử dụng post() để hoãn mã cho đến sau khi vị trí con trỏ được cập nhật. Do đó, vị trí tôi nhận được được đảm bảo đồng ý với EditText và mã cũng đơn giản hơn.

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

Tôi cũng đang gặp vấn đề tương tự. Và khi tôi cố gắng sử dụng "int offset = layout.getOffsetForHorizontal (0, x);" như Wayne Kail cho biết, cũng có NPE trong dòng này. Vì vậy, tôi đã cố gắng và cuối cùng viết như thế này:

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

không làm việc cho tôi. – Dharmishtha

Các vấn đề liên quan