是否可以在Android中对SeekBar或ProgressBar使用数据绑定?我有这个数据元素:
<data>
<variable
name="foo"
type="com.example.Foo" />
</data>
如果我在TextField中引用变量foo.bar(这是一个int),它会按预期工作:
<TextView
android:text="@{String.valueOf(foo.bar)}"
[...]
我试图做的是:
<SeekBar
android:progress="@{foo.bar}"
[...]
但它没有得到认可。 (一旦我在引号之间写了一个&#34; @&#34;它在编辑器中变成了红色)。还有另一种数据绑定方式吗?
答案 0 :(得分:12)
要在SeekBar更改时更新TextView,请通过android:onProgressChanged
属性绑定到进度更改。这期望模型中的公共方法具有SeekBarBindingAdapter.OnProgressChanged
:
查看强>
<TextView
android:text="{@model.seekBarValue} />
<SeekBar
android:onProgressChanged="@{model.onValueChanged}" />
<强>模型强>
public class Model {
public ObservableField<String> seekBarValue = new ObservableField<>("");
public void onValueChanged(SeekBar seekBar, int progresValue, boolean fromUser) {
seekBarValue.set(progresValue + "");
}
}
一般情况下,我建议您查看为数据绑定所做的所有Adapter类的源代码。例如,如果您导航到Android Studio中的文件SeekBarBindingAdapter.java
(菜单导航&gt;文件),您将学习可以通过适配器绑定到的所有事件方法。由于Google已实施以下适配器,因此可以使用此特定功能:
@BindingAdapter("android:onProgressChanged")
public static void setListener(SeekBar view, OnProgressChanged listener) {
setListener(view, null, null, listener);
}
答案 1 :(得分:4)
如果它对某人有帮助,这个问题会在搜索中大量出现,现在可以使用双向数据绑定来完成。我在下面使用了两个可绑定值,我倾向于在XML本身中不使用显示逻辑,但我怀疑它只能用于一个。
在 ViewModel 中创建可绑定值,一个用于SeekBar
( seekValue ),另一个用于TextView
( seekDisplay )
int mSeekValue;
int mSeekDisplay;
@Bindable
public int getSeekValue() {
return mSeekValue;
}
public void setSeekValue(int progress) {
mSeekValue = progress;
notifyPropertyChanged(BR.seekValue);
setSeekDisplay(progress);
}
@Bindable
public String getSeekDisplay() {
return Integer.toString(mSeekDisplay);
}
public void setSeekDisplay(int progress) {
mSeekDisplay = progress;
notifyPropertyChanged(BR.seekDisplay);
}
现在您可以将这些绑定到Widget
。
<SeekBar
android:id="@+id/my_seek"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:progress="@={viewModel.seekValue}" />
<TextView
android:id="@+id/my_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@{viewModel.seekDisplay}" />
需要注意的要点是,您使用SeekBar
在@={viewModel.seekValue}
上使用双向数据绑定,这将调用您的setSeekValue(...)
方法。< / p>
一个名为,它会通过调用TextView
setSeekDisplay(...)
答案 2 :(得分:2)
@George Mount是正确的,你必须在你的Model或Handler类中定义的layout xml中添加一个处理程序(无论你怎么称呼它)。
看看我对这个问题的答案,看一个完整的例子:
Two way databinding with Android Databinding Library
这是答案的例子:
示例:
public class AmanteEditModel extends BaseObservable {
private String senhaConfirm;
@Bindable
public String getSenhaConfirm() {
return senhaConfirm;
}
public void setSenhaConfirm(String senhaConfirm) {
this.senhaConfirm = senhaConfirm;
notifyPropertyChanged(BR.senhaConfirm);
}
// Textwatcher Reference: http://developer.android.com/reference/android/text/TextWatcher.html
public TextWatcher getMyEditTextWatcher() {
return new TextWatcher() {
public void afterTextChanged(Editable s) {
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
// Important! Use the property setter, otherwhise the model won't be informed about the change.
setSenhaConfirm(s);
}
};
}
}
在你的布局中,xml将EditText更改为:
<EditText
android:id="@+id/amante_edit_senha_confirm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:hint="Confirme a senha"
android:inputType="textPassword"
android:maxLines="1"
android:text="@{model.senhaConfirm}"
app:addTextChangeListener="@{model.myEditTextWatcher}"
/>
注意 addTextChangeListener 的命名空间。这个方法可能无法通过android:namespace获得,所以我正在使用app:here。您也可以使用bind:使绑定更清晰。
所以不要错过添加
xmlns:app="http://schemas.android.com/apk/res-auto"
或
xmlns:bind="http://schemas.android.com/apk/res-auto"
到您的XML名称空间。
此解决方案适用于所有输入控件,包括自定义,因为您在模型中提供了正确的监听器。
答案 3 :(得分:0)
那么您可能需要使用如下所示的双向绑定。
添加绑定utils类
private static final String ANDROID_PROGRESS = "android:progress";
@BindingAdapter(ANDROID_PROGRESS)
public static void setSeekbarProgress(SeekBar seekBar, int progress) {
try {
seekBar.setProgress(progress);
} catch (Resources.NotFoundException nfe) {
nfe.printStackTrace();
}
}
@InverseBindingAdapter(attribute = ANDROID_PROGRESS)
public static int getSeekbarProgress(SeekBar seekBar) {
try {
return seekBar.getProgress();
} catch (Resources.NotFoundException nfe) {
nfe.printStackTrace();
return 0;
}
}
添加视图模型中的可观察对象
var child1Age = ObservableField(1)
在布局中
<SeekBar
android:id="@+id/child1_age_sb"
style="@style/HotelChildAgeSeekBarStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_14"
android:progress="@={vm.child1Age}"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/childs_age_label" />
<TextView
android:layout_marginTop="@dimen/spacing_6"
android:id="@+id/child1_age_value"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintTop_toBottomOf="@+id/child1_age_sb"
app:layout_constraintLeft_toLeftOf="@id/child1_age_sb"
app:layout_constraintRight_toRightOf="@id/child1_age_sb"
android:text="@{String.valueOf(vm.child1Age)}"
android:textColor="@color/black_medium"
android:textSize="@dimen/font_14"/>