/ / Jak przekazać ObservableField wewnątrz kontroli wewnętrznej - java, android, powiązanie danych, powiązanie danych z Androidem

Jak przekazać ObservableField wewnątrz kontroli wewnętrznej - java, android, powiązanie danych, wiązanie danych android

Główny model widoku wygląda tak:

class MainVM{
public ObservableField<String> title;
public ObservableField<Boolean> isFlexible;
}

główny układ wygląda tak:

<layout>
<date><variable name="item" type="MainVM"></data>
<LinearLayout>
<TextView text="@{item.title}"/>
<CustomCtrl1 vm="@{item.isFlexible}">
</LinearLayout>
</layout>

i CustomCtrlUkład „wygląda trochę jak

   <layout>
<date><variable name="item" type="boolean"></data>
<LinearLayout>
...
<Switch checked="@{item}"/>
...
</LinearLayout>
</layout>

Problemem jest ObservableField od MainVM konwertuj wartość s na wartość boolowską po przekazaniu do CustomCtrl i po zmianie wartości logicznej wewnątrz CustomCtrl nie wpływaj MainVM„s. Pierwszym pomysłem była zmiana CustomCtrl"s viewmodel z Boolean do ObservableField<Boolean> ale z jakiegoś powodu nie jest to dozwolone.

Więc pytanie brzmi - jaki jest właściwy sposób przekazywania ObservableField wewnątrz kontroli wewnętrznej.

Odpowiedzi:

1 dla odpowiedzi № 1

Najlepszym sposobem na to jest użycie wiązania dwukierunkowegobezpośrednio. Wymaga to Android Studio 2.1 i nowszych. Android Studio 2.2 naprawia błąd inflacyjny, który możesz trafić za pomocą niestandardowych kontrolek. Jeśli użyłbyś dołączenia zamiast kontrolki niestandardowej, byłoby to dość trywialne:

<layout>
<date><variable name="item" type="MainVM"></data>
<LinearLayout>
<TextView android:text="@{item.title}"/>
<include layout="@layout/other" app:vm="@={item.isFlexible}">
</LinearLayout>
</layout>

I inny układ:

<layout>
<date><variable name="item" type="boolean"></data>
<LinearLayout>
...
<switch android:checked="@={item}"/>
...
</LinearLayout>
</layout>

Dzięki niestandardowej kontroli musisz zaimplementować słuchacza samodzielnie. Oznacza to, że musisz mieć słuchacza dla nieruchomości. Myślę, że to powinno zadziałać (jestem teraz na tablecie, więc nie mogę „zweryfikować”):

@InverseBindingMethods({
InverseBindingMethod(type = CustomControl.class, attribute="vm")})
public class CustomCtrl extends View {
private CustomCtrlBinding binding;
private InverseBindingAdapter listener;

public CustomCtrl(...) {
binding = ...
binding.addOnPropertyChangedCallback(new OnPropertyChangedCallback() {
@Overriide
public void OnPropertyChanged(Observable sender, int propertyId) {
if (listener != null) {
listener.onChange();
}
}
});
}

@Bindable
public boolean getVm() { return binding.getItem(); }

public void setVm(boolean vm) {
binding.setItem(vm);
}

@BindingAdapter("vmAttrChanged")
public static void setListener(CustomCtrl view,
InverseBindingListener listener) {
view.listener = listener;
}
}

Następnie masz powiązanie dwukierunkowe:

<layout>
<date><variable name="item" type="MainVM"></data>
<LinearLayout>
<TextView android:text="@{item.title}"/>
<CustomCtrl app:vm="@={item.isFlexible}">
</LinearLayout>
</layout>

I niestandardowy układ sterowania:

<layout>
<date><variable name="item" type="boolean"></data>
<LinearLayout>
...
<switch android:checked="@={item}"/>
...
</LinearLayout>
</layout>

Normalnie napisałbym niestandardową kontrolkę, która miała swój własny detektor dla atrybutu, ale InverseBindingListener działa w szczyptę.