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>
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With