TextWatcher设置最小值和最大值



im试图使用TextWatcher将输入限制在一个数字范围内,如果用户试图超出范围,则强制输入最小值和最大值。工作几乎如预期,但在删除时,允许视觉上为空的文本。我该怎么避免呢?

inputVal.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(s:Editable) {     //s=""
var curVal = s.toString().toIntOrNull()?:5  //curVal=5
if (curVal <  5){
curVal = 5
s.replace(0,s.length,"5")  <- problem here, not replacing cuz s.length=0
}else if (curVal >50){
curVal = 50
s.replace(0,s.length,"50")
}
//some other things to do based on 'curVal'
}})

更新我需要的是,例如,u有一个"20",并添加一个0(将是200(,将其转换为"50";如果删除0(为2(,则在输入中强制使用5。

如果s为空,则curVal将为5。

所以它不会触发任何条件。

也许试试:

if (curVal <=  5)

您可以根据自己的喜好进行更改;我们只需要使用source和dest。

source返回在edittext中输入的新输入,如果按退格键则为空dest返回缓冲区中已存在的前一个输入

假设我第一次在edittext中输入6,source返回6,dest返回空,因为第一次在缓冲区中没有输入,如果接下来输入7,那么source将返回7,而dest将返回6。使用这个我们可以检查极限。

class InputRangeFilter(val mMin: Int, val mMax: Int) : InputFilter {
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence? {

val finalValue = (dest.toString().trim() + source.toString().trim()).toInt()

return if (source?.isEmpty() == true && dest?.isEmpty() == true) {
""
} else if (finalValue in (mMin + 1) until mMax) {
null // keep original
} else {
if ((!TextUtils.isEmpty(source) && source.toString().trim().toInt() < mMin)
&& finalValue < mMax
) {
if (source.toString().toInt() == 0) {
""
} else {
source
}
} else {
""
}
}
}
}

用法:

binding.edtText.filters = arrayOf(InputRangeFilter(5, 100))

好吧,经过测试,我可以让它工作了,下面是代码:

class NumberWatcher(private val mMin: Int, private val mMax: Int)
: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(s:Editable) {
Log.d("TextWatcher","Triggered '$s'")
if (s.isEmpty() || s.toString().toInt() < mMin){
s.replace(0, s.length, mMin.toString())
return //will retrigger after the change, to avoid double excecution
}else if (s.toString().toInt() > mMax){
s.replace(0, s.length, mMax.toString())
return //will retrigger after the change, to avoid double excecution
}
Log.d("TextWatcher","Do some things with '$s'")
//do whatever
}
}

用法:

editText.addTextChangedListener(NumberWatcher(5,50))

日志:

D/TextWatcher: Triggered '45'
D/TextWatcher: Do some things with '45'
D/TextWatcher: Triggered '4'
D/TextWatcher: Triggered '5'
D/TextWatcher: Do some things with '5'
D/TextWatcher: Triggered '95'
D/TextWatcher: Triggered '50'
D/TextWatcher: Do some things with '50'
D/TextWatcher: Triggered '0'
D/TextWatcher: Triggered '5'
D/TextWatcher: Do some things with '5'
D/TextWatcher: Triggered '35'
D/TextWatcher: Do some things with '35'
D/TextWatcher: Triggered ''
D/TextWatcher: Triggered '5'
D/TextWatcher: Do some things with '5'

最新更新