2013-01-07 10 views
44

voglio avere il testo costante all'interno EditText come:inserire testo costante all'interno EditText che dovrebbe essere non modificabile - Android

http://<here_user_can_write> 

utente non dovrebbe essere in grado di eliminare tutti i caratteri da "http://", ho cercato su questo e ho trovato questo:

editText.setFilters(new InputFilter[] { 
    new InputFilter() { 
     public CharSequence filter(CharSequence src, int start, 
      int end, Spanned dst, int dstart, int dend) { 
      return src.length() < 1 ? dst.subSequence(dstart, dend) : ""; 
     } 
    } 
}); 

ma io non so se limita l'utente a non eliminare tutti i caratteri da dall'inizio alla fine limite. Inoltre non ho potuto capire l'uso della classe Spanned.

Un modo sarebbe una buona scelta se possiamo inserire un TextView all'interno di EditText ma non penso sia possibile in Android poiché entrambi sono Views, è possibile?

+0

controllare questa risposta http://stackoverflow.com/a/19789317/983741 –

risposta

85

Hai provato questo metodo?

final EditText edt = (EditText) findViewById(R.id.editText1); 

edt.setText("http://"); 
Selection.setSelection(edt.getText(), edt.getText().length()); 


edt.addTextChangedListener(new TextWatcher() { 

     @Override 
     public void onTextChanged(CharSequence s, int start, int before, int count) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void beforeTextChanged(CharSequence s, int start, int count, 
       int after) { 
      // TODO Auto-generated method stub 

     } 

     @Override 
     public void afterTextChanged(Editable s) { 
      if(!s.toString().startsWith("http://")){ 
       edt.setText("http://"); 
       Selection.setSelection(edt.getText(), edt.getText().length()); 

      } 

     } 
    }); 
+22

E 'più sicuro usare 'startsWith' piuttosto che' contains', per evitare all'utente di spostare il cursore e scrivi qualcosa prima della costante. –

+0

ma quando lo elimina senza spostare la mano dal pulsante Elimina il testo viene rimosso. Come posso risolvere? – user1767260

+0

Grazie machan, è stato utile ... –

9

C'è stato un piccolo problema con la risposta di @Rajitha Siriwardena. Si presuppone che l'intera stringa, tranne il suffisso è stato eliminato prima del suffisso è significato se avete la stringa di

http://stackoverflow.com/ 

e tenta di eliminare qualsiasi parte del http:// si elimina stackoverflow.com/ conseguente solo http://.

Ho anche aggiunto un controllo nel caso in cui l'utente tenta di immettere prima del prefisso.

@Override 
public void afterTextChanged(Editable s) { 
    String prefix = "http://"; 
    if (!s.toString().startsWith(prefix)) { 
     String cleanString; 
     String deletedPrefix = prefix.substring(0, prefix.length() - 1); 
     if (s.toString().startsWith(deletedPrefix)) { 
      cleanString = s.toString().replaceAll(deletedPrefix, ""); 
     } else { 
      cleanString = s.toString().replaceAll(prefix, ""); 
     } 
     editText.setText(prefix + cleanString); 
     editText.setSelection(prefix.length()); 
    } 
} 

Nota: questo non gestisce il caso in cui l'utente tenta di modificare il prefisso stesso solo prima e dopo.

0

Ecco una soluzione meno efficiente che dovrebbe gestire tutti i casi per quando i caratteri O parole vengono cancellati/inseriti in OR attorno al prefisso.

prefix = "http://" 
extra = "ahhttp://" 
differencePrefix(prefix, extra) = "aht" 

Codice:

public static String differencePrefix(String prefix, String extra) { 
    if (extra.length() < prefix.length()) return ""; 
    StringBuilder sb = new StringBuilder(); 
    StringBuilder eb = new StringBuilder(); 
    int p = 0; 
    for (int i = 0; i < extra.length(); i++) { 
     if (i >= prefix.length()) { 
      while(p < extra.length()) { 
       eb.append(extra.charAt(p)); 
       p++; 
      } 
      break; 
     } 
     if (p >= extra.length()) break; 
     char pchar = extra.charAt(p); 
     char ichar = prefix.charAt(i); 
     while(pchar != ichar) { 
      //check if char was deleted 
      int c = i + 1; 
      if (c < prefix.length()) { 
       char cchar = prefix.charAt(c); 
       if (cchar == pchar) { 
        break; 
       } 
      } 
      sb.append(pchar); 
      p++; 
      if (p >= extra.length()) break; 
      pchar = extra.charAt(p); 
     } 
     p++; 
    } 

    return eb.toString() + sb.toString(); 
} 

è possibile utilizzarlo come questo

editText.addTextChangedListener(new TextWatcher() { 
    @Override 
    public void beforeTextChanged(CharSequence s, int start, int count, int after) { 

    } 

    @Override 
    public void onTextChanged(CharSequence s, int start, int before, int count) { 

    } 

    @Override 
    public void afterTextChanged(Editable s) { 
     String input = s.toString(); 
     if (!input.startsWith(prefix)) { 
      String extra = differencePrefix(prefix, input); 
      String newInput = prefix + extra; 
      editText.setText(newInput); 
      editText.setSelection(newInput.length()); 
     } 
    } 
}); 
3

Avevi quasi giusto, provare

private final String PREFIX="http://"; 

editText.setFilters(new InputFilter[]{new InputFilter() { 
      @Override 
      public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int 
        dend) { 
       return dstart<PREFIX.length()?dest.subSequence(dstart,dend):null; 
      } 
     }}); 
9

è così che si può effettivamente farlo con un InputFilter:

Se si desidera che il prefisso non sia selezionabile, è possibile aggiungere il seguente codice.

final SpanWatcher watcher = new SpanWatcher() { 
    @Override 
    public void onSpanAdded(final Spannable text, final Object what, 
     final int start, final int end) { 
    // Nothing here. 
    } 

    @Override 
    public void onSpanRemoved(final Spannable text, final Object what, 
     final int start, final int end) { 
    // Nothing here. 
    } 

    @Override 
    public void onSpanChanged(final Spannable text, final Object what, 
     final int ostart, final int oend, final int nstart, final int nend) { 
    if (what == Selection.SELECTION_START) { 
     if (nstart < prefix.length()) { 
     final int end = Math.max(prefix.length(), Selection.getSelectionEnd(text)); 
     Selection.setSelection(text, prefix.length(), end); 
     } 
    } else if (what == Selection.SELECTION_END) { 
     final int start = Math.max(prefix.length(), Selection.getSelectionEnd(text)); 
     final int end = Math.max(start, nstart); 
     if (end != nstart) { 
     Selection.setSelection(text, start, end); 
     } 
    } 
    } 
}; 

editText.getText().setSpan(watcher, 0, 0, Spanned.SPAN_INCLUSIVE_EXCLUSIVE); 
+0

Molto utile e funzionante – ashishdhiman2007

0

so che sto facendo rivivere un vecchio post, ma voglio condividere con la comunità che ho lottato con questo tema in questi giorni e ho scoperto che mettendo un TextView sopra la EditText non è solo perfettamente fattibile (a rispondere alla seconda parte della domanda), molto di più in questo caso quando è necessario il testo costante nella posizione di partenza, ma anche preferibile. Inoltre il cursore non si muoverà nemmeno prima del testo "mutabile", che è un effetto elegante. Preferisco questa soluzione perché non aggiunge carico di lavoro e complessità alla mia app con gli ascoltatori e qualsiasi altra cosa.

Ecco un esempio di codice della mia soluzione:

<RelativeLayout 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_centerVertical="true" 
     android:layout_marginStart="3dp" 
     android:text="http://" /> 

    <EditText 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:inputType="textUri" 
     android:paddingStart="choose an appropriate padding" /> 
</RelativeLayout> 

Con racchiude il punto di vista in un RelativeLayout saranno sovrapposti. Il trucco sta giocando con la android:paddingStart proprietà del EditText, per rendere il testo inizia appena a destra dopo il TextView, mentre android:layout_centerVertical="true" e android:layout_marginStart="3dp" proprietà del TextView assicurarsi che il suo testo sia correttamente allineata con il testo immesso e con l'inizio della linea sottostante di EditText (o almeno questo si verifica quando si utilizza un tema a tema Materiale).

2

Utilizzare questa EditText personalizzato:

public class PrefixEditText extends EditText { 

private String mPrefix = "$"; // add your prefix here for example $ 
private Rect mPrefixRect = new Rect(); // actual prefix size 

public PrefixEditText(Context context, AttributeSet attrs) { 
    super(context, attrs); 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    getPaint().getTextBounds(mPrefix, 0, mPrefix.length(), mPrefixRect); 
    mPrefixRect.right += getPaint().measureText(" "); // add some offset 

    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    canvas.drawText(mPrefix, super.getCompoundPaddingLeft(), getBaseline(), getPaint()); 
} 

@Override 
public int getCompoundPaddingLeft() { 
    return super.getCompoundPaddingLeft() + mPrefixRect.width(); 
} 
} 
+0

Grazie, è stato molto utile –

2

codice per aggiungere CUSTOM prefisso per il tuo EDITTEXT (prefisso non è modificabile)

Codice da Medium di Ali Muzaffar

public class PrefixEditText extends AppCompatEditText { 
    float originalLeftPadding = -1; 

    public PrefixEditText(Context context) { 
     super(context); 
    } 

    public PrefixEditText(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public PrefixEditText(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
     super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
     calculatePrefix(); 
    } 

    private void calculatePrefix() { 
     if (originalLeftPadding == -1) { 
      String prefix = (String) getTag(); 
      float[] widths = new float[prefix.length()]; 
      getPaint().getTextWidths(prefix, widths); 
      float textWidth = 0; 
      for (float w : widths) { 
       textWidth += w; 
      } 
      originalLeftPadding = getCompoundPaddingLeft(); 
      setPadding((int) (textWidth + originalLeftPadding), 
       getPaddingRight(), getPaddingTop(), 
       getPaddingBottom()); 
     } 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 
     String prefix = (String) getTag(); 
     canvas.drawText(prefix, originalLeftPadding, getLineBounds(0, null), getPaint()); 
    } 
} 

e XML

<com.yourClassPath.PrefixEditText 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:gravity="bottom" 
    android:textSize="14sp" 
    android:tag="€ " /> 
+0

Assicurati di utilizzare il percorso di classe giusto nel tuo file xml. com.alimuzaffar.customwidgets.PrefixEditText: se lo usi, la tua app si romperà. –

+0

Sì, ho ragione, modificherò post. Errore mio –

0

Ho appena trovato la soluzione su come rendere il prefisso non modificabile e su come salvare il testo se si tenta di rimuovere il prefisso. Questo è molto vicino alla risposta di @Rajitha Siriwardena. Tutto ciò che ti è mancato è salvare il testo prima di applicare qualsiasi modifica. Sarà ripristinato in afterTextChanged (...).

Codice:

final String prefix = "http://"; 
editText.setText(prefix); 
Selection.setSelection(editText.getText(), editText.getText().length()); 

editText.addTextChangedListener(new TextWatcher() { 
    String text; 
    @Override 
    public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { 
     text = charSequence.toString(); 
    } 

    @Override 
    public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { 
    } 

    @Override 
    public void afterTextChanged(Editable editable) { 
     if (!editable.toString().startsWith(prefix)) { 
      editText.setText(text); 
      Selection.setSelection(editText.getText(), editText.getText().length()); 
     } 
    } 
}); 
Problemi correlati