Dynami c начальный текст для android EditText - PullRequest
0 голосов
/ 25 марта 2020

Я рассмотрел использование TextWatcher и InputFilter, но я не слишком уверен, как решить эту проблему.

Идея состоит в том, чтобы EditText вставлял текст справа налево. По мере изменения входных данных, я хотел бы, чтобы произошло следующее.

- 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, по-видимому, предназначен для исключения текста, а использование setText внутри TextWatcher, по-видимому, работает в бесконечном l oop.

Ответы [ 2 ]

1 голос
/ 25 марта 2020

Попробуйте это:

activity_main. xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <EditText
        android:id="@+id/edittext"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25dp"
        android:padding="20dp"
        android:inputType="number"
        android:maxLength="4"/>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textview"
        android:textSize="25dp"
        android:padding="20dp"/>

</LinearLayout>

MainActivity.kt

import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        edittext.addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable) {}
            override fun beforeTextChanged(s: CharSequence, start: Int,
                                           count: Int, after: Int) {
            }
            override fun onTextChanged(s: CharSequence, start: Int,
                                       before: Int, count: Int) {
                if (s.length<5){
                    var a=""
                    var i=4-s.length
                    var j=0
                    while (j<i){
                        a+="0"
                        j++
                    }
                    var b=a+s
                    b = b.substring(0, 2) + ":" + b.substring(2, b.length)
                textview.setText(b)}
            }
        })
    }
}
0 голосов
/ 27 марта 2020

Итак, я вчера нашел довольно приличное решение.

Я использовал два текста для редактирования и текстовое представление. Я выровнял их в макете ограничения

        <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. И часы, и минуты выглядят одинаково, за исключением позиции enum / курсор , Сами поля позволят ввести третий ди git в позиции курсора. Таким образом, поле с «12» превратится в «123», а затем запустит время обновления, которое выясняет, нужно ли нам устанавливать текст где-либо еще, или отклонять число, или какой-либо другой требуемый лог c.

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 для наблюдения за ключом удаления, специально предназначенного для реализации пользовательских логи c. Но прежде чем он вернет результат нажатия клавиши, я бы отслеживал положение курсора при нажатии клавиши для каждого события. Входы минут и часов выглядят одинаково / одинаково.

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

Наконец, у меня есть класс Logi c, который я фактически выполнял для работы со строками.

// 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[]

Затем я сразу установил время с помощью входов.

updateTime(mins, hours, position, Field.MINUTES).also{ 
    // ("00", "129", 2, Minutes) returns as ["01", "29"] 
    minutesInput.setText(it[0])
    minutesInput.setText(it[1])
}

Сложная проблема, над которой все еще ведется работа, но так я ее решил. Внедрение этого решения заняло у меня 4 часа, когда я крутил колеса почти три дня!

...