nick.tdr
nick.tdr

Reputation: 4933

Setting scroll flags using data binding in android

I want to set the scroll flags in collapsing toolbar layout using data binding. This is what I am trying to achieve:

app:layout_scrollFlags="@{isListEmpty ? snap : scroll|exitUntilCollapsed|snap}"

But it is giving the following error:

Found data binding errors. ****/ data binding error ****msg: Identifiers must have user defined types from the XML file. snap is missing it

So basically I just want to turn off the collapsing effect when the list is empty. I can achieve that in code but it would be really helpful if there was a way to achieve this using data binding in xml.

Upvotes: 1

Views: 1033

Answers (2)

Peter Staranchuk
Peter Staranchuk

Reputation: 1393

You can do it with BindingAdapter. Like that:

  1. Add binding adapter:
@BindingAdapter("app:layout_scrollFlags")
    fun setLayoutScrollFlags(toolbar : Toolbar, flags : Int) {

    //toolbar is your toolbar within an AppBarLayout
    val params = toolbar.layoutParams as AppBarLayout.LayoutParams
    params.setScrollFlags(flags);
    toolbar.layoutParams = params
}

  1. Replace code in your xml:
    app:layout_scrollFlags="@{viewModel.flags}"
  1. If/else statements in in xml code is a bad practice (in spite of you can see it in Android documentation, this practice is a breakdown of single responsibility principle because view decide which flag to set according to boolean variable).

Set your flags on activity/fragment side as integers:

if(isListEmpty) {
    viewModel.setFlags(snap) 
} else {
    viewModel.setFlags(scroll|exitUntilCollapsed|snap)
}

So you will not hold any "Android related" data like reference on flag in view model. For view model it will be just an integer variable.

Hope it'll help)

Upvotes: 2

nick.tdr
nick.tdr

Reputation: 4933

I achieved this using BindingAdapters. Although I would still like to know if this can be achieved only from xml so that we don't have to use any custom attributes.

So I added a custom attribute

 @BindingAdapter("set_scroll_flags")
public static void setCollapsingToolbarScroll(CollapsingToolbarLayout 
 collapsingToolbar, boolean isListEmpty) {

    if(isListEmpty)
    {
        AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) collapsingToolbar.getLayoutParams();
        toolbarLayoutParams.setScrollFlags(0);
        collapsingToolbar.setLayoutParams(toolbarLayoutParams);
    }
    else
    {

        AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) collapsingToolbar.getLayoutParams();
        toolbarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
                | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED | AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP);
        collapsingToolbar.setLayoutParams(toolbarLayoutParams);
    }
}

The above code stops the collapsing effect when the list is empty and when the list is not empty it behaves according to the scroll flags you set(I used EXIT_UNTIL_COLLAPSED, SNAP and SCROLL).

Then in the xml, in the CollapsingToolbarLayout use the attribute like below:

set_scroll="@{isListEmpty}"

Where 'isListEmpty' can be a variable in the data tag of xml.

Upvotes: 2

Related Questions