問題描述
我已經研究過使用 TextWatcher
和 InputFilter
,但我不太確定如何解決這個問題.
I've looked into using a TextWatcher
and an InputFilter
, but I'm not too sure how to approach this problem.
這個想法是有一個 EditText
從右到左插入文本.隨著使用輸入的變化,我希望發生以下情況.
The idea is to have an EditText
that inserts text from right to left. As the use input changes, I would like the following to occur.
- User enters "1" -> Text formats as 00:01
- User enters "2" -> Text formats as 00:12
- User enters "8" -> Text formats as 01:28
我該如何處理?Inputfilter
似乎用于排除文本并在 TextWatcher
內使用 setText
似乎在無限循環中運行.
How could I approach this? Inputfilter
seems to be for excluding text and using setText
inside the TextWatcher
appears to run in an endless loop.
推薦答案
所以我昨天想出了一個相當不錯的解決方案.
So I came up with a pretty decent solution yesterday.
我使用了兩個編輯文本和一個文本視圖.我在約束布局中對齊它們
I used two edit texts and a text view. I Aligned them within a constraint layout
<TextView
android:id="@+id/colon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text=":"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="@+id/hoursInput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:inputType="number"
android:maxLength="3"
android:text="00"
app:layout_constraintBottom_toBottomOf="@id/colon"
app:layout_constraintEnd_toStartOf="@id/colon"
app:layout_constraintTop_toTopOf="@id/colon"
app:layout_constraintVertical_bias="0.0" />
<EditText
android:id="@+id/minutesInput"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:inputType="number"
android:maxLength="3"
android:text="00"
app:layout_constraintBottom_toBottomOf="@id/colon"
app:layout_constraintStart_toEndOf="@id/colon"
app:layout_constraintTop_toTopOf="@id/colon" />
因為我只想使用數字,所以我不得不使用文本視圖來表示冒號.修改了每個輸入的文本觀察器.我利用字符串大小來確定何時完全更新文本,并使用 onTextChanged
強制字符串始終為最小大小 2 - 小時和分鐘看起來完全相同,除了枚舉/光標位置.字段本身將允許在光標位置輸入第三個數字.因此,帶有12"的字段將變為123",然后觸發更新時間,這會確定我們是否需要在其他位置設置文本,或者拒絕數字,或者需要任何自定義邏輯.
Since I only wanted to use numbers so I had to use a text view to represent the colon. modified the Text watcher for each input. I leveraged the string size in determining when to update the text entirely, and used onTextChanged
to force the string to always be at minimum size 2 - Both the hours and minutes look exactly the same, with the exception of the enum/cursor position. The fields themselves would allow for a third digit to be enterd at the cursor position. So a fiel with "12" would turn into "123" and then trigger update time, which figures out if we need to set text else where, or reject the number, or whatever custom logic is required.
addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
if (s != null && s.toString().length > 2)
//I used an ENUM to tell my update time function which view I was in. More to come. Cusor position is set in the keylistener
updateTime(s.toString, hoursInput.text, cursorPosition, Field.MINUTES)
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
if (s != null && s.length < 2)
StringBuilder(s).apply { this.insert(0, "0") }.toString().also {
minutesInput.setText(it)
}
}
})
我還添加了一個 onKeyListener 來監視刪除鍵,專門用于實現自定義邏輯.但在它返回按下鍵的結果之前,我會跟蹤每個事件的 keydown 上的光標位置.分鐘和小時輸入看起來相同/相似.
I also added an onKeyListener to watch the delete key specifically to implement custom logic. But before it would return the result of the key pressed, i'd track the cursor position on keydown for every event. Both minutes and Hours inputs look the same/similar.
setOnKeyListener { _, keyCode, keyEvent ->
if (keyEvent.action == KeyEvent.ACTION_DOWN) cursorPosition = selectionStart
(keyCode == KeyEvent.KEYCODE_DEL && keyEvent.action == KeyEvent.ACTION_DOWN && selectionStart == selectionEnd && selectionStart != 0).also { performDelete ->
if (performDelete) Logic.deleteTime(minutesInputString, minutesInput.text, cursorPosition, Field.Minutes)
}
}
最后,我有我的邏輯類,我實際上執行了字符串操作.
Finally, I have my Logic class which I actually performed the string manipulation.
// Inside update/delete I convert the strings into a string that is like 00129 and use the cursorPosition/Field enum to determine where to add text.
Logic.updateTime(minutesInputString, hoursInputString, cursorPosition, Field) : String[]
Logic.deleteTime(minutesInputString, hoursInputString, cursorPosition, Field): String[]
然后我立即使用輸入設置時間.
I then set the time immediately with the inputs.
updateTime(mins, hours, position, Field.MINUTES).also{
// ("00", "129", 2, Minutes) returns as ["01", "29"]
minutesInput.setText(it[0])
minutesInput.setText(it[1])
}
仍在解決的復雜問題,但這就是我解決它的方法.實施這個解決方案花了我 4 個小時,我已經轉動了將近三天的輪子!
Complicated problem that is still being worked on, but this is how I've solved it. Implementing this solution took me 4 hours where I had spun my wheels for nearly three days!
這篇關于android 的 EditText 的動態前導文本的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!