Android 使用RecyclerView进行数据绑定,其中每个项目都有复选框
我有RecyclerView,其中每个项目表示、复选框和编辑文本 单击复选框时,EditText的文本应划破, 我有一个完整的文件 我在app:checkBoxChangeListener=“@{article.complete}”中使用了它 app:itemplete=“@{article.complete}” 除非我滚动RecyclerView,然后单击另一个项目的文本被删除的复选框,否则它是有效的Android 使用RecyclerView进行数据绑定,其中每个项目都有复选框,android,android-recyclerview,android-databinding,Android,Android Recyclerview,Android Databinding,我有RecyclerView,其中每个项目表示、复选框和编辑文本 单击复选框时,EditText的文本应划破, 我有一个完整的文件 我在app:checkBoxChangeListener=“@{article.complete}”中使用了它 app:itemplete=“@{article.complete}” 除非我滚动RecyclerView,然后单击另一个项目的文本被删除的复选框,否则它是有效的 @BindingAdapter("itemComplete") public static
@BindingAdapter("itemComplete")
public static void bindItemComplete(EditText itemInput, boolean complete){
itemInput.setPaintFlags(complete ?
(itemInput.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG) : 0);
}
Article.java
public class Article{
public final ObservableBoolean complete = new ObservableBoolean();
}
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">
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="se.ica.handla.articles.ArticleListViewModel" />
<variable
name="article"
type="se.ica.handla.models.articles.Article" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<EditText
android:id="@+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:itemComplete="@{article.complete}"
/>
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={article.complete}" />
</android.support.constraint.ConstraintLayout>
</layout>
如我在评论中所述,我建议您使用双向数据绑定 您可以完全删除此
BindingAdapter
:
@BindingAdapter(value = {"checkBoxChangeListener", "article"}, requireAll = false)
public static void bindCheckBox(CheckBox view, final ObservableBoolean checked, Article article) {
if (view.getTag(R.id.binded) == null) {
//Here you are setting the attributes to your *view* and
//decouple it from your article. It does not reference it,
//the properties (isChecked) isnow on the view.
//So when your view gets recycled when you scroll,
//it still has the property you set the last time -
//and not from your current article, which is displayed now in the view.
view.setTag(R.id.binded, true);
view.setOnCheckedChangeListener((buttonView, isChecked) -> checked.set(isChecked));}
}
}
正如您已经发现的,您的xml现在应该是这样的,使用双向数据绑定:
<EditText
android:id="@+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:itemComplete="@{article.complete}"
/>
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={article.complete}" //@={} for Two-Way Databinding
/>
如我在评论中所述,我建议您使用双向数据绑定 您可以完全删除此
BindingAdapter
:
@BindingAdapter(value = {"checkBoxChangeListener", "article"}, requireAll = false)
public static void bindCheckBox(CheckBox view, final ObservableBoolean checked, Article article) {
if (view.getTag(R.id.binded) == null) {
//Here you are setting the attributes to your *view* and
//decouple it from your article. It does not reference it,
//the properties (isChecked) isnow on the view.
//So when your view gets recycled when you scroll,
//it still has the property you set the last time -
//and not from your current article, which is displayed now in the view.
view.setTag(R.id.binded, true);
view.setOnCheckedChangeListener((buttonView, isChecked) -> checked.set(isChecked));}
}
}
正如您已经发现的,您的xml现在应该是这样的,使用双向数据绑定:
<EditText
android:id="@+id/editText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
app:itemComplete="@{article.complete}"
/>
<CheckBox
android:id="@+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="@={article.complete}" //@={} for Two-Way Databinding
/>
So。。在bindCheckBox
中,您想设置articles属性complete
,对吗?也许你可以用它来实现这一点<代码>数据绑定适用于这么多人-这可能是您的一个错误complete是可以观察到的一种实现双向绑定的方法,我在app中使用complete:checkBoxChangeListener=“@{article.complete}”作为复选框,在EditText中使用app:itemComplete=“@{article.complete}”,它可以工作滚动时出现问题滚动时出现错误,因为您将complete
设置为视图,而不是文章(view.setTag()…
)。而且由于RecyclerView
中的视图被回收,因此当您滚动时,这些值会被弄乱。我看到的最简单的方法是使用双向数据绑定
。你为什么不想使用它?@Amylinn我已经更新了我的问题并发布了我的解决方案。它是有效的,但我不明白你提到使用view.setTag()的方式,请让我知道。我只是引用了你的代码来让它更清楚-如果这让你感到困惑,很抱歉。我很高兴它现在起作用了。我会加上它作为一个答案,也许我可以让你更清楚。另外,请不要用解决方案编辑您的问题代码,它会为其他用户隐藏问题,并会混淆他们。因此。。在bindCheckBox
中,您想设置articles属性complete
,对吗?也许你可以用它来实现这一点<代码>数据绑定
适用于这么多人-这可能是您的一个错误complete是可以观察到的一种实现双向绑定的方法,我在app中使用complete:checkBoxChangeListener=“@{article.complete}”作为复选框,在EditText中使用app:itemComplete=“@{article.complete}”,它可以工作滚动时出现问题滚动时出现错误,因为您将complete
设置为视图,而不是文章(view.setTag()…
)。而且由于RecyclerView
中的视图被回收,因此当您滚动时,这些值会被弄乱。我看到的最简单的方法是使用双向数据绑定
。你为什么不想使用它?@Amylinn我已经更新了我的问题并发布了我的解决方案。它是有效的,但我不明白你提到使用view.setTag()的方式,请让我知道。我只是引用了你的代码来让它更清楚-如果这让你感到困惑,很抱歉。我很高兴它现在起作用了。我会加上它作为一个答案,也许我可以让你更清楚。另外,请不要用解决方案编辑您的问题代码,它会为其他用户隐藏问题,并会让他们感到困惑。是的,我明白了,但是对于这个示例,android:checked=“@={article.complete}”@={}与android:checked是标准属性一样工作,但当我想为自定义属性app:focus尝试它时,我无法使用@={}app:focus@{article.focus}“我有这个方法,当滚动@BindingAdapter(“focus”)public static void bindFocus(EditText itemInput,ObservableBolean focus){if(focus.get()){itemInput.requestFocus();}else{itemInput.clearFocus();}时,我面临同样的问题你需要一个InverseBindingAdapter
来定制双向数据绑定。你可以查看这个主题。是的,我明白了,但是对于这个例子,android:checked=“@={article.complete}”@={}与android:checked是标准属性一样工作,但是当我想尝试定制属性app:focus时,我不能使用@={}app:focus=“@{article.focus}”我有这个方法,当滚动@BindingAdapter(“focus”)公共静态void bindFocus(EditText itemInput,ObservableBolean focus){if(focus.get()){itemInput.requestFocus();}else{itemInput.clearFocus();}时,我面临同样的问题您需要一个用于自定义双向数据绑定的InverseBindingAdapter
。您可以查看此主题。