我的库模块中有一个抽象的BaseActivity:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Normal method to inflate the layout
mBinding = DataBindingUtil.setContentView(this, R.layout.base_view_stub_layout);
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
if (mBinding != null && mBinding.viewStub != null && mBinding.viewStub.getViewStub() != null) {
mBinding.viewStub.getViewStub().setLayoutResource(getLayoutId());
}
if (!hasStubInflated) {
View inflatedView = mBinding.viewStub.getViewStub().inflate();
//Abstract method
onViewStubInflated(inflatedView, savedInstanceState);
//Normal method to hide progress bar
onViewStubInflated();
}
initControllers();
handleViews();
setListeners();
restoreValues(savedInstanceState);
}
AppModule的MainActivity扩展了库模块的BaseActivity,因此可以获取一个抽象方法来覆盖:
MainActivity扩展了BaseActivity
private ActivityMainBinding mBinding;
@Override
public int getLayoutId() {
return R.layout.activity_main;
}
@Override
public void onViewStubInflated(View inflatedView, Bundle savedInstanceState) {
if (mBinding == null || mBinding.getRoot() != inflatedView) {
mBinding = ActivityMainBinding.bind(inflatedView);
}
}
运行该应用程序时,我得到:
Caused by: java.lang.RuntimeException: view must have a tag
at com.example.android.emailapp.DataBinderMapperImpl.getDataBinder(DataBinderMapperImpl.java:67)
at androidx.databinding.MergedDataBinderMapper.getDataBinder(MergedDataBinderMapper.java:74)
at androidx.databinding.DataBindingUtil.bind(DataBindingUtil.java:199)
at androidx.databinding.ViewDataBinding.bind(ViewDataBinding.java:693)
at com.example.android.emailapp.databinding.ActivityMainBinding.bind(ActivityMainBinding.java:99)
at com.example.android.emailapp.databinding.ActivityMainBinding.bind(ActivityMainBinding.java:87)
at com.example.android.emailapp.login.MainActivity.onViewStubInflated(MainActivity.java:86)
at com.library.android.common.ui.baseui.BaseActivity.onCreate(BaseActivity.java:52)
请注意,我在BaseActivity和MainActivity的xml中都具有布局标签。
我尝试了this,但没有成功。
mBinding.viewStub.getViewStub()。setLayoutResource(getLayoutId())是否存在问题,因为它将尝试从AppModule获取布局?那,我该怎么解决?
如果您知道答案,请尝试解释为什么会出现这种情况以及解决方案...
已尝试
答案 0 :(得分:0)
如果您将自定义类用作your_layout.xml
的根视图,则必须覆盖所有视图构造器
class MyCustomView : FrameLayout {
constructor(context: Context) : super(context){
...
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs){
...
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr){
...
}
}
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="viewModel" type="......" />
</data>
<MyCustomView
android:layout_width="match_parent"
android:layout_height="match_parent">
</MyCustomView>
</layout>
答案 1 :(得分:0)
您还必须用 <layout></layout>
包装 viewStub 的布局,这正是他们所期望的:要么到处使用 DataBinding,要么根本不使用。
如果您不想在 viewStub 上使用 DataBinding,则需要做额外的工作。
例如,如果 itemData
是我的列表视图的 DataBindingImpl 对象,并且我要膨胀某种 more options
覆盖视图存根,那么我需要自己存储膨胀的视图,并避免访问`DataBinding 的 ViewStubProxy 的 mRoot 字段
ViewGroup inflated = (ViewGroup) itemData.someView.getTag();
if(inflated==null) {
ViewStub stub = itemData.viewStubProxy.getViewStub();
if(stub!=null) {
stub.setOnInflateListener(null);
inflated = (ViewGroup) stub.inflate();
// what I need is simply to set onClickListener on all of it's children. (one for-loop inside)
Utils.setOnClickListenersOneDepth(inflated, onClickListener, 3, null);
itemData.someView.setTag(inflated);
}
}
if(inflated!=null) {
// what I need then is to animate the overlay.
View mRoot = inflated;
int width = itemData.getRoot().getWidth();
mRoot.setAlpha(0);
mRoot.setTranslationX(width/3);
mRoot.animate().alpha(1);
mRoot.animate().translationX(0);
}
永远不要调用 itemData.viewStubProxy.getViewStub().getRoot()
、.isInflated()
左右,因为我们现在将 inflated
存储在 DataBindingImpl 对象之外。