Как обновить текст всех элементов EditTexts в RecyclerView с двусторонней привязкой данных - PullRequest
14 голосов
/ 12 июля 2020

У меня есть RecyclerView , который содержит некоторые CardViews , и каждый CardView содержит EditText , который умножает пользователя задано количество , умноженное на c скорость (скорость исходит от конечной точки, и скорость отличается для каждой строки). Для CardViews я использую привязку данных.

Пример использования приложения:

Приложение должно показать, сколько, например, 2, 7,89, 14,34 или 110 € указаны в других валютах.

  1. Пользователь вводит количество EditText ) в любой строке, каждая строка имеет " курс"(скорость поступает из конечной точки API) с другим значением
  2. Пользователь, введенный сумма , умножается на" ставка"
  3. Каждая строка в RecyclerView должна быть обновлена ​​

Теперь возникает вопрос, как обновить текст всех элементов EditTexts в RecyclerView с двусторонними данными привязка

Это мой класс данных для привязки данных:

data class CurrencyItem(
    var flag: String,
    var shortName: String,
    var fullName: String,
    var rate: Double
) : BaseObservable() {

    @Bindable
    var rateTimesAmount: String = (CurrencyApplication.userEnteredAmount * rate).toString()
        set(amount) {
            val amountAsDouble = amount.toDouble()
            val number2digits: Double = String.format("%.2f", amountAsDouble).toDouble()
            CurrencyApplication.userEnteredAmount = number2digits
            field = number2digits.toString()
            notifyPropertyChanged(BR.rateTimesAmount)
        }

}

Это мой EditText в item_currency. xml

<EditText
                android:id="@+id/currency_rate"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginEnd="16dp"
                android:imeOptions="actionDone"
                android:inputType="numberDecimal"
                android:lines="1"
                android:maxLength="8"
                android:text="@={currency.rateTimesAmount}"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                tools:text="1183.068" />

Это мой Application класс, в котором хранится введенное пользователем количество:

class CurrencyApplication : Application() {

    companion object {
        var userEnteredAmount: Double = 1.00
    }

}

Здесь я получаю доступ к RecyclerView через Kotlin Android Extension s:

recycler_view.apply {
            setHasFixedSize(true)
            itemAnimator = DefaultItemAnimator()
            adapter = currencyAdapter
        }

Вот RecyclerView из activity_main. xml

<androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_margin="8dp"
        android:clipToPadding="false"
        android:paddingBottom="8dp"
        android:scrollbars="vertical"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

Вот Адаптер для RecyclerView :

class CurrencyAdapter(
    val currencies: ArrayList<CurrencyItem>
) : RecyclerView.Adapter<CurrencyViewHolder>() {
    
    override fun getItemCount() = currencies.size

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): CurrencyViewHolder {
        val itemCurrencyBinding: ItemCurrencyBinding = DataBindingUtil.inflate(
            LayoutInflater.from(parent.context),
            R.layout.item_currency,
            parent,
            false
        )
        return CurrencyViewHolder(itemCurrencyBinding)
    }

    override fun onBindViewHolder(holder: CurrencyViewHolder, position: Int) {
        holder.itemCurrencyBinding.currency = currencies[position]
    }

    fun setUpCurrencies(newCurrencies: List<CurrencyItem>) {
        currencies.clear()
        currencies.addAll(newCurrencies)
        notifyDataSetChanged()
    }
}

class CurrencyViewHolder(val itemCurrencyBinding: ItemCurrencyBinding) :
    RecyclerView.ViewHolder(itemCurrencyBinding.root)

1 Ответ

0 голосов
/ 13 июля 2020

Возможно, вы захотите создать еще Observable в -say- вашей viewModel или адаптере и привязать его как переменную к элементам адаптера.

Примерно так:

class CurrencyAdapter: RecyclerView.Adapter<...>() {

    val rate = ObservableField(0.0)

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = DataBindingUtil.inflate<ViewDataBinding>(inflater, viewType, parent, false)
        binding.setVariable(BR.rate, rate)
        return YourViewHolder(binding.root)
    }

}

Если у вас возникнут проблемы с другими представлениями, которые с нетерпением обновляют переменную скорости, попробуйте создать настраиваемый адаптер привязки данных, чтобы позволить представления, запускающие обновления, только когда они находятся в фокусе.

@BindingAdapter("android:textAttrChanged")
fun TextView.setOnTextAttrChangedInFocus(listener: InverseBindingListener) {
    addTextChangedListener(afterTextChanged = {
        if(isFocused) {
            listener.onChange()
        }
    })
}

(в примере используется androidx .core extension)

Надеюсь, поможет;)

Проверьте teanity , это может помочь вам быстрее разобраться в подобных вещах.

...