【发布时间】:2015-11-26 02:09:12
【问题描述】:
我正在试用新的 Android 数据绑定库 (1.0-rc1),我已经创建了一个包含三个字符串字段(姓名、电子邮件和年龄)的用户对象,并将它们链接到 3 个 EditTexts在我的布局中。
在第一个字段(名称)上,我放置了一个 TextWatcher。一切似乎都运作良好。我通过在允许它调用 setName 之前检查文本是否不同来阻止名称字段中的 notifyPropertyChanged 循环。
问题是,每次我在名称字段中键入时,光标都会在每个字符后重置到 EditText 的左侧。我四处搜寻解决方案,但大多数针对光标问题的修复建议都说要获取对 EditText 的引用并手动调整光标位置。但我想避免这样做,因为我需要 findViewByID 到 EditText 并且数据绑定的重点是尽量避免这样做。感谢您的帮助。
我的布局是这样的:
<layout>
<data>
<variable name="user" type="com.carlpoole.databindingstest.User"/>
</data>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:id="@+id/name"
android:text="@{user.name}"
bind:addTextChangedListener="@{user.nameChanged}"
/>
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:id="@+id/email"
android:layout_below="@+id/name"
android:text="@{user.email}"/>
<EditText
android:layout_width="200dp"
android:layout_height="wrap_content"
android:id="@+id/age"
android:layout_below="@+id/email"
android:text="@{user.age}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/age"
android:text="@{user.name}"/>
</RelativeLayout>
我的用户对象如下所示:
import android.databinding.BaseObservable;
import android.databinding.Bindable;
import android.text.Editable;
import android.text.TextWatcher;
public class User extends BaseObservable {
private String name;
private String email;
private String age;
public User(String name, String email, String age) {
this.name = name;
this.email = email;
this.age = age;
}
public User(){};
@Bindable
public String getName() {
return name;
}
@Bindable
public String getEmail() {
return email;
}
@Bindable
public String getAge() {
return age;
}
public final TextWatcher nameChanged = new TextWatcher() {
@Override
public void afterTextChanged(Editable s) {
if(!s.toString().equalsIgnoreCase(name))
setName(s.toString());
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
};
public void setName(String name) {
this.name = name;
notifyPropertyChanged(com.carlpoole.databindingstest.BR.name);
}
public void setEmail(String email) {
this.email = email;
}
public void setAge(String age) {
this.age = age;
}
}
我的活动如下所示
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import com.carlpoole.databindingstest.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User user = new User("Carl Poole", "mail@carlpoole.com", "26");
binding.setUser(user);
}
}
【问题讨论】:
-
“我阻止了名称字段中的 notifyPropertyChanged 循环,方法是在允许它调用 setName 之前检查文本是否不同”——但是,如果我是一个赌徒,我会那样做这就是导致您的光标问题的原因。为什么首先要有
TextWatcher? -
@CommonsWare TextWatcher 侦听 EditText 中的更新,以便它可以触发对 User 对象中 name 变量的更新。没有它,它不会知道。如果我从 afterTextChanged 方法中删除 setName 调用,它似乎工作正常,所以问题可能是由我使用数据绑定库的方式引起的
-
“没有它,它不会知道”——当用户告诉你更新模型时更新模型(点击“完成”按钮,通过 HOME 离开活动等)。
-
@carlpoole 这对我来说是一个很棒的答案,尽管这是一个问题。非常感谢您发布整个解决方案。我能够查看它并让我的数据绑定正常工作,但我在任何地方都找不到任何其他如此清晰的示例。我搜索了书籍、SO、谷歌、android 文档。唷...我永远不会让那些时间回来。 SuperMegaUpvote 以获得清晰而详细的问题答案。 :)
标签: android data-binding 2-way-object-databinding