Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to bind a layout_width and layout_height using data binding in Android

I'm trying to bind a boolean that indicates to an ImageView if the screen size is small, so it shrinks if I need more space for other components. I'm using the DataBinding Library to do so.

My layout whose width and height depends on this boolean:

...
<data>
    ...
    <variable name="smallScreen" type="boolean"/>
    ...
</data>
...
<ImageView
android:layout_width="@{smallScreen ? @dimen/img_small_screen_size : @dimen/img_big_screen_size}"
android:layout_height="@{smallScreen ? @dimen/img_small_screen_size : @dimen/img_big_screen_size}"
android:layout_gravity="center_horizontal"
android:contentDescription="@{message}"
android:src="@{image}"
android:scaleType="center"
tools:src="@drawable/img_message_private"/>
...

If I just try to build my project like this, the compiler says layout_width cannot accept type float. Fair enough, I use the BindingAdapter class to create a float enter for layout attributes, as follows:

...
@BindingAdapter("android:layout_width")
public static void setLayoutWidth(View view, float width) {
    ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
    layoutParams.width = (int) width;
    view.setLayoutParams(layoutParams);
}

@BindingAdapter("android:layout_height")
public static void setLayoutHeight(View view, float height) {
    ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
    layoutParams.height = (int) height;
    view.setLayoutParams(layoutParams);
}
...

That allows my project to build. But when the layout is finally being rendered, I fall in the following exception:

java.lang.RuntimeException: Binary XML file line #21: You must supply a layout_width attribute.

Just for information, my dimensions are set in dp units, as follows:

<dimen name="img_small_screen_size">100dp</dimen>
<dimen name="img_big_screen_size">208dp</dimen>

Does someone know how can I override the layout_width attribute so I can use databind with it directly, using dimensions?

like image 719
Felipe Jun Avatar asked Jan 18 '16 20:01

Felipe Jun


People also ask

Can I use both data binding and view binding?

View binding doesn't support layout variables or layout expressions, so it can't be used to declare dynamic UI content straight from XML layout files. View binding doesn't support two-way data binding.

What is data binding in Android example?

In Android, the Data Binding Library is a support library that allows you to bind UI components in your layouts to data sources in your app using a declarative format rather than programmatically.

What is two way data binding in Android?

Stay organized with collections Save and categorize content based on your preferences. The @={} notation, which importantly includes the "=" sign, receives data changes to the property and listen to user updates at the same time.


2 Answers

You should add a default value, i.e.,

android:layout_width="@{smallScreen ? @dimen/img_small_screen_size : @dimen/img_big_screen_size, default=wrap_content}"
like image 152
qichuan Avatar answered Oct 19 '22 18:10

qichuan


I just figured it out as I wrote my question. I just used another attribute to bind the one I wanted changed, the code ended like this:

<ImageView
android:layout_width="@{smallScreen ? @dimen/img_small_screen_size : @dimen/img_big_screen_size}"
android:layout_height="@{smallScreen ? @dimen/img_small_screen_size : @dimen/img_big_screen_size}"
android:layout_gravity="center_horizontal"
android:contentDescription="@{message}"
android:src="@{image}"
android:scaleType="center"
tools:src="@drawable/img_message_private"/>

So my BindingAdapters became this:

@BindingAdapter("android:layout_width")
public static void setLayoutWidth(View view, float width) {
    ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
    layoutParams.width = (int) width;
    view.setLayoutParams(layoutParams);
}

@BindingAdapter("android:layout_height")
public static void setLayoutHeight(View view, float height) {
    ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
    layoutParams.height = (int) height;
    view.setLayoutParams(layoutParams);
}
like image 6
Felipe Jun Avatar answered Oct 19 '22 18:10

Felipe Jun