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:
- Cómo quitar la etiqueta de HTML en android?
- ¿Cómo puedo interactuar con el diseño de Lockscreen para mostrar texto en él, como esta aplicación:
- La última palabra de Android de una línea puede provocar una dimensión de texto incorrecta si se utiliza un margen derecho
- TextView ampliar animación como en Android Market
- La interfaz de usuario se actualiza cuando mi aplicación pierde el foco y recupera el foco. Tema extraño
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?
- Fuente urdu en la vista de texto
- RadioButtons con TextView en RadioGroup
- Añadir opaco "sombra" (esquema) a Android TextView
- Establecer el borde y el color de fondo de textView
- Justificar texto en la vista de texto
- Android enlaza sin primer carácter
- Android: agrega texto a la presentación al pulsar el botón
- Resaltar Textview con EditText
¿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).
- Android – Imagen parpadeante utilizando la animación Alpha fade
- Manejo del botón MENU que falta en las nuevas versiones de Android (3.x y superior)