2012-04-21 11 views
8

Chcę zaimplementować niestandardowy interfejs tekstowy, dotknięcie + przeciągnięcie zaznaczenia tekstu i podniesienie klawiatury, w przeciwieństwie do domyślnego zachowania podczas długiego kliknięcia menu CCP i klawiatura. Moje zrozumienie sugeruje, muszę to podejście:android: Jak uzyskać pozycję tekstową z wydarzenia dotykowego

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

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

ja dowiedziałem się o getSelectStart() i różne metody ustalania zakresu i takie, ale nie mogę znaleźć sposobu, aby uzyskać pozycję tekstu na podstawie dotykowym imprezy getX() i getY(). Czy jest jakiś sposób to zrobić? Widziałem zachowanie, które chcę w innych aplikacjach biurowych.

Co zrobić, aby zatrzymać wyświetlanie klawiatury, dopóki nie zostanie ręcznie zażądana?

Odpowiedz

12

"mText.setInputType (InputType.TYPE_NULL)" wytłumi miękką klawiaturę, ale także dezaktywuje migający kursor w polu EditText w systemie Android 3.0 lub nowszym. Zakodowałem moduł onTouchListener i przywróciłem wartość true, aby wyłączyć klawiaturę, a następnie musiałem uzyskać pozycję dotykową od zdarzenia ruchu, aby ustawić kursor we właściwym miejscu. Możesz użyć tego zdarzenia ACTION_MOVE, aby wybrać tekst do przeciągnięcia.

Oto kod użyłem:

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

mam Null Pointer Exception na linii ::: "int offset = layout.getOffsetForHorizontal (0, x);" –

10

Dzięki Waine Kail za udostępnienie kodu startowego, ale tylko obsługiwane osi „X” imprezy. Dla wielowierszowego EditText, należy również:

1- obliczenie pozycji pionowej (y):
2- uzyskania linii przesunięcia z położenia pionowego
3- uzyskać tekst przesunięciem za pomocą linii i położenia poziomego

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

Dzięki temu pomóżcie mi ... :) – ADT

+0

Otrzymuję zerowy wskaźnik Wyjątek dla układu, dlaczego? Nie wiem. – Dharmishtha

+0

dla układu Zrobiłem coś takiego. ViewTreeObserver vto = edittext.getViewTreeObserver(); vto.addOnGlobalLayoutListener (nowa ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { layout = edittext.getLayout();} }); – Dharmishtha

2

Do mojej aplikacji potrzebowałem uzyskać pozycję w touchlistener, ale powyższe rozwiązanie wydaje się nie podać dokładnej lokalizacji. Dla mnie częściej niż nie było wyłączone przez 1-2 znaki w stosunku do kursora tekstowego. Poniższy kod rozwiązuje to. Kluczem do uruchomienia tej funkcji jest użycie post(), aby odłożyć kod, dopóki pozycja kursora nie zostanie zaktualizowana. W ten sposób otrzymana pozycja jest zgodna z pozycją EditText, a kod jest również prostszy.

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

Mam do czynienia z tym samym problemem. I kiedy próbowałem użyć "int offset = layout.getOffsetForHorizontal (0, x);" jak powiedział Wayne Kail, również ma NPE w tej linii. Więc próbowałem iw końcu napisać tak:

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

nie działa dla mnie. – Dharmishtha