Android Data Binding different icon based on different states - android

Iv'e got a recyclerView with items using databinding.
The model contains multiple values that together determine the icon/state of the list item.
so i tried to add a variable to the XML that contains a helper function to return a R.drawable that needs to be shown based on different values in the model
ListItem.xml
<data>
<import type="android.view.View"/>
<variable name="model" type="com.example.model"></variable>
<variable name="helper" type="com.example.helper"></variable>
</data>
...
<TextView ...
android:text="#{model.a}" /> <<< THIS UPDATES LIKE EXPECTED
<ImageView ...
app:imageResource="#{helper.getIcon(model)}"/> <<< THIS IS NOT UPDATING AFTER THE VALUES CHANGES
...
helper.kt
fun getIcon(model:Model){
return if(model.a == true){
if(model.b == true){
R.drawable.b
}else{
R.drawable.a
}
}else{
R.drawable.c
}
}
if the model values changes the getIcon is not triggered. (only when i scroll up and down)

Related

LiveData only triggered on orientation change

I have a MutableLiveData variable displayText, which is the text for a TextView, set through data binding
The code:
vm.displayTextValue.value = "New Value"//code for updating
binding.setViewModel(/* ViewModel variable*/)//set data variable in the Fragment
<layout>
<data>
<variable
name="viewModel"
type="com.myapp.theViewModel"/>
<TextView
android:text="#{viewModel.displayTextValue}" />
</layout>
Somehow, the text of the TextView only changes on orientation change, but does not change when the variable is changed. Why?

Identifiers must have user defined types from the XML file, databinding with observablefield

I want my view visibility to be dependent on condition behaviour so I am using ObservableField and with databinding trying to change view visibility but getting issue like "Identifiers must have user defined types from the XML file. InputType is missing it"
Code:
Kotlin File
var showView: ObservableField<Boolean>? = ObservableField(false)
//API call response
showView.set(true)
Layout File:
<TextView
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="#{viewModel.showView ? View.VISIBLE : View.GONE}"/>
How to apply databinding with Observablefield of type boolean? I have used it for string text also and it's working but not working with boolean conditional statement.
I am not sure if that's the case here, but this error message is usually displayed when you reference a type in your binding expressions that hasn't been declared in the <data> section of your layout. The same way you declare the View type as an import, you should declare the type InputType.
<data>
<!-- Maybe an import for InputType is missing here? -->
<import type="android.view.View" />
<variable
name="viewModel"
type="com.yourpackage.YourViewModel"/>
</data>

How to hide button in landscape mode when using Databinding

I have a view that uses DataBinding to display data from a ViewModel. The view has a button that is hidden when the view is in landscape mode. At the moment this works by having two layoutfiles, but I would like to only have one as it's a nightmare to refactor. But how to go about this using DataBinding and BindingAdapters?
How do you enable the following bindingexpression for a given view?
android:visibility="#{isLandscapeMode ? View.INVISIBLE : View.VISIBLE}"
EDIT:
My extension property definition (ViewUtils.kt):
val View.isLandscapeMode: Boolean
get() = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
And my layout:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View"/>
<import type="com.example.base.views.ViewUtilsKt" />
<variable
name="isLandscapeMode "
type="java.lang.Boolean"/>
<variable
name="viewmodel"
type="com.example.ui.task.TaskViewModel" />
</data>
...
<ImageButton
...
android:visibility="#{isLandscapeMode ? View.INVISIBLE : View.VISIBLE}"
...
/>
This causes a compile error: Cause: not a valid name: isLandscapeMode
You have to check in your binding adapter which phone orientation is currently on. Here is another post where you can find answer to your question how to detect orientation of android device?
EDIT:
You need to detect orientation and save it as boolean value. Later you have to pass that variable to your adapter which in this case will be boolean.
<data>
<import type="android.view.View"/>
<variable
name="isLandscapeMode"
type="boolean"/>
</data>
For others if they need same behavior. There are two solutions.
First solution (create a BindingAdapter and use it on the UI element of your choice):
#BindingAdapter("bind:visibleInLandscapeMode")
fun View.setVisibleInLandscapeMode(visible: Boolean) {
Timber.d("setVisibleInLandscapeMode() returns ${resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE}")
visibility = if (visible && (resources.configuration.orientation != Configuration.ORIENTATION_LANDSCAPE)) VISIBLE else INVISIBLE
}
In your XML layout:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:bind="http://schemas.android.com/apk/lib/com.example">
...
<ImageButton
...
bind:visibleInLandscapeMode="false"
...
/>
Second solution (create a bindingexpression that changes the visibility of the UI element):
<ImageButton
...
android:visibility="#{context.getResources.getConfiguration.orientation == Configuration.ORIENTATION_LANDSCAPE ? View.INVISIBLE : View.VISIBLE}"
...
/>
Remember the correct imports:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View"/>
<import type="android.content.res.Resources" />
<import type="android.content.res.Configuration" />
...
</data>
...
Btw. be careful when using Databinding with AndroidAnnotation. See issue here and here.

Cannot set string array for spinner using Android data binding

I have a spinner now and I want to load the data to the spinner with data binding feature. I tried to find the way to declare the string array in the XML(https://developer.android.com/topic/libraries/data-binding/index.html#expression_language) but no satisfied result is found.
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:apps="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.util.SparseArray"/>
<variable
name="statuslist"
type="SparseArray<String>"/>
</data>
...
<android.support.v7.widget.AppCompatSpinner
android:id="#+id/spn_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignStart="#+id/spinner1"
android:layout_below="#+id/btn2"
android:entries="#{statuslist}"
apps:adapter="#{statusAdapter}"/>
</layout>
When it is build, the following error is shown.
Error:Execution failed for task ':app:dataBindingProcessLayoutsDebug'.
org.xml.sax.SAXParseException; systemId: file:/C:/Users/../app/build/intermediates/res/merged/debug/layout/testdialog.xml; lineNumber: 24; columnNumber: 30; The value of attribute "type" associated with an element type "null" must not contain the '<' character.
However, there is something confused.
When I tried to use SparseArray as shown on website. I found a "Cannot resolve sysmbol" in Android Studio XML Editor.
I do not know is it the correct way to setup the array value for the spinner since there is no official instructions for the spinner data bindingin the website.
have you import the SparseArray ?
try this :
<data><import type="android.util.SparseArray"/></data>
This is a very simple way to setup a spinner with a string-array from your resource's array.xml
<Spinner
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:entries="#array/spinner_array_items"/>
The spinner_array_items should contain a list of items to be found in the spinner dropdown.
Change SparseArray<String> to SparseArray<String>.
Well my implementation logic is based on your's but used ArrayList instead SparseArray.
XML:
<data>
<import type="java.util.ArrayList" />
<variable
name="cities"
type="ArrayList<String>"
/>
</data>
<!-- Location -->
<Spinner
android:id="#+id/dd_city"
android:entries="#{cities}"
style="#style/dropdown"
/>
Now, we just need to bind our ArrayList to cities variable through Binding Class.
At least data will be bind : ).
TC.

Visibility not working in data binding android

I am using the latest data binding in android using android studio 2.1.
using the visibility tag as describe in the below code getting an error as
java.lang.RuntimeException: Found data binding errors.
/ data binding error ****msg:Identifiers must have user defined types from the XML file. View is missing it
file:D:\HP\HealthPortal_Android\Code\app\src\main\res\layout\cardview_image_twotextview.xml
loc:68:90 - 68:93
\ data binding error
<TextView
android:id="#+id/card_sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/card_title"
android:layout_marginLeft="#dimen/carview_margin"
android:layout_toRightOf="#+id/card_image"
android:text="#{toolsAndTrackersCards.subtitle}"
android:textColor="#color/black"
android:textSize="20sp"
android:visibility="#{toolsAndTrackersCards.subtitle.equals(#string/Empty_String) ? View.VISIBLE : View.GONE}"
/>
Done some google not abel to find the solution. The #string/Empty_String is define as empty string "" in string.xml file. where I am doing wrong.
Android data binding, Radio Button not updating
Add this to your cardview_image_twotextview.xml:
<data>
<import type="android.view.View" />
<!--your variables-->
</data>
To hide a view if the string is empty, use the below expression in data binding
<data>
<import type="android.view.View"/>
<variable
name="item"
type="com.test.model.Item" />
</data>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{item.title}"
android:visibility='#{item.title.equals("") ? View.GONE : View.VISIBLE}'/>
NOTE: need to use outer single quote string in order to use double quote to
represent the empty string
If you want to check for null and empty, use the below code :
<data>
<import type="android.view.View"/>
<import type="android.text.TextUtils"/>
<variable
name="item"
type="com.test.model.Item" />
</data>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{item.title}"
android:visibility="#{TextUtils.isEmpty(item.title) ? View.GONE : View.VISIBLE}"/>
Zero or more import elements may be used inside the data element.
These allow easy reference to classes inside your layout file, just
like in Java.
you need to import View class inorder to use its properties.
<data>
<import type="android.view.View"/>
</data>
you can also refer official DataBinding guideline.

Categories

Resources