j2emanue
j2emanue

Reputation: 62519

Android databinding - How to get dimensions from dimens.xml

I want to set margins based on dimensions i have created in dimens.xml The dimensions it sself works fine, its just data binding cant find it in the case below:

<TextView
           android:id="@+id/title_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_below="@+id/disableButton"
*************
        android:layout_marginBottom="@{@bool/showAds ? 
@dimen/frontpage_margin_ads: @dimen/frontpage_margin_noads}"
*************        
android:gravity="center_horizontal"
        android:text="@string/app_name"
        android:textColor="@android:color/holo_orange_dark"
        android:contentDescription="@string/app_name"
        android:textSize="64sp"
        android:textStyle="bold" />

it did find it but it says that marginbottom cannot take type float. How can i fix this? I tried casting both dimens to int but then it complains that it cannot be casted to int.

My dimensions xml file looks like this:

    <resources>

    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
    <dimen name="bigText">44sp</dimen>
    <dimen name="littleText">44sp</dimen>
    <dimen name="mediumText">40sp</dimen>
        <dimen name="smallText">24sp</dimen>
    <dimen name="fab_margin">16dp</dimen>
    <dimen name="frontpage_margin_noads">0dp</dimen>
    <dimen name="frontpage_margin_ads">13dp</dimen>


</resources>

Upvotes: 23

Views: 17739

Answers (3)

Wex
Wex

Reputation: 4686

Other examples didn't work for me, so I wrote my own. This can be added to a new, blank Kotlin file. The functions don't need to be in a class. Make sure you've got your own package statement at the top of the file.

import android.view.View
import android.view.ViewGroup
import androidx.databinding.BindingAdapter

@BindingAdapter("android:layout_marginBottom")
fun setLayoutMarginBottom(view: View, dimen: Int) {
    (view.layoutParams as ViewGroup.MarginLayoutParams).let {
        it.bottomMargin = dimen
        view.layoutParams = it
    }
}

@BindingAdapter("android:layout_marginTop")
fun setLayoutMarginTop(view: View, dimen: Int) {
    (view.layoutParams as ViewGroup.MarginLayoutParams).let {
        it.topMargin = dimen
        view.layoutParams = it
    }
}

@BindingAdapter("android:layout_marginStart")
fun setLayoutMarginStart(view: View, dimen: Int) {
    (view.layoutParams as ViewGroup.MarginLayoutParams).let {
        it.marginStart = dimen
        view.layoutParams = it
    }
}

@BindingAdapter("android:layout_marginEnd")
fun setLayoutMarginEnd(view: View, dimen: Int) {
    (view.layoutParams as ViewGroup.MarginLayoutParams).let {
        it.marginEnd = dimen
        view.layoutParams = it
    }
}

Upvotes: 1

antygravity
antygravity

Reputation: 1307

Almost the same solution, but using Kotlin:

In file BindingAdapters.kt add:

@BindingAdapter("layoutMarginBottom")
fun setLayoutMarginBottom(view: View, dimen: Float) {
    view.updateLayoutParams<ViewGroup.MarginLayoutParams> {
        bottomMargin = dimen.toInt()
    }
}

Usage in layout:

<LinearLayout
    app:layoutMarginBottom="@{viewModel.type == Type.SMALL ? @dimen/margin_small : @dimen/margin_large}"

You can write similar method for top, start, end margins.

Upvotes: 2

George Mount
George Mount

Reputation: 20926

The problem here is not with dimensions, but with android:layout_marginBottom. There is no built-in support for any LayoutParams attributes. This was done to remove the "foot gun" that many might use to bind variables to LayoutParams and maybe attempt to use data binding to animate their positions this way.

Data Binding is perfect to be used in your example and you can easily add your own. It would be something like this.

@BindingAdapter("android:layout_marginBottom")
public static void setBottomMargin(View view, float bottomMargin) {
    MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams();
    layoutParams.setMargins(layoutParams.leftMargin, layoutParams.topMargin,
        layoutParams.rightMargin, Math.round(bottomMargin));
    view.setLayoutParams(layoutParams);
}

You would, of course, also add the left, top, right, start, and end BindingAdapters as well.

Upvotes: 44

Related Questions