前言
Editext控件用于输入和修改文本的用户界面元素,我们定义R.styleable.TextView_inputType属性可以限制Editext的输入数据类型。一般你可以选择使用单个值或者多个值用“|”进行分割。例如你需要一个输入身高体重的输入框提供给用户则只需要将inputType属性设置为“number|numberDecimal”,这样你就可以在输入框中限制用户只输入数字和小数点了。
一、在XML中设置一个EditText
<EditText
android:id="@+id/height_edittext"
android:paddingEnd="15dp"
android:background="@color/white"
android:hint="请输入身高"
android:enabled="false"
android:textSize="14sp"
android:inputType="number|numberDecimal"
android:gravity="right|center_vertical"
android:lines="1"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="@+id/height_text"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:textColor="#FF7D7D7D"
android:layout_width="0dp"
android:layout_height="match_parent"
tools:ignore="RtlHardcoded,RtlSymmetry" />
二、添加editText的文本输入监听
val editText = findViewById<EditText>(R.id.height_edittext)
editText.addTextChangedListener(object :TextWatcher{
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
TODO("Not yet implemented")
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
TODO("Not yet implemented")
}
override fun afterTextChanged(s: Editable?) {
TODO("Not yet implemented")
}
})
三、afterTextChanged中处理单位
先创建一个需要设置的单位变量,在afterTextChanged方法中我们先判断输入内容是否为空,当输入的内容不为空并且输入的内容和我们的单位内容是一样的 则将editText 设置为空内容。
//先创建一个heightUnit变量 内容是你需要添加的单位
private val heightUnit = "cm"
val editText = findViewById<EditText>(R.id.height_edittext)
editText.addTextChangedListener(object :TextWatcher{
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(inputContent: Editable?) {
if (inputContent != null) {
editText.removeTextChangedListener(this) //暂时移除输入监听避免死循环
if (inputContent.toString().trim() == heightUnit) {
editText.setText("")
} else {
}
}
}
})
接下来判断内容不仅仅是单位的情况,我们需要先判断输入的内容光标位置,如果光标位置在内容的最后则我们主动将光标位置移动到单位前内容后的位置。
val editText = findViewById<EditText>(R.id.height_edittext)
editText.addTextChangedListener(object :TextWatcher{
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(inputContent: Editable?) {
if (inputContent != null) {
editText.removeTextChangedListener(this) //移除输入监听,避免陷入死循环
if (inputContent.toString().trim() == heightUnit) {
//当此时内容是单位的时候,将edittext置为空
editText.setText("")
} else {
var ss = inputContent.toString()
//判断光标的位置
val len = ss.length - heightUnit.length
if (len >0 && ss.substring(ss.length - heightUnit.length,ss.length) == heightUnit){
//单位就在最后不处理
}else {
//当用户将光标置到单位后面时,输入的内容就会在单位后面,此时将前面的单位去掉,将单位放到最后
ss = ss.replace(heightUnit, "") + heightUnit
editText.setText(ss)
}
}
}
}
})
最后我们再将光标的位置重新设置并且将移除的监听重新添加进来就可以了,下面是完整代码
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.Editable
import android.text.Selection
import android.text.TextWatcher
import android.widget.EditText
class MainActivity : AppCompatActivity() {
private val heightUnit = "cm"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initEditText()
}
private fun initEditText() {
val editText = findViewById<EditText>(R.id.height_edittext)
editText.addTextChangedListener(object :TextWatcher{
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
override fun afterTextChanged(inputContent: Editable?) {
if (inputContent != null) {
editText.removeTextChangedListener(this) //移除输入监听,避免陷入死循环
if (inputContent.toString().trim() == heightUnit) {
//当此时内容是单位的时候,将edittext置为空
editText.setText("")
} else {
var ss = inputContent.toString()
//辅助判断单位存不存在/存在的位置
val len = ss.length - heightUnit.length
if (len >0 && ss.substring(ss.length - heightUnit.length,ss.length) == heightUnit){
//单位就在最后不处理
}else {
//当用户自己将光标置到单位后面时,输入的内容就会在单位后面,此时将前面的单位去掉,将单位放到最后
ss = ss.replace(heightUnit, "") + heightUnit
editText.setText(ss)
//这里得到光标应该在的位置(单位前面)
val index= ss.length - heightUnit.length
//设置光标的位置
Selection.setSelection(editText.text, if (index<0) 0 else index)
}
//重新进行监听
editText.addTextChangedListener(this)
}
}
}
})
}
}
这个需求并不难,关键是处理好输入过程中的判断逻辑。