2012-04-21 14 views
8

Sto implementando un'interfaccia di testo personalizzata, con il tocco + trascinamento selezionando il testo e la tastiera non sollevata, in contrasto con il comportamento predefinito di un clic prolungato il menu CCP e la tastiera. La mia comprensione suggerisce Ho bisogno di questo approccio:android: Come ottenere la posizione del testo dall'evento touch

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

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

ho trovato tutto su getSelectStart() e vari metodi per impostare un intervallo e quali, ma non riesco a trovare il modo di ottenere la posizione del testo sulla base di un evento di tocco getX() e getY(). C'è un modo per fare questo? Ho visto il comportamento che voglio in altre app per ufficio.

Inoltre, come dovrei interrompere la visualizzazione della tastiera fino alla richiesta manuale?

risposta

12

"mText.setInputType (InputType.TYPE_NULL)" sopprimerà la tastiera software ma disabiliterà anche il cursore lampeggiante in una casella EditText in Android 3.0 e versioni successive. Ho codificato un onTouchListener e restituito true per disabilitare la tastiera e quindi ho dovuto ottenere la posizione di tocco dall'evento di movimento per impostare il cursore sul punto corretto. Potresti essere in grado di usarlo in un evento di movimento ACTION_MOVE per selezionare il testo da trascinare.

Ecco il codice che ho usato:

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

ho avuto Null Pointer Exception on line ::: "Int offset = layout.getOffsetForHorizontal (0, x);" –

10

Grazie Waine Kail per la condivisione del codice di avvio, ma trattate solo l'asse "x" della manifestazione. Per multilinea EditText, è inoltre necessario:

1- Calcolare la posizione verticale (y):
2- Prendi il compensato dalla posizione verticale
3- ottenere il testo linea di offset utilizzando la linea e la posizione orizzontale

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

Grazie a questo aiuto ... :) – ADT

+0

Ricevo puntatore Null Eccezione per il layout, perché? Non lo so. – Dharmishtha

+0

per il layout avevo fatto qualcosa del genere. ViewTreeObserver vto = edittext.getViewTreeObserver(); vto.addOnGlobalLayoutListener (nuova ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { layout = edittext.getLayout();} }); – Dharmishtha

2

per la mia domanda ho bisogno per ottenere la posizione all'interno di un touchlistener ma la soluzione di cui sopra sembra non dare una precisa collocazione. Per me il più delle volte era spento di 1-2 caratteri rispetto al cursore del testo. Il codice seguente risolve questo problema. La chiave per far funzionare questo è usare post() per posticipare il codice fino a dopo che la posizione del cursore è stata aggiornata. Quindi la posizione che ottengo è garantita per concordare con quella di EditText, e il codice è anche più semplice.

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

Anche io sto affrontando lo stesso problema. E quando ho provato a usare "int offset = layout.getOffsetForHorizontal (0, x);" come detto Wayne Kail, ha anche ottenuto NPE in questa linea. Così ho provato e alla fine scrivo in questo modo:

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

non ha funzionato per me. – Dharmishtha

Problemi correlati