如何解决ViewStub 元素找不到 BindingAdapter
我有一个带有 ViewStub 的 XML 布局。我创建了一个绑定适配器 setLayout
来设置 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>
<import type="android.view.View"/>
<variable
name="viewModel"
type="com.smellydogcoding.westvirginiaelectronicfieldguidedistrict.ui.codeDetail.CodeDetailViewModel" />
</data>
<ScrollView
android:id="@+id/codeDetailsScrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ViewStub
android:id="@+id/retailfood_viewStub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"
app:setLayout="@{viewModel.searchRuleset}"
app:viewModel="@{viewModel}"/>
</LinearLayout>
</ScrollView>
</layout>
绑定适配器
// set the layout for code details ViewStub
@BindingAdapter("setLayout")
fun ViewStub.setLayout(rule: String) {
layoutResource = when (rule) {
"retailfood" -> R.layout.stub_code_details_retail_food
"general" -> R.layout.stub_code_details_general
"recwater" -> R.layout.stub_code_details_recwater
"citations" -> R.layout.stub_code_details_citations
else -> R.layout.stub_code_details_other
}
}
我在生成的绑定文件中不断收到错误:
cannot find symbol variable setLayout
if (this.retailfoodViewStub.isInflated()) this.retailfoodViewStub.getBinding().setVariable(BR.setLayout,viewModelSearchRulesetGetValue);
^
symbol: variable setLayout
location: class BR
好像 XML 布局找不到绑定适配器
编辑
这是绑定适配器所在的文件。绑定适配器不在伴随对象或其他命名对象中。
package com.smellydogcoding.westvirginiaelectronicfieldguidedistrict.ui
import android.app.Application
import android.view.ViewStub
import android.webkit.WebView
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat.getColor
import androidx.databinding.BindingAdapter
import com.smellydogcoding.westvirginiaelectronicfieldguidedistrict.R
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
// sets the background image for the program grid view recyclerview
@BindingAdapter("backgroundResource")
fun bindImageResource(imageView: ImageView,imagePath: String) {
imageView.setImageResource(when (imagePath) {
"code" -> R.drawable.code
"restaurant" -> R.drawable.restaurant
"hotelroom" -> R.drawable.hotelroom
"well" -> R.drawable.well
"septic" -> R.drawable.septic
"pool" -> R.drawable.pool
"tattoo" -> R.drawable.tattoo
"mobilehomepark" -> R.drawable.mobilehomepark
"daycare" -> R.drawable.daycare
"raccoon" -> R.drawable.raccoon
"tornado" -> R.drawable.tornado
else -> R.drawable.code
})
}
// sets the content for the code details WebViews
@BindingAdapter("webViewData")
fun WebView.webViewData(url: String?) {
url?.let {
settings.textZoom = 110
loadDataWithBaseURL(null,url,"text/html","base64",null)
}
}
// changes the font color for code details TextViews
@BindingAdapter("changeTextColor")
fun TextView.changeTextColor(text: String?) {
text?.let {
when (text) {
"Priority","Yes" -> setTextColor(getColor(context,R.color.error)
)
"Priority Foundation","Potential" -> setTextColor(getColor(context,R.color.warning)
)
}
}
}
// set the layout for code details ViewStub
@BindingAdapter("setLayout")
fun ViewStub.setLayout(rule: String) {
layoutResource = when (rule) {
"retailfood" -> R.layout.stub_code_details_retail_food
"general" -> R.layout.stub_code_details_general
"recwater" -> R.layout.stub_code_details_recwater
"citations" -> R.layout.stub_code_details_citations
else -> R.layout.stub_code_details_other
}
}
// load JSON assets to use with a recyclerview
object JsonAsset {
lateinit var application: Application
inline fun <reified T: Any> getJson (name: String): List<T>? {
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
val json = application.assets.open(name).bufferedReader().use{ it.readText() }
val listType = Types.newParameterizedType(List::class.java,T::class.java)
val adapter: JsonAdapter<List<T>> = moshi.adapter(listType)
return adapter.fromJson(json)
}
}
解决方法
所以这个问题有点重复This Stack Overflow Question
但有一些区别。
tl;dr;你不能。
您不能将绑定适配器与 ViewStub 一起使用,因为当编译器创建绑定文件时,它将为 ViewStub 正在膨胀的视图寻找适配器,而不是为 ViewStub 本身寻找适配器。因此它永远不会找到适配器,并抛出错误。恕我直言,这个设计没有意义。如果我想将绑定适配器应用于我正在膨胀的视图,我会制作它们。
上面的 SO 问题确实提到了一种创建方法。不幸的是,它只允许您在 ViewStub 布局通过 onInflateListener
膨胀后应用它,而且我必须在 ViewStub 膨胀之前设置布局。
通过从 ViewStub XML 布局中删除 android:visibility="visible" and app:setLayout="@{viewModel.searchRuleset}"
并以编程方式设置相应片段中存根的布局,我找到了一个解决方案:
// set the layout for the ViewStub and inflate
val viewStubProxy : ViewStubProxy = binding.codeDetailsViewStub
viewStubProxy.viewStub?.layoutResource = when (viewModel.searchRuleset.value) {
"retailfood" -> R.layout.stub_code_details_retail_food
"general" -> R.layout.stub_code_details_general
"recwater" -> R.layout.stub_code_details_recwater
"citations" -> R.layout.stub_code_details_citations
else -> R.layout.stub_code_details_other
}
viewStubProxy.viewStub?.inflate()
如果您使用数据绑定,则必须定位 ViewStubProxy
而不是 ViewStub
本身。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。