Androidデータバインディングをプロジェクトで使用しようとしていますが、この種の問題が発生します。たとえば、チェックボックスグループとして3つのチェックボックスがあります。最初のチェックボックスがオンの場合、次に変数type
は1です。2番目はtype
を2にし、3番目はtype
を3にします。このようにコードを実装します。
_ // layout.xml
<Android.support.v7.widget.AppCompatCheckBox
Android:layout_width="50dp"
Android:layout_height="50dp"
Android:checked="@{userInfoViewModel.type == 1}"
Android:onCheckedChanged="@{(compoundButton, checked) -> userInfoViewModel.onTypeChecked(checked, 1)}"
/>
<Android.support.v7.widget.AppCompatCheckBox
Android:layout_width="50dp"
Android:layout_height="55dp"
Android:checked="@{userInfoViewModel.type == 2}"
Android:onCheckedChanged="@{(compoundButton, checked) -> userInfoViewModel.onTypeChecked(checked, 2)}"
/>
<Android.support.v7.widget.AppCompatCheckBox
Android:layout_width="50dp"
Android:layout_height="55dp"
Android:checked="@{userInfoViewModel.type == 3}"
Android:onCheckedChanged="@{(compoundButton, checked) -> userInfoViewModel.onTypeChecked(checked, 3)}"
/>
_
_// viewModel
public void onTypeChecked(boolean checked, int i) {
if (checked) {
// if it is a check. set the type
type.set(i);
} else {
// if it is a uncheck. set type to unknown
type.set(0);
}
}
_
問題は、1番目のチェックボックスをオンにした場合、2番目のチェックボックスをオンにすることです。 type
を2に設定し、UIを正しく更新する必要があります。しかし実際には、uncheck
イベントも最初のチェックボックスで発生し、type
が2に設定された後、type.set(0)
がトリガーされるため、チェックボックスはチェックされません。
実際、この問題は onCheckedChangedが自動的に呼び出される と同じです。私が必要としているのは、データバインディングのソリューションです。
非データバインディングプロジェクトでは、setCheckedSilent
(@ Emanuel Andradaによる回答)を使用するのが最善の解決策だと思います。
_ public void setCheckedSilent(boolean checked) {
super.setOnCheckedChangeListener(null);
super.setChecked(checked);
super.setOnCheckedChangeListener(listener);
}
_
しかし、データバインディングでは、これを行うことはできません。それで、私を助けることができる専門家はいますか?
@Arpan Sharmaの回答によると、onClick
ではなくonCheckedChanged
を聞いてください。このソリューションは現在機能していますが、checked
の値が心配です。常に正しいですか?
_public void onTypeChecked(View view, int i) {
Boolean checked = ((CheckBox) view).isChecked();
if (checked) {
type.set(i);
} else {
type.set(0);
}
}
_
私は同じ問題に直面し、onCHeckリスナーではなくonCLickリスナーを使用しました。このようにして、プログラムで設定されたときにリスナーがチェック状態を変更しません。あなたの問題では、チェックボックスに異なるチェック変更リスナーを設定してみてください。
これはデータバインディングで非常に簡単です
XMLチェックボックスコンポーネント
<CheckBox
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:onCheckedChanged="@{(compoundButton, checked) ->
changeKeyboardVM.onCheckedChange(compoundButton, checked)}" />
ViewModelまたはアクティビティ内
public void onCheckedChange(CompoundButton button, boolean check) {
Log.d("Z1D1", "onCheckedChange: " + check);
}
チェックがオンの場合はブールチェックtrue
、オフの場合はfalse
私はこの質問に初めて遭遇し、バインディングアダプターを使用して実装する方が良いと思います。
アダプタをバインドするためのコードは次のとおりです
interface OnUserCheckedChangeListener {
fun onUserCheckChange(view:CompoundButton, isChecked:Boolean)
}
@BindingAdapter("onUserCheckedChange")
fun setUserCheckedChangeListener(view:CompoundButton, listener: OnUserCheckedChangeListener?){
if(listener == null){
view.setOnClickListener(null)
}else{
view.setOnClickListener {
listener.onUserCheckChange(view, view.isChecked)
}
}
}
そして、どの複合ボタンでも使用できます
<CheckBox
Android:id="@+id/finish_check"
Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
Android:checked="@{your_condition}"
onUserCheckedChange="@{(view, checked) -> vm.onItemChecked(todo, checked)}"
/>
ViewModelからObservableBooleanを公開し、そのブールに対して双方向のデータバインディングを使用します。
次に、ObservableBooleanの値を使用して、XMLにエンコードするのではなく、何を実行するかを決定できます。
Android:checked="@={vm.checkedValue}"
双方向のバインドを防ぐために、onClick
の代わりにonCheckedChanged
を使用します。
From item_order_view.xml
:
<data>
<variable
name="viewModel"
type="com.package.name.OrderItemViewModel" />
</data>
<CheckBox
Android:id="@+id/cb_selected"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:layout_marginLeft="8dp"
Android:buttonTint="@color/white"
Android:checked="@{viewModel.isSelect}"
Android:onClick="@{() -> viewModel.onClickedCheckBox()}"
Android:textColor="@color/white" />
OrderItemViewModel.Java
から
public class OrderItemViewModel {
public final ObservableField<Boolean> isSelect;
public final OrderItemViewModelListener mListener;
private final Order mOrder;
public OrderItemViewModel(Order order, OrderItemViewModelListener listener) {
this.mListener = listener;
this.mOrder = order;
isSelect = new ObservableField<>(mOrder != null ? mOrder.isSelect() : false);
}
/**
* Using onClick instead of onCheckedChanged
* to prevent 2-ways binding issue.
*/
public void onClickedCheckBox() {
mListener.onCheckChanged();
}
public interface OrderItemViewModelListener {
void onCheckChanged();
}
}