[英]Android Binding Adapter attribute not found
I am using a binding adapter to have mutable text in one of my views.我正在使用绑定适配器在我的一个视图中包含可变文本。 I believe I have it implemented correctly (and it's working in other places), but for the case of mutableText, it's getting the error
AAPT: error: attribute mutableText not found
我相信我已经正确实现了它(并且它在其他地方工作),但是对于 mutableText 的情况,它得到了错误
AAPT: error: attribute mutableText not found
I've looked through some other answers on here, but none of them have been able to solve the issue.我在这里查看了其他一些答案,但没有一个能够解决这个问题。
Here is my layout file:这是我的布局文件:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.example.nhlstats.ui.game.GameViewModel" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/awayTeam"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="12dp">
<ImageView
android:id="@+id/awayTeamLogo"
android:layout_height="48dp"
android:layout_width="0dp"
android:layout_weight="1"
tools:src="@drawable/ic_launcher_background"/>
<TextView
android:id="@+id/awayTeamName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:layout_gravity="center_vertical"
app:mutableText="@{viewModel.getAwayTeamName()}"
tools:text="CHI Blackhawks"/>
<TextView
android:id="@+id/awayScore"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
app:mutableText="@{viewModel.getAwayTeamScore().toString()}"
tools:text="0"/>
<TextView
android:id="@+id/gameTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
app:mutableText="@{viewModel.getTimeRemaining()"
tools:text="14:26 3rd"/>
</LinearLayout>
<LinearLayout
android:id="@+id/homeTeam"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp">
<ImageView
android:id="@+id/homeTeamLogo"
android:layout_height="48dp"
android:layout_width="0dp"
android:layout_weight="1"
tools:src="@drawable/ic_launcher_background"/>
<TextView
android:id="@+id/homeTeamName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:layout_gravity="center_vertical"
app:mutableText="@{viewModel.getHomeTeamName()}"
tools:text="CAR Hurricanes"/>
<TextView
android:id="@+id/homeScore"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="2"
app:mutableText="@{viewModel.getHomeTeamScore().toString()}"
tools:text="4"/>
</LinearLayout>
</LinearLayout>
</layout>
and my BindingAdpater function:和我的 BindingAdpater function:
@BindingAdapter("mutableText")
fun setMutableText(view: TextView, text: MutableLiveData<String>?) {
val parentActivity:AppCompatActivity? = view.getParentActivity()
if (parentActivity != null && text != null) {
text.observe(parentActivity, Observer { value ->
view.text = value?:""
})
}
}
GameViewModel:游戏视图模型:
class GameViewModel:BaseViewModel() {
private val awayTeamName = MutableLiveData<String>()
private val homeTeamName = MutableLiveData<String>()
private val awayTeamScore = MutableLiveData<Int>()
private val homeTeamScore = MutableLiveData<Int>()
private val timeRemaining = MutableLiveData<String>()
fun bind(response: Game) {
awayTeamName.value = response.gameData.teams.get(0).name
homeTeamName.value = response.gameData.teams.get(1).name
awayTeamScore.value = response.liveData.linescore.teams.get(1).goals
homeTeamScore.value = response.liveData.linescore.teams.get(0).goals
timeRemaining.value = response.liveData.linescore.currentPeriodOrdinal + " " + response.liveData.linescore.currentPeriodTimeRemaining
}
fun getAwayTeamName(): MutableLiveData<String> {
return awayTeamName
}
fun getHomeTeamName(): MutableLiveData<String> {
return homeTeamName
}
fun getAwayTeamScore(): MutableLiveData<Int> {
return awayTeamScore
}
fun getHomeTeamScore(): MutableLiveData<Int> {
return homeTeamScore
}
fun getTimeRemaining(): MutableLiveData<String> {
return timeRemaining
}
}
MainActivity:主要活动:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: GameListViewModel
private var errorSnackbar: Snackbar? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
binding.gameList.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
viewModel = ViewModelProviders.of(this).get(GameListViewModel::class.java)
viewModel.errorMessage.observe(this, Observer { errorMessage ->
if (errorMessage != null)
showError(errorMessage)
else
hideError()
})
binding.viewModel = viewModel
}
private fun showError(@StringRes errorMessage:Int) {
errorSnackbar = Snackbar.make(binding.root, errorMessage, Snackbar.LENGTH_INDEFINITE)
errorSnackbar?.setAction(R.string.retry, viewModel.errorClickListener)
errorSnackbar?.show()
}
private fun hideError() {
errorSnackbar?.dismiss()
}
}
Thanks in advance.提前致谢。
Your binding adapter receives a nullable value, while the viewModel returns a non-null value.您的绑定适配器接收一个可为空的值,而 viewModel 返回一个非空值。 Change the text parameter to be non-null, just like the function in the viewModel returns it.
将文本参数更改为非空,就像viewModel中的function返回它一样。
You can also do shorter encapsulation, for example:您还可以进行更短的封装,例如:
private val _data = MutableLiveData<String>()
val data: LiveData<String>
get() = _data
This way you don't have to write long and boring getters like in Java.这样您就不必像在 Java 中那样编写冗长而无聊的 getter。
As per your GameViewModel
, I don't think you need any custom binding adapter.根据您的
GameViewModel
,我认为您不需要任何自定义绑定适配器。
Please check the edited code.请检查编辑后的代码。
GameViewModel游戏视图模型
class GameViewModel:BaseViewModel() {
// Make the variables public and access directly instead of exposing them via get() method.
val awayTeamName = MutableLiveData<String>()
val homeTeamName = MutableLiveData<String>()
val awayTeamScore = MutableLiveData<String>() // Change to String
val homeTeamScore = MutableLiveData<String>() // Change to String
val timeRemaining = MutableLiveData<String>()
fun bind(response: Game) {
awayTeamName.value = response.gameData.teams.get(0).name
homeTeamName.value = response.gameData.teams.get(1).name
awayTeamScore.value = response.liveData.linescore.teams.get(1).goals.toString() // Convert to String from here only instead of writing it in XML!
homeTeamScore.value = response.liveData.linescore.teams.get(0).goals.toString()
timeRemaining.value = response.liveData.linescore.currentPeriodOrdinal + " " + response.liveData.linescore.currentPeriodTimeRemaining
}
}
Your layout file (Notice I accessed the variables directly and removed the toString() as we are now only exposing MutableLiveData
with String
and yes, we are not using your custom binding adapter.您的布局文件(请注意,我直接访问了变量并删除了 toString(),因为我们现在只使用
String
公开MutableLiveData
,是的,我们没有使用您的自定义绑定适配器。
<data>
<variable
name="viewModel"
type="com.example.nhlstats.ui.game.GameViewModel" />
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/awayTeam"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="12dp">
<ImageView
android:id="@+id/awayTeamLogo"
android:layout_height="48dp"
android:layout_width="0dp"
android:layout_weight="1"
tools:src="@drawable/ic_launcher_background"/>
<TextView
android:id="@+id/awayTeamName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:layout_gravity="center_vertical"
android:text="@{viewModel.awayTeamName}"
tools:text="CHI Blackhawks"/>
<TextView
android:id="@+id/awayScore"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:text="@{viewModel.awayTeamScore}"
tools:text="0"/>
<TextView
android:id="@+id/gameTime"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:text="@{viewModel.timeRemaining}"
tools:text="14:26 3rd"/>
</LinearLayout>
<LinearLayout
android:id="@+id/homeTeam"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp">
<ImageView
android:id="@+id/homeTeamLogo"
android:layout_height="48dp"
android:layout_width="0dp"
android:layout_weight="1"
tools:src="@drawable/ic_launcher_background"/>
<TextView
android:id="@+id/homeTeamName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:layout_gravity="center_vertical"
android:text="@{viewModel.homeTeamName}"
tools:text="CAR Hurricanes"/>
<TextView
android:id="@+id/homeScore"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="2"
android:text="@{viewModel.homeTeamScore}"
tools:text="4"/>
</LinearLayout>
</LinearLayout>
I haven't tested this so let me know how this goes for you.我还没有测试过这个,所以让我知道这对你有什么影响。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.