Reputation: 1025
I have a textfield which is databound to a view model like the xml here and I want the UI to update the txtProvider field on click of the cardView. How should I notify the change to the view from my viewmodel?
<layout xmlns:bind="http://schemas.android.com/tools">
<data>
<variable name="viewmodel"
type="io.leapingwolf.myapp.viewmodel.MyViewModel"/>
<variable
name="myModel"
type="io.leapingwolf.myapp.models.MyModel"/>
</data>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/cardView"
app:cardCornerRadius="5dp"
app:cardUseCompatPadding="true"
android:onClick="@{viewmodel.onClickModel}">
<TextView
android:id="@+id/txtProvider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:text="@{myModel.provider}"
android:textColor="@android:color/black"
android:textSize="15sp" />
</android.support.v7.widget.CardView>
</layout>
In MyViewModel(which extends BaseObserver class), I have
fun onClickModel() : View.OnClickListener {
val viewOnClick = View.OnClickListener { v ->
myModel!!.provider = "name changed"
notifyPropertyChanged(BR.myModel)
Toast.makeText(context,"clicked:" + myModel!!.provider , Toast.LENGTH_SHORT).show()}
return viewOnClick
}
My data class :
data class MyModel(
val type: String?,
var provider: String?
) : AutoParcelable
Upvotes: 4
Views: 2951
Reputation: 323
In your MyModel.kt file
class MyModel(
@get:Bindable
var provider: String = ""
) : BaseObservable() {
fun updateText(str:String){
provider = str
notifyPropertyChanged(BR.counter)
}
}
and then in your layout.xml
android:onClick="@{() -> myModel.updateText(`YOUR TEXT`)}"
Rebuild
your project if you cannot get BR.counter
autocomplete working
Upvotes: 1
Reputation: 1025
I got it working in Kotlin using the @Bindable in the viewmodel like below.Took me a while to understand how to use @Bindable in Kotlin syntax. The property BR.provider was not getting generated till i got the @Bindable syntax right.
fun onClickModel(): View.OnClickListener {
val viewOnClick = View.OnClickListener {
route!!.provider = "name changed"
notifyPropertyChanged(BR.provider)
}
return viewOnClick
}
val provider: String
@Bindable
get() {
Log.d("Utils", "get property")
return route!!.provider!!
}
Upvotes: 2
Reputation: 1025
It might be more of a kotlin issue. When I initialise the provider String as ObservableField as
var provider = ObservableField<String>()
init{
provider = route.provider as ObservableField<String>
}
I get an error at runtime java.lang.String cannot be cast to android.databinding.ObservableField
I will try posting it on the kotlin discussion site and seek some answers.
Upvotes: 0
Reputation: 5517
I'll use a java syntax, because I'm not that fluent with kotlin:
You need to declare your MyModel
or the provider
with DataBinding
to enable the binding. Use a @Bindable
on getter, and call notifyPropertyChanged
in the setter:
@Bindable
public String getProvider() {
return this.provider;
}
public void setProvider(String provider) {
this.lastName = lastName;
notifyPropertyChanged(BR.provider);
}
or make your MyModel
extend BaseObservable
, or since you have a viewmodel, create a ObservableField<String>
or even a ObservableField<MyModel>
:
//in your viewmodel:
private ObservableField<MyModel> modelField = new ObservableField<MyModel>();
Set the value in the constructor of your viewmodel, create a getter and reference this in your xml
.
Upvotes: 1