因为它支持android中的数据绑定菜单? 我写了这段代码,但错误:“错误:(16,26)没有指定资源类型(在'visible'处,值为'@ {item.visible}')。”
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="item"
type="ru.dixy.ubiworkerchecklistsmobile.Models.Fact"/>
<import type="android.view.View"/>
</data>
<item
android:id="@+id/compliteitem"
android:title="mybutton"
android:icon="@drawable/complite"
android:visible="@{item.visible}"
app:showAsAction="ifRoom"
/>
</menu>
答案 0 :(得分:17)
&#34;目前,数据绑定仅适用于布局资源,而非菜单资源&#34;
但是,可以使用 Observable.OnPropertyChangedCallback 来实现此行为。首先,您需要定义OnPropertyChangedCallback:
private final Observable.OnPropertyChangedCallback propertyChangedCallback = new Observable.OnPropertyChangedCallback() {
@Override
public void onPropertyChanged(Observable observable, int i) {
getActivity().invalidateOptionsMenu();
}
};
假设您的片段中有 Fact 模型的绑定:
<variable
name="item"
type="ru.dixy.ubiworkerchecklistsmobile.Models.Fact"/>
现在您需要注册propertyChangedCallback并在完成后取消注册:
@Override
public void onStart() {
super.onStart();
binding.getItem().addOnPropertyChangedCallback(propertyChangedCallback);
}
@Override
public void onStop() {
super.onStop();
binding.getItem().removeOnPropertyChangedCallback(propertyChangedCallback);
}
现在我们已准备好根据 Fact 模型更新您的视图状态:
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_fact, menu);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.findItem(R.id.compliteitem).setVisible(binding.getItem().isVisible());
}
答案 1 :(得分:8)
目前,数据绑定仅适用于布局资源,而不适用于菜单资源。
答案 2 :(得分:2)
我意识到这是一个老问题,但我想提供一个解决方案,以便它可以帮助其他人解决同样的问题。这可以使用菜单项的动作视图来实现。它需要相当多的代码,但它是一种使用MVVM的方法,可以用于任何数据绑定。
这是一个示例,其中图标显示计数,如果计数大于0,则更改背景。
定义菜单项
菜单/ main.xml中强>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/action_count"
android:enabled="true"
android:icon="@drawable/ic_menu_red_square"
android:title="@string/count"/>
</menu>
定义菜单项的视图模型。
public class CountMenuViewModel extends BaseObservable {
@Bindable
int count;
public CountMenuViewModel() {}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
if (this.count < 0) {
this.count = 0;
}
notifyPropertyChanged(BR.count);
}
@Bindable({"count"})
public @DrawableRes int getBackground() {
if (count > 0) {
return R.drawable.ic_menu_blue_square;
}
return R.drawable.ic_menu_red_square;
}
@Bindable({"count"})
public String getCountText() {
if (count > 0) {
return String.valueOf(count);
}
return null;
}
}
定义单击菜单项时活动将实现的回调。
public interface CountMenuActionCallback {
void onCountMenuItemClicked();
}
为操作视图创建布局。布局使用视图模型类并设置计数和背景的文本。回调接口用于操作视图的OnClickListener。
<强>布局/ menu_action_count.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="data"
type="com.botnerd.samplesapp.CountMenuViewModel"
/>
<variable
name="callback"
type="com.botnerd.samplesapp.CountMenuActionCallback"
/>
</data>
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{() -> callback.onCountMenuItemClicked()}"
android:background="?android:attr/actionBarItemBackground">
<ImageView
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_margin="4dp"
android:src="@{data.background}"
tools:src="@drawable/ic_menu_red_square"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@{data.countText}"
tools:text="30"
android:textSize="14dp"
android:maxLines="1"
android:textColor="@android:color/white"
tools:ignore="SpUsage"/>
</FrameLayout>
</layout>
请注意,自定义绑定适配器用于android:src
属性。这是一个很好的适配器,可以通过数据绑定设置ImageView src。
@BindingAdapter({"android:src"})
public static void setSrc(ImageView view, @DrawableRes int resId) {
try {
view.setImageDrawable(ContextCompat.getDrawable(view.getContext(), resId));
} catch (Resources.NotFoundException e) {
}
}
最后,膨胀菜单并在活动中绑定操作视图布局。
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
MenuItem menuItemCount = menu.findItem(R.id.action_count);
MenuActionCountBinding binding = MenuActionCountBinding.inflate(getLayoutInflater());
binding.setData(mCountMenuViewModel);
binding.setCallback(mCountMenuActionCallback);
MenuItemCompat.setActionView(menuItemCount, binding.getRoot());
MenuItemCompat.setShowAsAction(menuItemCount, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
return super.onCreateOptionsMenu(menu);
}
为了完整性,以下是样本中未定义的所有文件。
<强>抽拉/ ic_menu_blue_square.xml 强>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<padding android:bottom="4dp"
android:left="4dp"
android:right="4dp"
android:top="4dp"/>
<solid android:color="#000080"/>
<corners android:radius="2dp"/>
</shape>
<强>抽拉/ ic_menu_red_square.xml 强>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<padding android:bottom="4dp"
android:left="4dp"
android:right="4dp"
android:top="4dp"/>
<solid android:color="#800000"/>
<corners android:radius="2dp"/>
</shape>
<强>布局/ activity_main.xml中强>
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="callback"
type="com.botnerd.samplesapp.MainActivityActionCallback"
/>
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.botnerd.samplesapp.MainActivity">
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-"
android:onClick="@{() -> callback.onMinusClicked()}"
android:layout_marginStart="79dp"
app:layout_constraintBaseline_toBaselineOf="@+id/button2"
tools:layout_constraintBaseline_creator="1"
tools:layout_constraintLeft_creator="1"
app:layout_constraintLeft_toLeftOf="parent"/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"
android:onClick="@{() -> callback.onPlusClicked()}"
tools:layout_constraintTop_creator="1"
android:layout_marginStart="25dp"
android:layout_marginTop="97dp"
tools:layout_constraintLeft_creator="1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@+id/button"/>
</android.support.constraint.ConstraintLayout>
</layout>
<强> MainActivityActionCallback.java 强>
public interface MainActivityActionCallback {
void onPlusClicked();
void onMinusClicked();
}
<强> MainActivity.java 强>
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mBinding;
CountMenuViewModel mCountMenuViewModel;
CountMenuActionCallback mCountMenuActionCallback = new CountMenuActionCallback() {
@Override
public void onCountMenuItemClicked() {
Toast.makeText(MainActivity.this, "Count clicked!", Toast.LENGTH_SHORT)
.show();
}
};
MainActivityActionCallback mActionCallback = new MainActivityActionCallback() {
@Override
public void onPlusClicked() {
mCountMenuViewModel.setCount(mCountMenuViewModel.getCount() + 1);
}
@Override
public void onMinusClicked() {
mCountMenuViewModel.setCount(mCountMenuViewModel.getCount() - 1);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mCountMenuViewModel = new CountMenuViewModel();
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mBinding.setCallback(mActionCallback);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
MenuItem menuItemCount = menu.findItem(R.id.action_count);
MenuActionCountBinding binding = MenuActionCountBinding.inflate(getLayoutInflater());
binding.setData(mCountMenuViewModel);
binding.setCallback(mCountMenuActionCallback);
MenuItemCompat.setActionView(menuItemCount, binding.getRoot());
MenuItemCompat.setShowAsAction(menuItemCount, MenuItemCompat.SHOW_AS_ACTION_ALWAYS);
return super.onCreateOptionsMenu(menu);
}
}