Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically toggle visibility of layout elements with Android data-binding.

I am building an Android app, where I want to toggle the visibility of some view elements based on a button click. I am trying to archive it with data-binding instead of using findViewById(), but all the solutions I've have found until now doesn't update the layout, when the variable is changed.

Here is what I have so far. (I've simplified the code, to focus on the problem)

Activicy.java

public class RecipeActivity extends AppCompatActivity {
private Recipe recipe;
private ActivityRecipeBinding binding;
private RecipeBinderHelper rbhelper = new RecipeBinderHelper();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    Intent intent = getIntent();
    recipe = intent.getParcelableExtra("recipe");
    binding = DataBindingUtil.setContentView(this, R.layout.activity_recipe);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    toolbar.setTitle(recipe.getName());
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    binding.recipeContent.setRecipe(recipe);
    binding.recipeContent.setHelper(rbhelper);

    binding.Button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //HERE I CHANGE THE VALUE OF THE VARIBLE
            rbhelper.setPresentationViewVisible(false);
            binding.notifyChange();
        }
    });
}
}

Helper class

public class RecipeBinderHelper{
private Boolean presentationElementsVisible;
private Boolean timerElementsVisible;

public RecipeBinderHelper(){
    this.presentationElementsVisible = true;
    this.timerElementsVisible = false;
}
public void setPresentationViewVisible(boolean presentationElementsVisible) {
    this.presentationElementsVisible = presentationElementsVisible;
}
public Boolean getPresentationElementsVisible() {
    return presentationElementsVisible;
}
//getters and setters for private Boolean timerElementsVisible;
}

Layout

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
    <import type="android.view.View"/>
    <variable
        name="helper"
        type="com.myapps.recipeApp.RecipeBinderHelper"/>
    <variable
        name="recipe"
        type="com.myapps.recipeApp.Recipe"/>
</data>
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.myapp.recipeApp.RecipeActivity"
    tools:showIn="@layout/activity_recipe">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/r_source"
        android:textStyle="bold"
        android:text="@{recipe.source}"
        android:visibility="@{helper.presentationElementsVisible ? View.VISIBLE : View.GONE}" />
<!-- More TextViews here -->
<!-- Button is located in parret layout -->
</RelativeLayout>
</layout>
like image 934
mutttenxd Avatar asked Jul 07 '16 08:07

mutttenxd


People also ask

Which is better view binding or Data Binding in Android?

ViewBinding vs DataBindingThe main advantages of viewbinding are speed and efficiency. It has a shorter build time because it avoids the overhead and performance issues associated with DataBinding due to annotation processors affecting DataBinding's build time.

What is 2 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. // Avoids infinite loops.

What is ActivityMainBinding?

The above layout filename is activity_main. xml so the corresponding generated class is ActivityMainBinding . This class holds all the bindings from the layout properties (for example, the user variable) to the layout's views and knows how to assign values for the binding expressions.


1 Answers

I highly recommend to read George Mount's posts about Android data-binding, they are very useful.


To solve the problem I extended the helper class as an BaseObservable as described in the documentation.

Helper class

public class RecipeBinderHelper{
    private Boolean presentationElementsVisible;
    private Boolean timerElementsVisible;

    public RecipeBinderHelper(){
        this.presentationElementsVisible = true;
        this.timerElementsVisible = false;
    }
    public void setPresentationViewVisible(boolean presentationElementsVisible) {
        this.presentationElementsVisible = presentationElementsVisible;
        //Notifying change in the setter. 
        notifyPropertyChanged(BR.presentationElementsVisible);
    }
    //assigning Bindable annotation to the getter 
    @Bindable
    public Boolean getPresentationElementsVisible() {
        return presentationElementsVisible;
    }
    //getters and setters for private Boolean timerElementsVisible;
}

The binding.notifyChange();in the Activity is not necessary and can be removed.

The app now removes the TextView as desired, when the button is clicked.


One peculiar thing is that Android Studio (2.1.2, Ubuntu) gives me a Cannot resolve symbol 'BR' warning, but the app compiles and runs as expected.

like image 86
mutttenxd Avatar answered Oct 04 '22 06:10

mutttenxd