Подтвердить что ты не робот

Установите неизменяемую часть editText android

У меня есть EditText для ввода мобильного номера. Приложение должно добавлять уникальный текст для каждой страны. Например, для Армении необходимо добавить +374, и пользователь должен заполнить другие номера. Также +374 должен быть неизменным, пользователь не может его изменить или удалить. Итак, есть ли способы сделать это? enter image description here

EDIT:

Я не хочу использовать textView или другое представление с этим текстом и оставлять его слева от ediText. Я хочу найти способ с меньшим количеством операций. Мне нужно, чтобы текст был заморожен, чтобы не проверять каждый текст или добавлять отсутствующий текст, когда пользователь удалит часть его.

4b9b3361

Ответ 1

Создайте пользовательский класс для рисования, который поможет преобразовать текст в рисованный.

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;
  }
}

Затем установите рисование слева от текста редактирования как

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

Где текст редактирования определяется в файле макета как

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

Окончательный результат выглядит как

enter image description here

Ответ 2

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

            }

        }

    });
}

}

Ответ 3

вы можете создать расширение класса AppCompatEditText или 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());
            }
        }

}

для использования:

edt.setCharactersNoChangeInitial("+734 ");

Ответ 4

Использовать наблюдателя текста, а когда пользователь вводит +3, он завершается +374, и он сравнивает первые четыре символа, и если он отключает обратное нажатие программной клавиатуры, чтобы он не менял текст и вводил другую цифру, которая добавьте текст, используемый из текстового элемента

Ответ 5

Я выбрал решение, похожее на другое представленное, для расширения EditText и изменения onSelectionChanged. Это не позволяет пользователю даже войти в этот регион.

Вот что я использую:

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 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
        }
    }
}

С тестами:

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