如何为 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);
    }
}
  1. define your resource as integer:
 <item type="integer" name="button_with_percent" format="float">0.3</item>
  1. apply to your layout:
android:layout_width="0dp"   
app:layout_constraintWidth_percent="@integer/button_with_percent"