I'm trying to assign a behavior different than the standard one when my swipelayout is refreshed:
This is my code:
binding.refreshed = binding.refreshOtrosRequestList
binding.refreshOtrosRequestList!!.setOnRefreshListener(SwipeRefreshLayout.OnRefreshListener {
[Change behavior]
})
These are the elements I'm using defined in the corresponding XML file:
<data>
<variable name="refreshed" type="androidx.swiperefreshlayout.widget.SwipeRefreshLayout"/>
</data>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="#+id/refreshOtrosRequestList"
app:onRefreshListener="#{() -> model.onRefresh(refreshed)}"
android:layout_width="wrap_content"
android:layout_height="match_parent">
But the defined setOnRefreshListener never fires:
What am I doing wrong?
PD: this is request, also in data in XML file:
<data>
<variable name="model" type="es.nscontrol.controlpresencial.viewmodels.NonWorkingDateViewModel"/>
<variable name="refreshed" type="androidx.swiperefreshlayout.widget.SwipeRefreshLayout"/>
</data>
What is "model"?
model.onRefresh(refreshed)
Is it somewhere defined?
Additionally, it looks strange when you use databiding to store view from this layout in a variable.
Edit:
I hope you also binded this "model" to the actual variable as you did with
binding.refreshed = binding.refreshOtrosRequestList
And invoke this after you binded these variables:
binding.executePendingBindings()
Related
Code A can work well, I don't know why Code b can't work, could you tell me ?
Code A
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="androidx.lifecycle.LiveData" />
<variable
name="MyValue1"
type="LiveData<Integer>" />
</data>
...
Code B
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="androidx.lifecycle.LiveData" />
<variable
name="MyValue2"
type="LiveData<Int>" />
</data>
...
Because Int is not part of Expression language for data binding
can not assign the Java's primitive type to LiveData
class of Int is not available on Java but Kotlin does
class of Integer is available on Java but Kotlin doesn't
class of Int on Kotlin is not a primitive type, this is a wrapper class for int so we can assign Int type to LiveData
As i'm new to data-binding, can Anyone help to fix this.
Here is my Fragment
Here is my Layout
Here is my gradle
Here is my ViewModel
Change the variable name of your LoginViewModel from data to viewModel.
For Example:
<data>
<variable name="viewModel" type="com.xxx.yyy.ui.login.LoginViewModel" />
</data>
After that Rebuild your project
in databinding of android simply i want to control view visibility by checking viewmodel parameter as profilePicUrl
Solution 1:
when profilePicUrl is empty view should be gone, otherwise that should be visible, for example:
<data>
<import type="android.view.View"/>
<import type="android.text.TextUtils"/>
<variable name="viewModel" type="xx.xxxxx.xxxxxxx.MyViewModel"/>
</data>
...
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="#{TextUtils.isEmpty(viewModel.profilePicUrl) ? View.GONE : View.VISIBLE}"
>
i get this error:
error: '#{TextUtils.isEmpty(viewModel.profilePicUrl)? View.GONE : View.VISIBLE' is incompatible with attribute visibility (attr) enum [gone=2, invisible=1, visible=0].
Solution 2:
after getting this error i try to test another solution to approach that, for example:
BindingAdapters class:
object BindingAdapters {
#BindingAdapter("visibleIf")
#JvmStatic
fun changeVisibility(#NonNull imageView: ImageView, visible: Boolean) {
if (visible) {
imageView.visibility = View.VISIBLE
} else {
imageView.visibility = View.GONE
}
}
}
xml layout:
<data>
<import type="android.view.View"/>
<import type="android.text.TextUtils"/>
<variable name="viewModel" type="xx.xxxxx.xxxxxxx.MyViewModel"/>
</data>
...
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:visibleIf="#{TextUtils.isEmpty(viewModel.profilePicUrl)}"
>
i get this error:
error: attribute visibleIf (aka xxx.xxxxx.xxxxxxxx:visibleIf) not found.
Are you sure you have enabled data-binding properly? Your code is correct, so there is no reason why it shouldn't work.
Please make sure this code is added in the Gradle file of your app module:
dataBinding {
enabled = true
}
In addition, I would recommend adding this to the gradle.properties file:
android.databinding.enableV2=true
Here you can see a similar question.
Regarding the second solution, sometimes importing the object that contains the adapter methods helps:
<import type="com.your.package.name.BindingAdapters" />
Also, please make sure you have added this attribute on your layout tag:
xmlns:app="http://schemas.android.com/apk/res-auto"
I'm trying to set an OnClickListener for an <include>d layout, but receive a data binding error at compile time stating that data binding "Cannot find the setter for attribute 'android:onClick' with parameter type android.view.View.OnClickListener".
Context here is that I'm using data binding to inflate the included layout, so that I can pass values into it from a viewModel that I've bound to the including layout.
I've tried various syntax for the data binding expression:
#{viewModel::onClickFunction}
#{viewModel.onClickFunction}
#{() -> viewModel.onClickFunction()}
#{(view) -> viewModel.onClickFunction()}
#{_ -> viewModel.onClickFunction()}
I've tried all of the above with onClickFunction as a function, and also as an OnClickListener object.
Other related questions on Stack Overflow seem to solve this issue by cleaning the project to regenerate the databinding files, but that hasn't worked for me.
Relevant code snippets below:
viewModel
class MyViewModel() {
val onClickFunctionAsAListener: OnClickListener = object:OnClickListener{
override fun onClick(v: View?) {
//Do something
}
}
fun onClickFunction() {
//Do something
}
}
Including layout
<layout>
<data>
<variable name="viewModel" type="full.package.name.MyViewModel"/>
</data>
<LinearLayout>
<include
layout="#layout/included_layout"
android:onClick="#{viewModel.onClickListener}"
app:customAttribute="#{`someText`}/>
</LinearLayout>
</layout>
Included layout
<layout>
<data>
<variable name="customAttribute" type="String"/>
</data>
<TextView
layout="#layout/included_layout"
android:text="#{customAttribute}"/>
</layout>
It seems that you can't actually assign an OnClick handler to an <include> tag directly. I managed to get it to work by adding another variable to IncludedLayouts data binding class, and then assigning the OnClickListener to IncudedLayouts root view in XML.
After the changes, my files looked like this:
viewModel
class MyViewModel() {
val onClickFunction: OnClickListener = object:OnClickListener{
override fun onClick(v: View?) {
//Do something
}
}
}
Including layout
<layout>
<data>
<variable name="viewModel" type="full.package.name.MyViewModel"/>
</data>
<LinearLayout>
<include
layout="#layout/included_layout"
app:onClick="#{viewModel.onClickListener}"
app:customAttribute="#{`someText`}/>
</LinearLayout>
</layout>
Included layout
<layout>
<data>
<variable name="customAttribute" type="String"/>
<variable name="onClick" type="android.view.View.OnClickListener"/>
</data>
<TextView
layout="#layout/included_layout"
android:text="#{customAttribute}"
android:onClick="#{onClick}"/>
</layout>
include tag does not support onClick method directly. While the selected answer is correct, instead of passing onClickLister to include layout (or having custom #BindingAdapter, which is also another solution), I would just wrap my include inside a ViewGroup and onClick on ViewGroup.
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="#{()-> viewModel.yourFunction()}">
<include layout="#layout/custom_layout"/>
It's a workaround, but works as charm.
How to define a generic type of a data binding variable?
The following code never compiles.
<data>
<variable
name="viewModel"
type="com.example.viewmodel.ViewModel<Model>"/>
</data>
You need to escape <Model> as shown below:
<data>
<variable
name="viewModel"
type="com.example.viewmodel.ViewModel<Model>"/>
</data>
Android Studio will still show a "Cannot resolve symbol" error, but the XML will compile. It is a known issue. From Android Studio Support for Data Binding:
Note: Arrays and generic types, such as the Observable class, might display errors when there are no errors.
Try this one:
<data>
<variable
name="viewModel"
type="com.example.viewmodel.ViewModel<Model>"/>
</data>
< is responsible for < and > is responsible for >.
You can set something like examples above:
<data>
<import type="com.example.path.Model"/>
<variable
name="obj"
type="com.example.viewmodel.ViewModel<Model>"
/>
</data>
NOTE: you can write '>' or '>' at end of Model should be OK
To avoid error display do not forget to add line to tell what object type is used:
<import type="com.example.path.Model"/>
You have a left triangle bracket in XML; XML don't play that way. try
<data>
<variable
name="viewModel"
type="com.example.viewmodel.ViewModel<Model>"/>
</data>