我可以在Android中对ProgressBar进行数据绑定吗?

时间:2015-07-11 18:34:54

标签: android data-binding android-seekbar

是否可以在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;它在编辑器中变成了红色)。还有另一种数据绑定方式吗?

4 个答案:

答案 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名称空间。

此解决方案适用于所有输入控件,包括自定义,因为您在模型中提供了正确的监听器。

TextWatcher Reference

答案 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"/>