Поместите постоянный текст внутри 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, так как оба вида, это возможно?

787   11  

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

    Ничего не найдено.