84 votes

Mettre un texte constant dans un EditText qui ne devrait pas être modifiable - Android

Je veux avoir un texte constant à l'intérieur de editText comme :

http://<here_user_can_write>

L'utilisateur ne doit pas pouvoir supprimer des caractères de " http:// "J'ai fait des recherches à ce sujet et j'ai trouvé ceci :

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

mais je ne sais pas s'il restreint l'utilisateur à ne pas supprimer de caractères de du début à la fin limite. Je n'ai pas non plus compris l'utilisation de la classe Spanned.

Un bon choix serait de mettre en place une TextView à l'intérieur EditText mais je ne pense pas que ce soit possible dans Android puisque les deux sont des Vues, est-ce possible ?

165voto

Rajitha Siriwardena Points 2629

Avez-vous essayé cette méthode ?

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

            }

        }
    });

48voto

Mahozad Points 1573

A partir de la version 1.2.0-alpha01 de bibliothèque de conception de matériaux Le préfixe et le suffixe sont pris en charge pour les champs de texte :

<com.google.android.material.textfield.TextInputLayout
        app:prefixText="Price: "
        app:prefixTextAppearance="..."
        app:prefixTextColor="..."
        app:suffixText="Dollar"
        app:suffixTextColor="..."
        app:suffixTextAppearance="...">

    <com.google.android.material.textfield.TextInputEditText .../>

</com.google.android.material.textfield.TextInputLayout>

Le seul inconvénient, à mon avis, est que les suffixe est fixé à la fin du champ de texte et il n'y a pas d'option pour le faire suivre le texte saisi. Vous pouvez voter sur cette question pour cela.

16voto

Michael Points 16659

C'est ainsi que vous pouvez le faire avec 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 vous souhaitez également que le préfixe ne soit pas sélectionnable, vous pouvez ajouter le code suivant.

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

10voto

Il y a eu un petit problème avec la réponse de @Rajitha Siriwardena. Elle suppose que toute la chaîne à l'exception du suffixe a été supprimée avant que le suffixe ne soit signifié si vous avez la chaîne

http://stackoverflow.com/

et essayer de supprimer n'importe quelle partie de http:// vous supprimez stackoverflow.com/ qui n'a donné lieu qu'à http:// .

J'ai également ajouté un contrôle au cas où l'utilisateur essaierait de saisir des données avant le préfixe.

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

Remarque : cette méthode ne tient pas compte du cas où l'utilisateur tente de modifier le préfixe lui-même, mais seulement avant et après.

7voto

Vishal Jadav Points 387

Tiré du blog d'Ali Muzaffar, voir l'article original pour plus de détails.

Utiliser des produits personnalisés EditText Vue permettant de dessiner le texte du préfixe et d'ajouter un rembourrage en fonction de la taille du texte du préfixe :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X