android - 如何使用双向数据绑定(bind)更新 RecyclerView 中所有 EditTexts 元素的文本

标签 android kotlin android-recyclerview android-edittext two-way-binding

我有一个 回收站查看 其中包含一些 CardViews 和每个 卡片查看 包含 编辑文本 它将用户给定数量乘以特定速率(速率来自端点,每行的速率不同)。对于 CardViews 我正在使用数据绑定(bind)。
应用程序用例:
该应用程序应显示其他货币的金额,例如 2、7.89、14.34 或 110 欧元。

  • 用户输入 金额 (在 EditText 中)在任何行中,每一行都有一个“ rate ”(rate 来自 API 端点)字段,其值不同
  • 用户输入金额 乘以“
  • 中的每一行回收站查看 应该更新

  • 现在的问题是如何更新 中所有 EditTexts 元素的文本。回收站查看 双向数据绑定(bind)
    这是我用于数据绑定(bind)的数据类:
    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)
            }
    
    }
    
    这是我在 item_currency.xml 中的 EditText
    <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" />
    
    这是我的申请 存储用户输入金额的类:
    class CurrencyApplication : Application() {
    
        companion object {
            var userEnteredAmount: Double = 1.00
        }
    
    }
    
    在这里我访问 回收站查看 通过 Kotlin Android 扩展:
    recycler_view.apply {
                setHasFixedSize(true)
                itemAnimator = DefaultItemAnimator()
                adapter = currencyAdapter
            }
    
    这里是 回收站查看 来自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" />
    
    这里是 适配器 对于回收站查看 :
    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)
    

    最佳答案

    您可能想要创建另一个 Observable在 -say- 您的 viewModel 或适配器中,并将其作为变量绑定(bind)到适配器项。
    像这样:

    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)
        }
    
    }
    
    如果您遇到其他 View 急切更新速率变量的问题,请尝试制作自定义数据绑定(bind)适配器以仅允许 View 在焦点处于焦点时触发更新。
    @BindingAdapter("android:textAttrChanged")
    fun TextView.setOnTextAttrChangedInFocus(listener: InverseBindingListener) {
        addTextChangedListener(afterTextChanged = {
            if(isFocused) {
                listener.onChange()
            }
        })
    }
    
    (示例使用 androidx.core 扩展名)
    我希望它有帮助;)

    查看 teanity它可能会帮助您更快地找出类似的东西。

    关于android - 如何使用双向数据绑定(bind)更新 RecyclerView 中所有 EditTexts 元素的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62855700/

    相关文章:

    android - 在 Staggered Recyclerview 中显示类似结构的标签

    android - 从对话框更新 RecyclerView

    java - 将选定的对象传递给另一个 Activity

    java - 向 View 添加圆角?

    android - 使用 kotlin co 例程从单个函数返回多次

    java - 使用 Kotlin 时出现“java.lang.NumberFormatException : Invalid double' for European languages,”

    android - 为什么推送通知服务器准确地向客户端发送消息

    android - 使用 AChartEngine 时,X 轴上的某些标签会出现乱码(困惑)

    gradle - 如何使用Kotlin,Gradle和Web框架设置Spring Loaded?

    android - 扩展 RecyclerView : Error Inflating Class com. example.MyRecyclerView