Android的EditText的动态前导文本 [英] Dynamic leading text for android's EditText

查看:122
本文介绍了Android的EditText的动态前导文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经研究过使用TextWatcherInputFilter,但是我不太确定如何解决这个问题.

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

最后,我有了我的Logic类,我实际上执行了字符串操作.

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个小时的时间,将车轮旋转了将近3天!

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的动态前导文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆