在EditText中放置常量文本,该文本应该是不可编辑的 - Android

Shr*_*ant 64 android textview android-edittext

我想在editText中有一个常量文本,如:

http://<here_user_can_write>
Run Code Online (Sandbox Code Playgroud)

用户不应该从" 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) : "";
        }
    }
}); 
Run Code Online (Sandbox Code Playgroud)

但我不知道它是否限制用户不从开始到结束限制删除任何字符.我也无法理解Spanned类的使用.

一种方法是一个很好的选择,如果我们可以放入TextView内部,EditText但我不认为这是可能的Android,因为两者都是视图,是否可能?

Raj*_*ena 142

你尝试过这种方法吗?

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

            }

        }
    });
Run Code Online (Sandbox Code Playgroud)

  • 使用`startsWith`而不是`contains`更安全,以避免用户移动光标位置并在常量之前键入任何内容. (25认同)
  • 您还可以扩展EditText并覆盖受保护的void onSelectionChanged(int selStart,int selEnd)方法,这样就可以防止选择常量文本 (2认同)

Mah*_*zad 37

随着版本的1.2.0-alpha01材料设计库,前缀和后缀支持文本字段:

<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>
Run Code Online (Sandbox Code Playgroud)

我认为唯一的缺点是后缀固定在文本字段的末尾,并且没有选项可以使其与输入文本一起流动。您可以为此问题投票。


Mic*_*ael 15

这就是你用以下方法实际做到的方法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;
        }
      }
    }
});
Run Code Online (Sandbox Code Playgroud)

如果您还希望不能选择前缀,则可以添加以下代码.

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);
Run Code Online (Sandbox Code Playgroud)


Lac*_*ook 9

@Rajitha Siriwardena的回答有点问题.如果你有字符串,它假定在后缀之前删除了除后缀之外的整个字符串

http://stackoverflow.com/
Run Code Online (Sandbox Code Playgroud)

并尝试删除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());
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:这不处理用户尝试仅在之前和之后编辑前缀本身的情况.


Vis*_*dav 7

摘自 Ali Muzaffar 的博客,有关更多详细信息,请参阅原始帖子

使用自定义EditTextView绘制前缀文本并根据前缀文本大小添加padding:

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();
}
}
Run Code Online (Sandbox Code Playgroud)

  • 嘿,Vishal,下次您从某人的博客(或互联网上的任何地方)复制代码时,请记住链接到源。 (3认同)

sle*_*dav 5

你几乎是对的,试试

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;
            }
        }});
Run Code Online (Sandbox Code Playgroud)


Jac*_*per 5

将自定义前缀添加到您的编辑文本的代码(前缀不可编辑)

Ali Muzaffar 来自 Medium 的代码

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

和 XML

<com.yourClassPath.PrefixEditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="bottom"
    android:textSize="14sp"
    android:tag="€ " />
Run Code Online (Sandbox Code Playgroud)