Поместите постоянный текст внутри EditText, который должен быть не редактируемым-Android
Я хочу иметь постоянный текст внутри editText, как:
http://<here_user_can_write>
пользователь не должен быть в состоянии удалить все символы от "http://", Я искал об этом и нашел это:
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) : "";
}
}
});
но я не знаю, ограничивает ли это пользователя, чтобы не удалять любые символы из от начала до конца ограничения. Я также не мог понять использование Spanned класса.
один из способов был бы хорошим выбором, если мы можем поставить TextView внутри EditText но я не думаю, что это возможно в Android, так как оба вида, это возможно?
11 ответов:
вы пробовали этот метод?
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()); } } });
вот как вы можете сделать это с помощью
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; } } } });Если вы также хотите, чтобы префикс не выбирался, вы можете добавить следующий код.
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);
была небольшая проблема с ответом @Rajitha Siriwardena. Он предполагает, что вся строка, кроме суффикса, была удалена до того, как суффикс имеет значение, если у вас есть строка
http://stackoverflow.com/и попробуйте удалить любую часть
http://будут удаленыstackoverflow.com/в результатеhttp://.Я также добавил проверку, если пользователь пытается ввести перед префиксом.
@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()); } }Примечание: это не обрабатывает случай, когда пользователь пытается редактировать префикс только до и после.
КОД ДЛЯ ДОБАВЛЕНИЯ ПОЛЬЗОВАТЕЛЬСКОГО ПРЕФИКСА В ВАШ EDITTEXT (ПРЕФИКС НЕ РЕДАКТИРУЕТСЯ)
код от Medium by 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()); } }и XML
<com.yourClassPath.PrefixEditText android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="bottom" android:textSize="14sp" android:tag="€ " />
У вас это было почти правильно, попробуйте
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; } }});
используйте этот пользовательский 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(); } }
Я знаю, что я возрождаю старый пост, но я хочу поделиться с сообществом, что я боролся с этой темой в эти дни, и я обнаружил, что размещение
TextViewнаEditTextне только идеально выполнимо (чтобы ответить на вторую часть вопроса), гораздо больше в этом случае, когда постоянный текст необходим в начальной позиции, но и предпочтительнее. Кроме того, курсор даже не будет двигаться перед "изменяемым" текстом вообще, что является элегантным эффектом. Я предпочитаю это решение, потому что это не добавляет нагрузку и сложность в мое приложение со слушателями и вообще.вот пример кода моего решения:
<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>заключив представления в
RelativeLayoutони будут перекрываться. Трюк здесь играет сandroid:paddingStartсвойстваEditText, чтобы текст начинался сразу послеTextView, в то время какandroid:layout_centerVertical="true"иandroid:layout_marginStart="3dp"свойстваTextViewубедитесь, что его текст правильно выровнен с введенным текстом и с началом нижележащая строкаEditText(или, по крайней мере, это происходит при использовании материала тематический праздник).
это в основном для добавления префикса "+ 91 " в текстовое поле редактирования номера телефона.
1.Добавьте этот код в oncreate () activity
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_up); // Write other things......// etPhoneNumber.setFilters(new InputFilter[]{getPhoneFilter(),newInputFilter.LengthFilter(13)}); etPhoneNumber.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { if (etPhoneNumber.getText().toString().isEmpty()) { etPhoneNumber.setText("+91"); Selection.setSelection(etPhoneNumber.getText(), etPhoneNumber.getText().length()); } } else { if (etPhoneNumber.getText().toString().equalsIgnoreCase("+91")) { etPhoneNumber.setFilters(new InputFilter[]{}); etPhoneNumber.setText(""); etPhoneNumber.setFilters(new InputFilter[]{getPhoneFilter(),new InputFilter.LengthFilter(13)}); } } } }); }2.Объявить метод, называемый getPhoneFilter()
private InputFilter getPhoneFilter() { Selection.setSelection(etPhoneNumber.getText(), etPhoneNumber.getText().length()); etPhoneNumber.addTextChangedListener(new TextWatcher() { @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void afterTextChanged(Editable s) { if(!s.toString().startsWith("+91")){ if (etPhoneNumber.getFilters() != null && etPhoneNumber.getFilters().length > 0) { etPhoneNumber.setText("+91"); Selection.setSelection(etPhoneNumber.getText(), etPhoneNumber.getText().length()); } } } }); // Input filter to restrict user to enter only digits.. InputFilter filter = new InputFilter() { public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { for (int i = start; i < end; i++) { if (!String.valueOf(getString(R.string.digits_number)).contains(String.valueOf(source.charAt(i)))) { return ""; } } return null; } }; return filter; }3.объявите "digits_number" в файле значений
<string name="digits_number">1234567890+</string>
вот менее эффективное решение, которое должно обрабатывать все случаи, когда символы или слова удаляются/вставляются в префикс или вокруг него.
prefix = "http://" extra = "ahhttp://" differencePrefix(prefix, extra) = "aht"код:
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(); }вы можете использовать его так
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()); } } });
Я только что нашел решение, как сделать префикс не редактируемым и как сохранить текст, если вы пытаетесь удалить префикс. Это очень близко к ответу @Rajitha Siriwardena. Все, что вы пропустили, это сохранить текст до внесения каких-либо изменений. Он будет восстановлен в afterTextChanged(...).
код:
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()); } } });
EditText msg=new EditText(getContext()); msg.setSingleLine(true); msg.setSingleLine(); msg.setId(View.generateViewId()); msg.measure(0,0); TextView count=new TextView(getContext()); count.setTextColor(Color.parseColor("#666666")); count.setText("20"); count.setPadding(0,0,(int)Abstract.getDIP(getContext(),10),0); count.measure(0,0); float tenPIX =TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,getContext().getResources().getDisplayMetrics()); msg.setPadding((int)tenPIX,(int)tenPIX,(int)(int)tenPIX+count.getMeasuredWidth(),(int)tenPIX); RelativeLayout ll1=new RelativeLayout(getContext()); ll1.addView(msg,new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); LayoutParams countlp=new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); countlp.addRule(RelativeLayout.ALIGN_END,msg.getId()); countlp.addRule(RelativeLayout.ALIGN_BASELINE,msg.getId()); ll1.addView(count,countlp);
Comments