DataBinding:在点击时通过 LiveData 变量调整可见性

Posted

技术标签:

【中文标题】DataBinding:在点击时通过 LiveData 变量调整可见性【英文标题】:DataBinding: Adjust visibility by LiveData Variable on Click 【发布时间】:2019-06-19 07:07:15 【问题描述】:

我想根据ViewModel 中的MutableLiveData 变量调整ProgressBar 的可见性。我了解到 MutableLiveData 不起作用,所以我需要一个 LiveData 变量来转换它...有点奇怪,但至少它应该可以正常工作吗?

好吧,它目前不起作用。而且我不明白为什么我想让两个变量做一件事。

我希望代码不言自明:

活动:

override fun onCreate(savedInstanceState: Bundle?) 
    super.onCreate(savedInstanceState)
    val binding: ActivityLoginBinding = DataBindingUtil.setContentView(this, R.layout.activity_login)
    binding.lifecycleOwner = this
    binding.viewmodel = vm

查看模型:

class LoginViewModel : ViewModel() 
    var isLoading: MutableLiveData<Boolean> = MutableLiveData(false)
    var showLoadingIndicator: LiveData<Boolean> = Transformations.map(isLoading)  isLoading.value 

    fun login() 
        Timber.d("login")
        isLoading.value = true
    

布局:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
                name="viewmodel"
                type="mypackage.LoginViewModel"/>
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout>

        <com.google.android.material.button.MaterialButton        
                android:onClick="@() -> viewmodel.login()"/>

        <include
                layout="@layout/loading_indicator"
                app:goneUnless="@viewmodel.showLoadingIndicator"/>
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

BindingAdapter:

@Suppress("unused")
object BindingAdapters 
    @BindingAdapter("goneUnless")
    @JvmStatic
    fun goneUnless(view: View, visible: Boolean) 
        view.visibility = if (visible) View.VISIBLE else View.GONE
    

当我单击Button 时,Timber 调用有效,但加载指示器的可见性没有改变(从GONEVISIBLE)。我该如何解决这个问题,也许可以摆脱这两个变量而只有一个?

谢谢。

【问题讨论】:

【参考方案1】:

您实际上并不需要BindingAdapter,有一种更简单的方法可以完成您想要的。

1) ViewModel:将加载字段更改为:val isLoading = ObservableBoolean() OR val isLoading = MutableLiveData&lt;Boolean&gt;*

2) 在布局的&lt;data&gt; 标签内添加导入:&lt;import type="android.view.View"/&gt;

3) 您的包含将变为:

<include
   layout="@layout/loading_indicator"
   android:visibility="@viewmodel.isLoading ? View.VISIBLE : View.GONE"/>

使用set(value) 更改LiveDataObservableBooleansetValue()(如果您不在主线程,则为postValue())的值。

*公开LiveData 实例并保持实际MutableLiveData 私有是一种很好的做法。

【讨论】:

它有点工作。 include tho 我没有成功。但是当我直接添加Progressbar 时,它可以工作。我可能在包含的布局中搞砸了一些东西。非常感谢!它甚至适用于BindingAdapter:) ObservableBoolean 为我做到了。 您是否希望根据 LiveData 添加您的答案,因为建议用实时数据替换 observable 字段 无法识别 VISIBLE @ThiệnKopites 您必须在布局文件的 块中添加 &lt;import type="android.view.View"/&gt; @chrjs 给包含的布局一个 id 否则它将无法工作,即 【参考方案2】:

这对我很有用:

@BindingAdapter("android:visibility")
fun View.setVisibility(visible: Boolean?) 
    visibility = if (visible != null && visible) View.VISIBLE else View.GONE

【讨论】:

以上是关于DataBinding:在点击时通过 LiveData 变量调整可见性的主要内容,如果未能解决你的问题,请参考以下文章

我们为什么要使用 DataBinding

[Android DataBinding] 找不到符号 import com.xxx.databindingdemo.databinding.ActivityMainBindingImpl

WinForms dataBinding 触发 2 次 CheckedChanged 事件,使 checkBox 不可点击

Android:如何使用 dataBinding 在同一个 TextView 中显示多个值?

Android的DataBinding原理

wpf DataBinding