Как можно, чтобы выражение привязки данных реагировало на изменения в тексте редактирования в том же макете? - PullRequest
0 голосов
/ 25 сентября 2018

Предположим, у меня есть EditText с идентификатором foo.В другом месте того же ресурса макета у меня есть Button, и я хочу включить Button, только если в EditText.

есть текст. Я думал, что это будет работать:

        <Button
            android:id="@+id/bar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{listener}"
            android:text="Um, hi!"
            android:enabled="@{foo.text.length > 0}" />

Сгенерированный класс привязки действительно вызывает setEnabled() для bar в зависимости от длины текста в foo ... но только при вызове executeBindings().Кажется, это не называется пользовательскими типами, поэтому включенное состояние моего Button не изменяется в зависимости от ввода пользователем текста в EditText.

. Я могу обойти это, но этоТакое ощущение, что это должно работать.Я что-то упускаю?Это известное ограничение?

1 Ответ

0 голосов
/ 25 сентября 2018

Обновление

Просто измените foo.text.length на foo.text.length().


Старое решение

Некоторые моменты, возможно, которые вы упустили.

1.Используя BaseObservable

Если ваш model extends BaseObservable, то вам нужно сделать food.text @Bindable.

public class UserBaseObservable extends BaseObservable {
    private String name;

    @Bindable
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }
}

Причина существо, когда вы используете text.length, тогда вам нужно вызывать все зависимые элементы при его изменении.Потому что text.length не наблюдается, поэтому вам нужно вызвать его вручную.Сгенерированный класс привязки вызывает setName(value), но не меняет text.length зависимых представлений.

2.Использование MutableLiveData

Если вы используете MutableLiveData, то необходимо предоставить LifeCycleOwner

    binding.setLifecycleOwner(this);

3.Использование ObservableField (кратчайший подход)

Еще один простой подход - использовать ObservableField для foo.text

Я сказал просто , потому что вам не нужно делатьэто поле Bindable в данном случае.

public class UserObservableField {
    private ObservableField<String> name = new ObservableField<>();

    public ObservableField<String> getName() {
        return name;
    }

    public void setName(ObservableField<String> name) {
        this.name = name;
    }
}

Я создал образец с 3 из этих решений, все работают!

activity_login.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    >

    <data>

        <variable
            name="userObservableField"
            type="com.innovanathinklabs.sample.activities.LoginActivity.UserObservableField"/>

        <variable
            name="userMutable"
            type="com.innovanathinklabs.sample.activities.LoginActivity.UserMutable"/>

        <variable
            name="userBaseObservable"
            type="com.innovanathinklabs.sample.activities.LoginActivity.UserBaseObservable"/>

    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:padding="20dp">

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="Enter your name"
            android:text="@={userObservableField.name}"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="@{userObservableField.name.length()>0}"
            android:text="Proceed"/>

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="Enter your name"
            android:text="@={userMutable.name}"
            />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="@{userMutable.name.length()>0}"
            android:text="Proceed"/>

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:hint="Enter your name"
            android:text="@={userBaseObservable.name}"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="@{userBaseObservable.name.length()>0}"
            android:text="Proceed"/>

    </LinearLayout>
</layout>

LoginActivity.java

public class LoginActivity extends AppCompatActivity {
    ActivityLoginBinding binding;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_login);
        binding.setLifecycleOwner(this); // necessary for LiveData to work
        binding.setUserObservableField(new UserObservableField());
        binding.setUserBaseObservable(new UserBaseObservable());
        binding.setUserMutable(new UserMutable());
    }

    public static class UserObservableField {
        private ObservableField<String> name = new ObservableField<>();

        public ObservableField<String> getName() {
            return name;
        }

        public void setName(ObservableField<String> name) {
            this.name = name;
        }
    }


    public static class UserBaseObservable extends BaseObservable {
        private String name;

        // necessary for updating button
        @Bindable
        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
            notifyPropertyChanged(BR.name);
        }
    }


    public static class UserMutable {
        private MutableLiveData<String> name = new MutableLiveData<>();

        public MutableLiveData<String> getName() {
            return name;
        }

        public void setName(MutableLiveData<String> name) {
            this.name = name;
        }
    }
}

Я поместил все модели в Activity.Я попытался объяснить хорошо, тем не менее, вы можете комментировать, если у вас есть путаница.

Вывод

output image

...