Android Data Binding - как использовать ViewStub с привязкой данных
Можно ли использовать viewStubs с привязкой данных? может помочь ViewStubProxy?
Мой ток заглушки выглядит следующим образом:
<ViewStub
android:id="@+id/stub_import"
android:inflatedId="@+id/panel_import"
android:layout="@layout/progress_overlay"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="@{myobject.bottom ? bottom:top}" />
Но этот макет будет заменен, когда я буду раздувать viewStub, и как можно использовать ViewStubs с привязкой данных android?
это то, что я вижу из docs:
ViewStubs
ViewStubs немного отличаются от обычных представлений. Они начинают невидимыми, и когда они либо становятся видимыми, либо явно указаны надувать, они заменяют себя в макете, накачивая другой макета.
Поскольку ViewStub по существу исчезает из иерархии View, Просмотр в объекте привязки также должен исчезнуть, чтобы разрешить коллекция. Поскольку представления являются окончательными, объект ViewStubProxy принимает место ViewStub, предоставляя разработчику доступ к ViewStub когда он существует, а также доступ к расширенной иерархии представлений, когда ViewStub был завышен.
При раздувании другого макета необходимо установить привязку для новый макет. Поэтому ViewStubProxy должен прослушивать ViewStub ViewStub.OnInflateListener и установите привязку в это время. Поскольку существует только один, ViewStubProxy позволяет разработчику установите на нем OnInflateListener, который он вызовет после установления привязка.
Ответы
Ответ 1
Просто установите слушателя в качестве документа:
mBinding.viewStub.setOnInflateListener(new ViewStub.OnInflateListener() {
@Override
public void onInflate(ViewStub stub, View inflated) {
ViewStubBinding binding = DataBindingUtil.bind(inflated);
binding.setModel(model);
}
});
public void inflateViewStub(View view) {
if (!mBinding.viewStub.isInflated()) {
mBinding.viewStub.getViewStub().inflate();
}
}
Ответ 2
Объявите пространство имен xml и передайте переменную через это. Это работает с <include>
, также, кстати. Вот пример:
main_layout.xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:my-namespace="http://schemas.android.com/apk/res-auto">
<data>
<variable name="myData" type="com.example.SomeModel" />
</data>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ViewStub
android:id="@+id/view_stub"
android:inflatedId="@+id/view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout="@layout/another_layout"
my-namespace:data="@{myData}"
/>
</RelativeLayout>
</layout>
another_layout.xml:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<!-- No need to declare my-namespace here -->
<data>
<variable name="data" type="com.example.SomeModel" />
</data>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{data.someValue}" />
</RelativeLayout>
</layout>
Итак, теперь вам просто нужно позвонить inflate()
, и макет будет иметь данные.
Вы можете проверить сгенерированный класс привязки, чтобы проверить это. Он даже имеет тип безопасности, поэтому вы не можете передать какой-либо другой тип в data
.
Ответ 3
Я также столкнулся с этим типом проблем,
наконец, я получил решение и его безупречную работу.
ViewStub Holding Layout,
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data class="MBinding">
<variable
name="mmmmm"
type="com.vvv.bbb.fragments.MFragment" />
</data>
--------------------
--------------------
<ViewStub
android:id="@+id/stub_import"
-------------------
-------------------
<ViewStub/>
--------------------
--------------------
<layout/>
layout Inside ViewStub is,,
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data class="MViewStubLayoutBinding">
<variable
name="mmmmm"
type="com.vvv.bbb.fragments.MFragment" />
</data>
----------------
----------------
----------------
code Внутри класса есть,,
public Class KKKKKK() {
-----------------
MBinding mBinding;
MViewStubLayoutBinding mviewStubLayoutBinding;
-----------------------------
-----------------------------
mBinding.stubImport.getViewStub().setLayoutResource(R.layout.progress_overlay);
mBinding.stubImport.setOnInflateListener(new ViewStub.OnInflateListener() {
@Override
public void onInflate(ViewStub viewStub, View view) {
mviewStubLayoutBinding=DataBindingUtil.bind(view);
}
});
autoCheckBinding.vsAutoDetailsOne.getViewStub().inflate();
Ответ 4
Установите слушателя, чтобы получить доступ к раздутому макету после успешного раздувания viewStub
mBinding.viewStub.setOnInflateListener(new OnInflateListener() {
@Override
public void onInflate(ViewStub stub, View inflated) {
ViewStubBinding binding = DataBindingUtil.bind(inflated); //call after succesful inflating of viewStub
// set data here
}
});
Затем раздуйте viewStub
mBinding.viewStub.getViewStub().inflate();
Ответ 5
Просто, чтобы уточнить ответ @andrew-classen, принятый выше, а также включить ответ @user9113597:
В вашем макете, который содержит заглушку (например, my_fragment.xml)
<data class="MyDataBinding">
...
</data>
...
<ViewStub
android:id="@+id/stub_import"
... />
В вашей деятельности или фрагменте (пример ниже использует фрагмент):
MyDataBinding mBinding;
MyViewModel mViewModel;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState)
{
mBinding = DataBindingUtil.inflate(inflater, R.layout.my_fragment, container, false);
mBinding.viewStub.setOnInflateListener(new ViewStub.OnInflateListener()
{
@Override
public void onInflate(ViewStub stub, View inflated)
{
ViewDataBinding dataBinding = DataBindingUtil.bind(inflated);
binding.setVariable(BR.mViewModel, mViewModel));
}
});
}
public void inflateViewStub(View view) {
if (!mBinding.viewStub.isInflated()) {
mBinding.viewStub.getViewStub().inflate();
}
}
В вашем макете заглушки:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="mViewModel"
type="com.example.myapp.MyViewModel" />
</data>
...
Ответ 6
Еще один способ, которым я это сделал, - использование ViewStubProxy. Документация/исходный код для ViewStubProxy это хорошо.
Когда вы создаете новый ViewStubProxy, передайте его ViewStub в конструкторе. Затем ViewStubProxy.setContainingBinding(<pass in your root layout binding)
. Если вы этого не сделаете, вы получите нули.
Затем вместо установки ViewStub.setOnInflateListener(ViewStubProxy установит один для вас), установите ViewStubProxy.setOnInflateListener для установки переменных привязки и LifecycleOwner.
Образец кода:
private void setBindings(){
//usual outside layout binding steps
binding = (MeasurementsLayoutBinding) getBinding();
binding.setViewModel(viewModel());
binding.setLifecycleOwner(this);
//cartSideStubView is the root layout stubview
cartViewStubProxy = new ViewStubProxy(cartSideStubView);
cartViewStubProxy.setContainingBinding(binding);
cartViewStubProxy.setOnInflateListener(((viewStub, view) -> {
cartViewStubProxy.getBinding().setVariable(BR.viewModel, viewModel());
cartViewStubProxy.getBinding().setLifecycleOwner(this);
//after inflation you can find your viewstub views
cartHitchToFixedAxleInputField = view.findViewById(R.id.cart_hitch_to_fixed_axle_input_field);
}));
}