Set unchangeable some part of editText android

前端 未结 5 852
青春惊慌失措
青春惊慌失措 2020-11-30 01:03

I have some EditText for mobile number input. App must add unique text for every country. For example for Armenia is must add +374 , and user must fill other nu

相关标签:
5条回答
  • 2020-11-30 01:45

    Use Text watcher and when user enters +3 it completes with +374 and it compares the first four characters and if it is same disable the back press of the softkeyboard so that it will not change the text and enters the other digit which append for the text used from the textwatcher

    0 讨论(0)
  • 2020-11-30 01:47

    Create a custom drawable class that will help to convert text into drawable.

    public class TextDrawable extends Drawable {
    
      private final String text;
      private final Paint paint;
    
      public TextDrawable(String text) {
          this.text = text;
          this.paint = new Paint();
          paint.setColor(Color.BLACK);
          paint.setTextSize(16f);
          paint.setAntiAlias(true);
          paint.setTextAlign(Paint.Align.LEFT);
      }
    
      @Override
      public void draw(Canvas canvas) {
          canvas.drawText(text, 0, 6, paint);
      }
    
      @Override
      public void setAlpha(int alpha) {
          paint.setAlpha(alpha);
      }
    
      @Override
      public void setColorFilter(ColorFilter cf) {
          paint.setColorFilter(cf);
      }
    
      @Override
      public int getOpacity() {
          return PixelFormat.TRANSLUCENT;
      }
    }
    

    Then set the drawable to left of the edittext as

    EditText et = (EditText)findViewById(R.id.editText1);
    String code = "+374";
    et.setCompoundDrawablesWithIntrinsicBounds(new TextDrawable(code), null, null, null);
    et.setCompoundDrawablePadding(code.length()*10);
    

    Where the edittext is defined in the layout file as

    <EditText
    android:id="@+id/editText1"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="16sp"
    android:ems="10" >
      <requestFocus />
    </EditText>
    

    Final Output looks like

    enter image description here

    0 讨论(0)
  • 2020-11-30 01:49

    you can create class extend AppCompatEditText or EditText.

    public class CEditTextMaster extends AppCompatEditText {
    
            private boolean isNeedNoChangeSomeCharacters;
            private String charactersNoChange;
    
            public CEditTextMaster(Context context) {
                super(context);
                init(context, null);
            }
    
            public CEditTextMaster(Context context, AttributeSet attrs) {
                super(context, attrs);
                init(context, attrs);
            }
    
            public CEditTextMaster(Context context, AttributeSet attrs, int defStyleAttr) {
                super(context, attrs, defStyleAttr);
                init(context, attrs);
            }
    
            public void init(Context context, @Nullable AttributeSet attrs) {
    
                if (isInEditMode())
                    return;
    
                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) {
                        if (isNeedNoChangeSomeCharacters && charactersNoChange != null) {
                            if (!getText().toString().startsWith(charactersNoChange)) {
                                removeTextChangedListener(this);
                                if (charactersNoChange.length() > s.length()) {
                                    setText(charactersNoChange);
                                } else {
                                    setText(charactersNoChange + getText());
                                }
                                setSelection(getText().toString().length());
                                addTextChangedListener(this);
                            }
                        }
                    }
                });
    
            }
    
            @Override
            protected void onSelectionChanged(int selStart, int selEnd) {
                if (isNeedNoChangeSomeCharacters && charactersNoChange != null) {
                    if (length() > charactersNoChange.length() && selStart < charactersNoChange.length()) {
                        setSelection(charactersNoChange.length(),selEnd);
                    }
                }
            }
    
    
            @Override
            public void setText(CharSequence text, BufferType type) {
                super.setText(text, type);
                if (isNeedNoChangeSomeCharacters && charactersNoChange != null) {
                    if (!getText().toString().trim().startsWith(charactersNoChange)) {
                        setText(charactersNoChange + getText());
                    }
                }
            }
    
            public void setCharactersNoChangeInitial(String charactersNoChange) {
                isNeedNoChangeSomeCharacters = true;
                this.charactersNoChange = charactersNoChange;
                if (!getText().toString().trim().startsWith(charactersNoChange)) {
                    setText(getText());
                }
            }
    
    }
    

    for use:

    edt.setCharactersNoChangeInitial("+734 ");
    
    0 讨论(0)
  • 2020-11-30 01:50

    I opted for a solution, similar to another one submitted, of extending EditText and modifying onSelectionChanged. This prevents the user from even entering that region.

    Here's what I'm using:

    import android.content.Context
    import android.text.Editable
    import android.util.AttributeSet
    import androidx.appcompat.widget.AppCompatEditText
    
    class PrefixEditText(context: Context, attrs: AttributeSet?) : AppCompatEditText(context, attrs) {
        private var prefix: String? = null
    
        fun setPrefix(prefix: String) {
            this.prefix = prefix
            setText(prefix)
    
            addTextChangedListener(object : TextWatcher {
                override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) = Unit
                override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) = Unit
    
                override fun afterTextChanged(s: Editable?) {
                    // Block deleting the prefix
                    if (s?.startsWith(prefix) == false) {
                        setText(prefix)
                    }
                }
            })
        }
    
        override fun onSelectionChanged(selStart: Int, selEnd: Int) {
            var newStart = selStart
            var newEnd = selEnd
            prefix?.length?.let {
                newStart = if (selStart < it) it else selStart
                newEnd = if (selEnd < it) it else selEnd
            }
    
            if (selStart != newStart || selEnd != newEnd) {
                setSelection(newStart, newEnd)
            } else {
                super.onSelectionChanged(selStart, selEnd)
            }
        }
    
        // Here to conform to EditText's API
        // Could also just override getText()
        fun getPostText(): Editable? {
            return prefix?.let {
                Editable.Factory.getInstance().newEditable(text)?.delete(0, it.length)
            } ?: run {
                text
            }
        }
    
        // Here for convenience, to avoid instantiating a new Editable, if the text is all you need
        fun getPostCharSeq(): CharSequence? {
            return prefix?.let {
                text?.substring(it.length)
            } ?: run {
                text
            }
        }
    }
    

    With tests:

    import android.view.ViewGroup
    import android.widget.FrameLayout
    import androidx.test.ext.junit.runners.AndroidJUnit4
    import androidx.test.rule.ActivityTestRule
    import com.roosterteeth.roosterteeth.TestActivity
    import org.junit.Assert
    import org.junit.Rule
    import org.junit.Test
    import org.junit.runner.RunWith
    
    @RunWith(AndroidJUnit4::class)
    class PrefixEditTextTest {
        @Rule
        @JvmField
        var activityRule: ActivityTestRule<TestActivity> = ActivityTestRule(TestActivity::class.java, true, true)
    
        private fun setupView(prefix: String, message: String): PrefixEditText {
            val editText = PrefixEditText(activityRule.activity, null)
            val lp = FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
            activityRule.activity.addContentView(editText, lp)
    
            editText.setPrefix(prefix)
            editText.append(message)
    
            return editText
        }
    
        @Test
        fun testSelection() {
            activityRule.runOnUiThread {
                val prefix = "pre: "
                val message = "hello world"
                val editText = setupView(prefix, message)
    
                editText.setSelection(0)
                Assert.assertEquals(editText.selectionStart, prefix.length)
                Assert.assertEquals(editText.selectionEnd, prefix.length)
                editText.setSelection(0, editText.length())
                Assert.assertEquals(editText.selectionStart, prefix.length)
                Assert.assertEquals(editText.selectionEnd, editText.length())
            }
        }
    
        @Test
        fun testGetPostText() {
            activityRule.runOnUiThread {
                val prefix = "pre: "
                val message = "hello world"
                val editText = setupView(prefix, message)
    
                Assert.assertEquals(message, editText.getPostText().toString())
                // This test is after to make sure that getting the post text did not actually modify the contents
                Assert.assertEquals("pre: $message", editText.text.toString())
            }
        }
    
        @Test
        fun testGetPostCharSeq() {
            activityRule.runOnUiThread {
                val prefix = "pre: "
                val message = "hello world"
                val editText = setupView(prefix, message)
    
                Assert.assertEquals(message, editText.getPostCharSeq())
                // This test is after to make sure that getting the post text did not actually modify the contents
                Assert.assertEquals("pre: $message", editText.text.toString())
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-30 01:56
    public class MainActivity extends Activity {
    
    private EditText editText;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        editText = (EditText) findViewById(R.id.editText1);
        editText.setText("+374");
        Selection.setSelection(editText.getText(), editText.getText().length());
        editText.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("+374")) {
                    editText.setText("+374");
                    Selection.setSelection(editText.getText(), editText
                            .getText().length());
    
                }
    
            }
    
        });
    }
    
    }
    
    0 讨论(0)
提交回复
热议问题