Android Databinding default variable value - android

I have this layout.
<data>
<import type="android.view.View" />
<variable
name="shouldBeVisible"
type="java.lang.Boolean" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CheckBox
android:id="#+id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="#={shouldBeVisible}" />
<LinearLayout
android:layout_width="40dp"
android:layout_height="30dp"
android:background="#dd0"
android:visibility="#{shouldBeVisible ? View.VISIBLE : View.GONE}" />
</LinearLayout>
shouldBeVisible is by default false. Is there a way to make shouldBeVisible true? I want to have LinearLayout visible in this one case.
So far I'm using binding.shouldBeVisible=true

To solve that error you can use several ways:
You can use primitive boolean type with inverted logic (shouldBeVisible -> shouldBeHidden)
Second way is to use boxed Boolean type (as you have now) and set default value in expressions
Third way - manually set it after inflating of binding (as you already do now)
binding.shouldBeVisible=true
Use default keyword in databining value
Choose the one best fits your needs.

Related

How to set a layout default value from parent layout using databinding and <include> tag in order to see it in preview?

I'm trying to use a view with databinding using the include tag multiple times.
It works great when the app runs, but in preview I don't manage to make it work in the parent.
Instead, I can do it on the view itself, but it implies that if I use it 5 times in the same layout, I'll have 5 exact copies. It's not a blocking issue, but for debugging/ UI, it makes things a bit more complicated.
Here's the code of the replicated view:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View"/>
<import type="android.text.TextUtils"/>
<variable
name="title"
type="String" />
<variable
name="value"
type="String" />
</data>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:text="#{(!TextUtils.isEmpty(title) ? title : `Title`).concat(`:`), default=`Title:`}" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#{!TextUtils.isEmpty(value) ? #color/darkBlue : #color/red, default=#color/red }"
android:text="#{(!TextUtils.isEmpty(value) ? value : `Unknown`), default=`Unknown`}" />
</LinearLayout>
</layout>
And here's how it's included:
<include layout="#layout/titled_entry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
bind:title="#{`Firstname`}"
bind:value="#{user.firstName}" />
In Android it looks like this
But in preview it looks like this
Does anyone know how to fix it ?
Thanks, and have a good day in those complicated times.
Store your string in string.xml
And set that as default value
Like below
android:text='#{viewModel.firstName, default=#string/firstName}`

Android: re-using layouts using include with parameters

I'm creating an ordered list with a custom styling which is used in multiple places. I try to avoid extra code and to create a re-usable layout file for the list item, which can be included to ordered list with certain parameters. How I could do that?
What I have now is following:
layout_ordered_list_item.xml
<?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="order"
type="java.lang.String" />
<variable
name="text"
type="java.lang.String" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/order"
android:layout_width="28dp"
android:layout_height="28dp"
android:layout_marginBottom="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="#{order}"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="60dp"
android:text="#{text}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</layout>
Then I would like to use that layout like following:
layout_ordered_list.xml
<LinearLayout>
<include layout="#layout/layout_ordered_list_item"
bind:order="1"
bind:text="First text content"/>
<include layout="#layout/layout_ordered_list_item"
bind:order="2"
bind:text="Second text content"/>
etc.
</LinearLayout>
Note that I'm not interested about setting variables in code dynamically. I use these layouts only with hard-coded values (or with string resources) like in my example. But since I'm using these so many times, I don't want to copy-paste list item again and again just to alter order and text content. I also know that my example is not working, it's here just to demonstrate how I would like it to work.
I've already searched the answer from Android documents but there is no example like that.
https://developer.android.com/training/improving-layouts/reusing-layouts.html
https://developer.android.com/topic/libraries/data-binding/index.html#includes
Pretty much identical question has been also asked before in SO but there is no usable answer either: How to Re-using Layouts with <include/> with parameters?
You should be able to achieve what you want by using the databinding library to inflate the including layout, and then passing in the hard coded text using a databinding statement.
Details on the databinding expression language can be found here.
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto">
<LinearLayout>
<include layout="#layout/layout_ordered_list_item"
bind:order="#{`1`}"
bind:text="#{`First text content`}"/>
<include layout="#layout/layout_ordered_list_item"
bind:order="#{`2`}"
bind:text="#{`Second text content`}"/>
</LinearLayout>
</layout>

How to use <layout> tag in Android

I need to know how to use layout tag in android xml file. I know it is used for data binding but I do not have complete knowledge on this. Please let me know if anyone can help me in same.
Thanks in Advance !!
The <layout> tag must be the root tag when you are using DataBinding. Doing so you are telling the compiler that you are using DataBinding and your layout will have special tags like <variable> or <import>, so you have to embed your layout within that tag.
In short, you need to use the <layout> tag whenever you are using DataBinding for the compiler to understand the special tags and generate the DataBinding class with the right variables and methods.
If you have a layout like this (layout_data_binding.xml):
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.firstName}"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{user.lastName}"/>
</LinearLayout>
</layout>
It is based on what is inside the <layout> tag to create the LayoutDataBinding class (auto-generated) with the User variable and its getters and setters.

Two-way binding Attribute is missing the Android namespace prefix <Data> <Variable>

Trying to implement two way binding
As mentioned:
Data Binding Library
Two-way Android Data Binding - How to use two-way Data Binding to manage a layout
2-way Data Binding on Android!
However on
<variable type="com.example.gideonsassoon.avariel.datamodels.Player" name="name"/>
I am getting the following message.:
"Attribute is missing the Android namespace prefix less... (Ctrl+F1)
Most Android views have attributes in the Android namespace. When
referencing these attributes you must include the namespace prefix, or
your attribute will be interpreted by aapt as just a custom attribute.
Similarly, in manifest files, nearly all attributes should be in the
android: namespace."
If I try to build it puts all the R. in my file in red and state they don't exist etc.
I have edited my build gradle file to have
dataBinding.enabled = true
Full code up to the point relevant below
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:windowSoftInputMode="adjustPan"
tools:context="com.example.gideonsassoon.avariel.ui.MainFragmentActivity">
<data>
<variable type="com.example.gideonsassoon.avariel.datamodels.Player" name="name"/>
</data>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<android.support.v4.view.PagerTabStrip
android:id="#+id/viewpagerStrip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"/>
</android.support.v4.view.ViewPager>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="7dp"
android:layout_marginTop="34dp">
<TextView
android:id="#+id/tv_character_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/name_colon"
android:textAppearance="#style/TextAppearance.AppCompat.Title"
android:textIsSelectable="false" />
<EditText
android:id="#+id/et_character_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#={player.name}"
android:layout_alignBaseline="#+id/tv_character_name"
android:layout_marginStart="15dp"
android:layout_toEndOf="#+id/tv_character_name"
android:ems="12"
android:hint="#string/character_name"
android:inputType="textPersonName" />
Ahh it appears to be that I have it as relativeLayout. It can't be "binding" so it can only be layout. Not sure how that's gonna affect my files as a whole but I guess we'll just have to see how it plays out. Here's my source. However if anyone wants to answer to that effect it would be most appreciated.
Using data binding in Android - Tutorial

Is it possible to have dynamic resource path when using Android data-binding?

I am using data-binding in my Android application, and I want to change the font color depending on what state my model is in. Something like
android:textColor='#{#color/state_ + myobj.state}'
in my layout. And
<color name="state_good">#0f0</color>
in my colors.xml. Is something like this possible?
I can think of two main possibilities.
The one that you probably don't want is to have your model object have a getter method that returns the color resource ID (based on its state). While this is simple, it would violate your typical view/model separation of concerns, as the model shouldn't really care about rendering colors.
The other is to have a utility class somewhere, with a static method that, given the state, returns the color resource ID. You can then import that class into the <layout> and call it from the expression.
For example, this layout imports Html, to be able to call Html.fromHtml(), to handle strings that may have HTML formatting (or, in this case, HTML entities):
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.text.Html"/>
<variable
name="item"
type="com.commonsware.android.databind.basic.Item"/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/icon"
android:layout_width="#dimen/icon"
android:layout_height="#dimen/icon"
android:layout_gravity="center_vertical"
android:contentDescription="#string/icon"
android:padding="8dip"/>
<TextView
android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:text="#{Html.fromHtml(item.title)}"
android:textSize="20sp"/>
</LinearLayout>
</layout>
In your case, you would import your utility class and call your static method in the android:textColor attribute.

Categories

Resources