如何为 float 类型定义资源并在 `layout_constraintWidth_percent` 的数据绑定中使用它?
how to define resource for the float type and use it in the databinding for `layout_constraintWidth_percent`?
如果使用
app:layout_constraintWidth_percent="@{vm.type == Type_1 ? 0.76F : 0.79F}”
它工作正常。
但使用
app:layout_constraintWidth_percent="@{vm.type == Type_1 ? @dimen/type_2_percent : @dimen/type_1_percent}”
崩溃了
android.content.res.Resources$NotFoundException: Resource ID #0x7f0700ac type #0x4 is not valid
其他使用带资源 ID 的数据绑定的项目也能正常工作。
如何为 float 类型定义资源并在 layout_constraintWidth_percent
的数据绑定中使用它?
相关代码如下:
<dimen name=“type_1_width">55dp</dimen>
<dimen name=“type_1_height">48dp</dimen>
<dimen name=“type_2_width">73dp</dimen>
<dimen name=“type_2_height">63dp</dimen>
<!-- define for float -->
<item name=“type_1_percent” format="float" type="dimen">0.76</item>
<item name="type_2_percent" format="float" type="dimen">0.79</item>
===
@JvmStatic @BindingAdapter("app:layout_constraintWidth_percent")
fun setLayoutConstraintWidthPercent(view: View, width: Float) {
(view.layoutParams as? ConstraintLayout.LayoutParams)?.apply { this.matchConstraintPercentWidth = width }
}
===
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="vm"
type="com.viewmodel.ListViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:visibility="@{(vm.count > 0) ? View.GONE : View.VISIBLE}"
>
<ImageView
android:id="@+id/avatar"
android:layout_width="@{vm.type == Type_1 ? @dimen/type_1_width : @dimen/type_2_width, default=wrap_content}"
android:layout_height="@{vm.type == Type_1 ? @dimen/type_1_height : @dimen/type_2_height, default=wrap_content}"
android:layout_margin="20dp"
android:src="@drawable/avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf=“@+id/text_body”
/>
<TextView
android:id="@+id/text_body"
android:layout_width="0dp"
app:layout_constraintWidth_percent="@{vm.type == Type_1 ? @dimen/type_2_percent : @dimen/type_1_percent}”
// app:layout_constraintWidth_percent="@{vm.type == Type_1 ? 0.76F : 0.79F}” <=== using float directly works
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="10dp"
android:text="@{vm.type == Type_1 ? @string/type_1_text : @string/type_2_text}"
android:textColor="#FF999999"
android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/avatar"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
浮点数不起作用。维度没有 type="float"
。如果您指定 type="dimen"
则绑定需要一个维度而不是一个浮点数。 (错误中的 0x04
资源类型为 "float"。)
我认为这样做的方法是将您的维度定义为分数,如下所示:
<item name="type_1_fraction" type="fraction">25%</item>
<item name="type_2_fraction" type="fraction">75%</item>
那么你可以在布局中使用如下:
app:layout_constraintWidth_percent="@{vm.type == 1 ? @fraction/type_1_fraction : @fraction/type_2_fraction}"
适配器应按原样工作。
@Cheticamp 解决方案有效,将生成的绑定代码放在这里以帮助理解为什么使用 type=fraction
:
生成的绑定代码:
val theFloat = ((vmType_1) ? (textBody.getResources().getFraction(R.fraction.type_1_fraction, 1, 1)) : (textBody.getResources().getFraction(R.fraction.type_2_fraction, 1, 1)));
com.utils.BindingAdapterUtils.setLayoutConstraintWidthPercent(this.textBody, theFloat);
Resources::getFraction()
:
public float getFraction(@FractionRes int id, int base, int pbase) {
final TypedValue value = obtainTempTypedValue();
try {
mResourcesImpl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_FRACTION) {
return TypedValue.complexToFraction(value.data, base, pbase);
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
} finally {
releaseTempTypedValue(value);
}
}
- define your resource as integer:
<item type="integer" name="button_with_percent" format="float">0.3</item>
- apply to your layout:
android:layout_width="0dp"
app:layout_constraintWidth_percent="@integer/button_with_percent"
如果使用
app:layout_constraintWidth_percent="@{vm.type == Type_1 ? 0.76F : 0.79F}”
它工作正常。 但使用
app:layout_constraintWidth_percent="@{vm.type == Type_1 ? @dimen/type_2_percent : @dimen/type_1_percent}”
崩溃了
android.content.res.Resources$NotFoundException: Resource ID #0x7f0700ac type #0x4 is not valid
其他使用带资源 ID 的数据绑定的项目也能正常工作。
如何为 float 类型定义资源并在 layout_constraintWidth_percent
的数据绑定中使用它?
相关代码如下:
<dimen name=“type_1_width">55dp</dimen>
<dimen name=“type_1_height">48dp</dimen>
<dimen name=“type_2_width">73dp</dimen>
<dimen name=“type_2_height">63dp</dimen>
<!-- define for float -->
<item name=“type_1_percent” format="float" type="dimen">0.76</item>
<item name="type_2_percent" format="float" type="dimen">0.79</item>
===
@JvmStatic @BindingAdapter("app:layout_constraintWidth_percent")
fun setLayoutConstraintWidthPercent(view: View, width: Float) {
(view.layoutParams as? ConstraintLayout.LayoutParams)?.apply { this.matchConstraintPercentWidth = width }
}
===
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<import type="android.view.View" />
<variable
name="vm"
type="com.viewmodel.ListViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="30dp"
android:visibility="@{(vm.count > 0) ? View.GONE : View.VISIBLE}"
>
<ImageView
android:id="@+id/avatar"
android:layout_width="@{vm.type == Type_1 ? @dimen/type_1_width : @dimen/type_2_width, default=wrap_content}"
android:layout_height="@{vm.type == Type_1 ? @dimen/type_1_height : @dimen/type_2_height, default=wrap_content}"
android:layout_margin="20dp"
android:src="@drawable/avatar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf=“@+id/text_body”
/>
<TextView
android:id="@+id/text_body"
android:layout_width="0dp"
app:layout_constraintWidth_percent="@{vm.type == Type_1 ? @dimen/type_2_percent : @dimen/type_1_percent}”
// app:layout_constraintWidth_percent="@{vm.type == Type_1 ? 0.76F : 0.79F}” <=== using float directly works
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="10dp"
android:text="@{vm.type == Type_1 ? @string/type_1_text : @string/type_2_text}"
android:textColor="#FF999999"
android:textSize="15sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/avatar"
app:layout_constraintBottom_toBottomOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
浮点数不起作用。维度没有 type="float"
。如果您指定 type="dimen"
则绑定需要一个维度而不是一个浮点数。 (错误中的 0x04
资源类型为 "float"。)
我认为这样做的方法是将您的维度定义为分数,如下所示:
<item name="type_1_fraction" type="fraction">25%</item>
<item name="type_2_fraction" type="fraction">75%</item>
那么你可以在布局中使用如下:
app:layout_constraintWidth_percent="@{vm.type == 1 ? @fraction/type_1_fraction : @fraction/type_2_fraction}"
适配器应按原样工作。
@Cheticamp 解决方案有效,将生成的绑定代码放在这里以帮助理解为什么使用 type=fraction
:
生成的绑定代码:
val theFloat = ((vmType_1) ? (textBody.getResources().getFraction(R.fraction.type_1_fraction, 1, 1)) : (textBody.getResources().getFraction(R.fraction.type_2_fraction, 1, 1)));
com.utils.BindingAdapterUtils.setLayoutConstraintWidthPercent(this.textBody, theFloat);
Resources::getFraction()
:
public float getFraction(@FractionRes int id, int base, int pbase) {
final TypedValue value = obtainTempTypedValue();
try {
mResourcesImpl.getValue(id, value, true);
if (value.type == TypedValue.TYPE_FRACTION) {
return TypedValue.complexToFraction(value.data, base, pbase);
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
+ " type #0x" + Integer.toHexString(value.type) + " is not valid");
} finally {
releaseTempTypedValue(value);
}
}
- define your resource as integer:
<item type="integer" name="button_with_percent" format="float">0.3</item>
- apply to your layout:
android:layout_width="0dp"
app:layout_constraintWidth_percent="@integer/button_with_percent"