Poner texto constante dentro de EditText que no debería ser editable – Android

Quiero tener texto constante dentro de editText como:

http://<here_user_can_write> 

El usuario no debería ser capaz de eliminar los caracteres de " http:// ", busqué acerca de esto y encontré esto:

 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) : ""; } } }); 

Pero no sé si restringe el usuario a no eliminar ningún carácter de principio a fin límite. También no podía entender el uso de la clase Spanned.

Una manera sería una buena opción si podemos poner un TextView dentro de EditText pero no creo que sea posible en Android ya que ambos son Vistas, ¿es posible?

¿Has probado este método?

 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().contains("http://")){ edt.setText("http://"); Selection.setSelection(edt.getText(), edt.getText().length()); } } }); 

Hubo un pequeño problema con la respuesta de @Rajitha Siriwardena. Asume que toda la cadena, excepto el sufijo, se ha eliminado antes de que el sufijo tenga significado si tiene la cadena

 http://stackoverflow.com/ 

Y tratar de eliminar cualquier parte de http:// se eliminará stackoverflow.com/ resultando en sólo http:// .

También agregué un cheque en caso de que el usuario intente ingresar antes del prefijo.

  @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: esto no maneja el caso en el que el usuario intenta editar el prefijo en sí solo antes y después.

Así es como puedes hacerlo con un InputFilter :

 final String prefix = "http://" editText.setText(prefix); editText.setFilters(new InputFilter[] { new InputFilter() { @Override public CharSequence filter(final CharSequence source, final int start, final int end, final Spanned dest, final int dstart, final int dend) { final int newStart = Math.max(prefix.length(), dstart); final int newEnd = Math.max(prefix.length(), dend); if (newStart != dstart || newEnd != dend) { final SpannableStringBuilder builder = new SpannableStringBuilder(dest); builder.replace(newStart, newEnd, source); if (source instanceof Spanned) { TextUtils.copySpansFrom( (Spanned) source, 0, source.length(), null, builder, newStart); } Selection.setSelection(builder, newStart + source.length()); return builder; } else { return null; } } } }); 

Si también desea que el prefijo no sea seleccionable, puede agregar el siguiente código.

 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); 

Lo tenías casi bien, intenta

 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; } }}); 

Utilice este Custom EditText:

 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(); } } 

Esta es una solución menos eficiente que debe manejar todos los casos para cuando los caracteres O las palabras se eliminan / insertan en O alrededor del prefijo.

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

Código:

 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(); } 

Puedes usarlo así

 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()); } } }); 

Sé que estoy reviviendo un viejo post, pero quiero compartir con la comunidad que he luchado con este tema en estos días y me pareció que la colocación de un TextView sobre el EditText no sólo es perfectamente factible (para responder a la segunda parte de la Cuestión), mucho más en este caso cuando el texto constante es necesario en la posición inicial, pero preferible, también. Además, el cursor ni siquiera se mueve antes del texto "mutable" en absoluto, lo cual es un efecto elegante. Yo prefiero esta solución, ya que no agrega carga de trabajo y complejidad a mi aplicación con los oyentes y lo que sea.

He aquí un ejemplo de código de mi solución:

 <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> 

Al incluir las vistas en un RelativeLayout , se superpondrán. El truco aquí es jugar con la propiedad android:paddingStart de EditText , para hacer que el texto comience justo después de TextView , mientras que android:layout_centerVertical="true" y android:layout_marginStart="3dp" propiedades de TextView asegurarse de que su El texto se alinea correctamente con el texto introducido y con el inicio de la línea subyacente del EditText (o al menos esto sucede cuando se utiliza un material temático).

  • TextViews en la parte superior e inferior, el espacio restante lleno de ListView
  • Android html.fromhtml + spannablestring
  • Android TextView habilita las etiquetas LinkiFy y Href
  • ¿Cuál es el color predeterminado para el texto en textview?
  • El texto no ellipsiza
  • Cómo mostrar un formato doble como un precio en una vista de texto en android
  • Cómo establecer el color del texto en una vista de texto mediante programación
  • Hacer que los elementos de ListView sean seleccionables
  • Añadir dinámicamente una vista al diseño de la actividad
  • Actualización de contenido de ScrollView
  • Conversión de TextView a String (tipo de) Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.