Put constant text inside EditText which should be non-editable - Android
Solution 1
Did u try this method?
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());
}
}
});
Solution 2
As of version 1.2.0-alpha01 of material design library, prefix and suffix is supported for text fields:
<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>
The only downside in my opinion is that the suffix is fixed at the end of the text field and there is no option to make it flow with the input text. You can vote on this issue for that.
Solution 3
That's how you can actually do it with an 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;
}
}
}
});
If you also want the prefix to be not selectable you can add the following code.
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);
Solution 4
There was a slight problem with @Rajitha Siriwardena's answer. It assumes that the entire string except the suffix has been deleted before the suffix is meaning if you have the string
http://stackoverflow.com/
and try to delete any part of http://
you will delete stackoverflow.com/
resulting in only http://
.
I also added a check incase the user tries to input before the prefix.
@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());
}
}
Note: this doesn't handle the case where the user tries to edit the prefix itself only before and after.
Solution 5
Taken from Ali Muzaffar's blog, see the original post for more details.
Use custom EditText
View to draw the prefix text and add padding according to the prefix text size:
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();
}
}
Related videos on Youtube
Shrikant Ballal
Hello, I am Shrikant Ballal, Staff Engineer - Android at YML. Interested in Android, Kotlin, Dev Tools, Processes and CI/CD.
Updated on July 08, 2022Comments
-
Shrikant Ballal almost 2 years
I want to have constant text inside editText like:
http://<here_user_can_write>
User should not be able to delete any chars from "
http://
", I searched about this and found this: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) : ""; } } });
but I don't know whether it restricts user to not delete any chars from start to end limit. I also could not understand use of Spanned class.
One way would be a good choice if we can put a
TextView
insideEditText
but I don't think it is possible in Android since both are Views, is it possible?-
Sunil Mishra over 10 yearsCheck this answer stackoverflow.com/a/19789317/983741
-
-
Ε Г И І И О almost 11 yearsIt's safer to use
startsWith
rather thancontains
, to avoid user moving the cursor position and type anything before the constant. -
user1767260 over 10 yearsbut when deletes it without moving the hand from delete button the text is removed.how can I solve?
-
Aman Verma about 8 yearsi cant set the hint now..help me
-
demaksee over 7 yearsAlso you can extend EditText and override protected void onSelectionChanged(int selStart, int selEnd) method, and in this way prevent even selecting constant text
-
Rishikesh pathak about 7 yearsI have quite similar requirement but i want text "KG" in back always.when user type text.How to achieve this.please help.
-
Johnny Five about 6 yearsMake sure you use right class path in your xml file. com.alimuzaffar.customwidgets.PrefixEditText - if you use this, your app will crush.
-
Abdul Rizwan almost 6 yearsthis is not working in Nougat and in other OS it's working fine, can you please let me know , how can we resolve this in Nougat?
-
Marcel Bro over 5 yearsHey Vishal, next time you copy a code from somebody's blog (or anywhere from the internet), please remember to link to the source.
-
Vishal Jadav over 5 yearsOkay will do 👍
-
A moskal escaping from Russia over 4 yearsThe answer written right before yours points to the same Medium post.
-
Jakub S. over 4 years@SebastianPalma at the time i wrote my answer there was no link to the blog. The answer was edited.
-
Ali Obeid almost 4 yearsThe EditText field stopped receiving any input. can't type anything in it. I believe this solution is not working anymore.
-
Sadda Hussain over 3 yearsHow would you set text on this edittext? .setText() does not seem to be working.
-
PriyankVadariya over 2 yearsAny way to update PreFix? I want to change after user perform some task
-
Antonis Radz over 2 yearsI think you can try remove old one and new one, just make some adjustments to code
-
Wini about 2 yearshow to change color for tag(prefix value)?
-
Konstantin Konopko almost 2 yearsHere prefix is not fixed at the beginning of a text