Android双向数据绑定与自定义绑定逻辑

时间:2016-10-18 21:10:29

标签: android android-layout android-studio android-databinding

我使用android数据绑定库,我有一个带复选框的布局,我需要使用自定义检查逻辑(layout)。

有没有办法创建这样的绑定,检查其中一个框会导致其余部分取消选中?什么是最好的方法?

5 个答案:

答案 0 :(得分:1)

我建议如下:

  1. 为复选框
  2. 设置一个共同的OnClickListener
  3. 按XML分配侦听器(不是必需的,但显然更好)
  4. 每次选中一个复选框时循环选中,并取消选中其他复选框。
  5. XML

    <LinearLayout
        android:id="@+id/parent"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    
        <CheckBox android:id="@+id/checkbox_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Option 1"
            android:onClick="onCheckboxClicked"/>
    
        <CheckBox android:id="@+id/checkbox_2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Option 2"
            android:onClick="onCheckboxClicked"/>
    
     </LinearLayout>
    

    活动

    public void onCheckboxClicked(View clickedView)
    {
            LinearLayout parent = (LinearLayout) findViewById(R.id.parent);
            for (int i=0; i < parent.getChildCount(); i++)
            {
                View view = parent.getChildAt(i);
                if (view instanceof CheckBox)
                {
                    CheckBox checkbox = (CheckBox) view;
                    if (checkbox.isChecked() && !checkbox.equals(clickedView)) {
                        checkbox.setChecked(false);
                    }
                }
            }
    }
    

    您显然可以创建一个名为 CheckBoxGroup 的自定义ViewGroup,它会收到复选框并自动实现此流程。但我不认为这是必要的,它会使事情复杂化。并且也不会那么灵活,因为复选框必须全部在其中。

答案 1 :(得分:0)

复选框通常单独使用,每个复选框都注册了一个单独的点击监听器。 Android指南也是如此。您可以在以下位置查看:https://developer.android.com/guide/topics/ui/controls/checkbox.html

但是,如果您有需要使用它们的场景,则必须创建一个逻辑用于自己处理它。 Checkbox有一个方法 setChecked(boolean),可用于设置状态:如果要检查状态,则为true;如果未选中状态,则为false。

您可以附加一个监听器来检查更改是否为支票。

checkbox.setOnCheckedChangeListener(new OnCheckedChangeListener(){

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        // TODO Auto-generated method stub

    }
});

为每个复选框附加单独的侦听器。当一个更改的检查状态对其他复选框进行适当的更改时。

checkbox1.setOnCheckedChangeListener(new OnCheckedChangeListener(){

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
       if(isChecked) {
            checkbox2.setChecked(false);
            checkbox3.setChecked(false);
        }
    }
});

checkbox2.setOnCheckedChangeListener(new OnCheckedChangeListener(){

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if(isChecked) {
            checkbox1.setChecked(false);
            checkbox3.setChecked(false);
        }
    }
});

checkbox3.setOnCheckedChangeListener(new OnCheckedChangeListener(){

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        if(isChecked) {
            checkbox1.setChecked(false);
            checkbox2.setChecked(false);
        }

    }
});

如果您需要用户只能选择其中一个选项,则可以使用单选按钮并使用无线电组。

电台组: https://developer.android.com/reference/android/widget/RadioGroup.html

答案 2 :(得分:0)

这是你可以尝试的东西。

  1. 在一个布局中包装所有复选框。
  2. 创建自定义static方法并将checkbox及其值和父布局传递给您,其中包含所有复选框。
  3. xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
    
    <data>
    
        <import type="com.example.Bindings" />
    </data>
    
    <RelativeLayout
        android:id="@+id/activity_demo"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <LinearLayout
            android:id="@+id/linearParent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
            <CheckBox
                android:id="@+id/chk1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="@{()->Bindings.setCheckbox(chk1,linearParent)}"
                android:text="1" />
    
            <CheckBox android:id="@+id/chk2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="@{()->Bindings.setCheckbox(chk2,linearParent)}"
                android:text="2" />
    
            <CheckBox android:id="@+id/chk3"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="@{()->Bindings.setCheckbox(chk3,linearParent)}"
                android:text="3" />
    
            <CheckBox android:id="@+id/chk4"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="@{()->Bindings.setCheckbox(chk4,linearParent)}"
                android:text="4" />
    
        </LinearLayout>
    
    </RelativeLayout>
    

    这是您的自定义方法

    public static void setCheckbox(CheckBox checkBox, LinearLayout parentLayout) {
        for (int i = 0; i < parentLayout.getChildCount(); i++) {
            if (parentLayout.getChildAt(i) instanceof CheckBox) {
                CheckBox child = (CheckBox) parentLayout.getChildAt(i);
                if (child.getId() != checkBox.getId())
                    child.setChecked(false);
            }
        }
    }
    

    就是这样,你完成了代码:)

答案 3 :(得分:0)

您可以使用ObservableBoolean。作为绑定,您只需使用android:checked="@={observableBoolean}"进行设置即可。使用双向数据绑定setOnCheckedChangeListener()不再起作用,但您现在已经在视图模型中拥有了这些值。

现在您只需要创建自己的广播组。这可以通过Observable.OnPropertyChangedCallback addOnPropertyChangedCallback() ObservableBoolean到您用于复选框的所有new Observable.OnPropertyChangedCallback() { private ObservableBoolean observable = new ObservableBoolean(); public void onPropertyChanged(Observable sender, int propertyId) { ObservableBoolean observable = (ObservableBoolean) sender; if (observable.get()) { this.observable.set(false); this.observable = observable; } } } 轻松实现。

=JOIN(CHAR(10),QUERY(TRANSPOSE(IMPORTRANGE(spreadsheet_key,reference_string)),,2E6))

答案 4 :(得分:0)

为了完成类似的任务,我做了以下工作:

  • 创建了一个独特的ViewModel,它添加在xml

    的数据字段中

    <import type="android.view.View"/>
    <variable
        name="viewModel"
        type="compackagename.MyViewModel" />
    

  • 在xml绑定中注意@ = {...}这称为双向绑定(从双向绑定更新变量会自动更新xml)

            <CheckBox
            android:checked="@={viewModel.checked1}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <CheckBox
            android:checked="@={viewModel.checked2}"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
  • 为MyViewModel中的每个复选框添加了ObservableBoolean字段

    public final ObservableBoolean checked1 = new ObservableBoolean();
    
  • MyViewModel构造函数中的
  • checked1.set(false);
    checked2.set(false);
    
    checked1.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable observable, int i) {
            if (checked1.get()){
                checked2.set(false);
            }
        }
    });
    checked2.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable observable, int i) {
            if (checked2.get()){
                checked1.set(false);
            }
        }
    });
    

你可以通过在列表中添加ObservableBooleans来优化这一点,但上面是一个很好的起点。