使用 Android 数据绑定动态切换布局元素的可见性。

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

我正在构建一个 Android 应用程序,我想在其中根据按钮单击来切换某些视图元素的可见性。我正在尝试使用数据绑定而不是使用 findViewById() 来存档它,但是我到目前为止找到的所有解决方案都不会在变量更改时更新布局。

这是我目前所拥有的。 (我已经简化了代码,以专注于问题)

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();
        }
    });
}
}

帮手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;
}

布局

<?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>

我强烈推荐阅读 George Mount 的 posts about Android data-binding,它们非常有用。


为了解决这个问题,我将助手 class 扩展为 BaseObservable as described in the documentation

帮手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;
}

Activity中的binding.notifyChange();不需要,可以去掉。

应用程序现在会在单击按钮时根据需要删除 TextView。


一个奇怪的事情是 Android Studio (2.1.2, Ubuntu) 给了我一个 Cannot resolve symbol 'BR' 警告,但应用程序按预期编译和运行。