我在活动类中有一个ObservableBoolean
字段,它与我的ToggleButton
的"checked"属性绑定,如下所示:
android:checked="@{activity.editing}"
我本希望这将创建一个按钮和布尔值之间的双向关系,但它只能从字段传递更改到按钮,而不能反过来。我做错了什么,或者这不在 DataBinding
的范围内?
我在活动类中有一个ObservableBoolean
字段,它与我的ToggleButton
的"checked"属性绑定,如下所示:
android:checked="@{activity.editing}"
我本希望这将创建一个按钮和布尔值之间的双向关系,但它只能从字段传递更改到按钮,而不能反过来。我做错了什么,或者这不在 DataBinding
的范围内?
你需要再加一个等号告诉Android你想要使用双向数据绑定:
android:checked="@={activity.editing}"
您可以在George Mount的WordPress文章中找到更多关于双向数据绑定的信息:
双向数据绑定
Android并不免疫典型的数据录入,将用户输入的更改反映回模型通常很重要。例如,如果以上数据在联系表单中,则很好地将编辑后的文本推回模型,而无需从EditText提取数据。这是如何做到的:
<layout ...>
<data>
<variable type="com.example.myapp.User" name="user"/>
</data>
<RelativeLayout ...>
<EditText android:text="@={user.firstName}" .../>
</RelativeLayout>
</layout>
很不错,是吗?唯一的区别在于这个表达式标记为
@={}
而不是@{}
。预计大多数数据绑定仍将是单向的,我们不希望创建所有这些监听器并观察永远不会发生变化的内容。
public class User{
private boolean checked;
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
}
在您的 ToggleButton
上执行双向绑定。
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={user.checked}"/>
binding.getUser().isChecked()
isChecked()
方法中缺少了@Bindable
注解,而且在setter方法中也没有调用notifyPropertyChanged(BR.checked)
。 - saiyancoder以下是设置数据绑定中的 OnCheckedChangeListener 的方法:
在布局文件中设置
<variable
name="activity"
type="com.innovanathinklabs.sample.activities.CalendarActivity"/>
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={model.checked}"
android:onCheckedChanged="@{activity::onGenderChanged}"
/>
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityCalendarBinding>(this, R.layout.activity_calendar)
binding.activity = this
binding.model = Model()
}
fun onGenderChanged(buttonView: CompoundButton, isChecked: Boolean) {
println("buttonView = [$buttonView], isChecked = [$isChecked]")
}
}
<variable
name="model"
type="com.innovanathinklabs.sample.data.Model"/>
<variable
name="activity"
type="com.innovanathinklabs.sample.activities.HomeActivity"/>
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={model.checked}"
android:onCheckedChanged="@{(button, bool)-> activity.saveGender(bool)}"
/>
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityCalendarBinding>(this, R.layout.activity_calendar)
binding.activity = this
binding.model = Model()
}
fun saveGender(isChecked: Boolean) {
println("isChecked = [$isChecked]")
}
}
OnCheckedChangeListener
匿名类传递给布局<variable
name="onGenderChange"
type="android.widget.CompoundButton.OnCheckedChangeListener"/>
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={model.checked}"
android:onCheckedChanged="@{onGenderChange}"
/>
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityCalendarBinding>(this, R.layout.activity_calendar)
binding.model = Model()
binding.setOnGenderChange { buttonView, isChecked ->
println("buttonView = [$buttonView], isChecked = [$isChecked]")
}
}
}
OnCheckedChangeListener
<variable
name="onGenderChange2"
type="android.widget.CompoundButton.OnCheckedChangeListener"/>
<ToggleButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={model.checked}"
android:onCheckedChanged="@{onGenderChange2}"
/>
活动
class HomeActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = DataBindingUtil.setContentView<ActivityCalendarBinding>(this, R.layout.activity_calendar)
binding.model = Model()
binding.onGenderChange2 = onGenderChange
}
private val onGenderChange: CompoundButton.OnCheckedChangeListener = CompoundButton.OnCheckedChangeListener { buttonView, isChecked ->
println("buttonView = [$buttonView], isChecked = [$isChecked]")
}
}
因为你无法在一个组件上设置两个回调函数。由于双向绑定已经设置了一个回调函数,所以你的回调函数将不起作用。
binding.toggleButton.setOnCheckedChangeListener { buttonView, isChecked ->
println("buttonView = [$buttonView], isChecked = [$isChecked]")
}
查看 CompoundButtonBindingAdapter 类 以了解 Switch 绑定的工作方式。
import android.databinding.BaseObservable;
import android.databinding.Bindable;
public class Item extends BaseObservable {
private Boolean checked;
@Bindable
public Boolean getChecked() {
return this.checked;
}
public void setChecked(Boolean checked) {
this.checked = checked;
notifyPropertyChanged(BR.checked);
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
public Item item;
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
item = new Item();
item.setChecked(true);
/* By default, a Binding class will be generated based on the name of the layout file,
converting it to Pascal case and suffixing “Binding” to it.
The above layout file was activity_main.xml so the generate class was ActivityMainBinding */
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
binding.setItem(item);
}
public void button_onClick(View v) {
item.setChecked(!item.getChecked());
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="item"
type="com.example.abc.twowaydatabinding.Item" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Switch
android:id="@+id/switch_test"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={item.checked}" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="change"
android:onClick="button_onClick"/>
</LinearLayout>
</layout>
build.gradle:
android {
...
dataBinding{
enabled=true
}
}
源文件文档:https://developer.android.com/topic/libraries/data-binding/index.html
该文档介绍了Android中数据绑定库的使用方法和优势。通过数据绑定,您可以将UI组件与应用程序数据模型绑定在一起,从而确保UI组件及时反应数据模型的变化。数据绑定还提供了类型安全、可读性好且易于维护的代码,以及减少手动更新UI的工作量等优点。