2016-07-29 13 views
6

アンドロイドのデータバインディングメニューをサポートしていますか? 私はこのコードを書いていますが、エラー: "エラー:(16,26)リソースタイプが指定されていません(値 '@ {item.visible}'で 'visible'Android DataBindingをメニューにバインドするにはどうすればいいですか?

<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

あなたは 'Fact'コードを追加していただけますか? –

答えて

3

AFAIK、現時点では、データバインディングはメニューリソースではなくレイアウトリソース用です。

13

しかし、動作がObservable.OnPropertyChangedCallbackで達成することができる「現時点では、データバインディングは、レイアウトリソースではなく、メニューのリソースに対してのみです」。まず、OnPropertyChangedCallback定義する必要があります。

private final Observable.OnPropertyChangedCallback propertyChangedCallback = new Observable.OnPropertyChangedCallback() { 
    @Override 
    public void onPropertyChanged(Observable observable, int i) { 
     getActivity().invalidateOptionsMenu(); 
    } 
}; 

はあなたのフラグメントでファクトモデルのために結合していると仮定すると:

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

は、今、私たちは事実に基づいて準備ができて更新あなたのビューステートですモデル:

@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

また、コールバックの 'int i'は' propertyId == BR.propertyName'でチェックできるプロパティIDであり、頻繁なメニューの無効化を避けることに注意してください – Philipp

2

私はこれが古い質問です実現が、私はそれが同じ問題に他人を助けることができるようにソリューションを提供したかったです。これは、メニュー項目のアクションビューを使用して実現できます。かなりのコードが必要ですが、MVVMを使用するアプローチであり、あらゆるデータバインディングに使用できます。

これは、アイコンカウントを示し、カウントは、メニュー項目

メニュー/ 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> 
を定義0

よりも大きい場合に背景を変更する例であります

メニュー項目のビューモデルを定義します。

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


} 
関連する問題