有没有将viewStubs与dataBinding一起使用?可以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 dataBinding一起使用?
这是我从docs看到的:
ViewStubs
ViewStubs与普通视图略有不同。他们开始了 看不见的,当它们被显示或被明确告知时 为了膨胀,他们通过膨胀另一个来替换自己的布局 布局。
因为ViewStub基本上从View层次结构中消失, 绑定对象中的视图也必须消失才能允许 采集。因为视图是最终的,所以ViewStubProxy对象需要 ViewStub的位置,使开发人员可以访问ViewStub 当它存在时,还可以访问膨胀的View层次结构 ViewStub已被夸大。
在为另一个布局充气时,必须为其建立绑定 新版面。因此,ViewStubProxy必须监听ViewStub ViewStub.OnInflateListener并在那时建立绑定。 由于只有一个可以存在,ViewStubProxy允许开发人员 在它上面设置一个OnInflateListener,它将在建立后调用 绑定。
答案 0 :(得分:15)
只需按照文档说明设置监听器:
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();
}
}
答案 1 :(得分:1)
声明你的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
。
答案 2 :(得分:1)
我也遇到过这类问题, 最后我得到了一个解决方案和完美的工作。
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/>
布局ViewStub内部是,,,
<?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>
----------------
----------------
----------------
类中的代码是,,,
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();
答案 3 :(得分:0)
设置侦听器,以便在成功膨胀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();
答案 4 :(得分:0)
只需详细说明@andrew-classen's accepted answer above,并同时包含@user9113597's answer:
在包含存根的布局中(例如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>
...
答案 5 :(得分:0)
我这样做的另一种方法是使用ViewStubProxy。 ViewStubProxy的文档/源代码很好。
创建新的ViewStubProxy时,请在构造函数中传入ViewStub。然后ViewStubProxy.setContainingBinding(<pass in your root layout binding)
。如果不这样做,您将得到null。
然后,不要设置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);
}));
}
答案 6 :(得分:0)
如果您使用的是ViewModels,则还需要为膨胀视图设置生命周期所有者。切记在片段/活动视图期间设置与mBinding变量相同的所有者。
mBinding.viewStub.setOnInflateListener(new ViewStub.OnInflateListener() {
@Override
public void onInflate(ViewStub stub, View inflated) {
ViewStubBinding binding = DataBindingUtil.bind(inflated);
binding.setModel(model);
binding.setLifeCycleOwner(this) // setLifeCycleOwner
}
});
public void inflateViewStub(View view) {
if (!mBinding.viewStub.isInflated()) {
mBinding.viewStub.getViewStub().inflate();
}
}
希望这对某人有所帮助。
答案 7 :(得分:-1)
可以通过使用
随时访问绑定layout_binding.viewStub.binding
,然后将其转换为布局的生成的Binding类
(layout_bindinng.viewStub.binding as YourLayoutBinding).viewModel = viewModel
请谨慎进行null检查,因为在充气之前它将为null。