如何在Android的DataBinding中使用自定义图像视图?

时间:2020-02-05 11:07:11

标签: android kotlin android-custom-view android-databinding android-jetpack

因此,我检查了此codelab by Google以在Android中创建自定义视图RatioImageView。它只是扩展ImageView并根据设备的视口的宽高比覆盖OnMeasure()方法。相同的代码是:

class RatioImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
): ImageView(context, attrs, defStyleAttr) {

    private val VP_HEIGHT = Resources.getSystem().displayMetrics.heightPixels
    private val VP_WIDTH = Resources.getSystem().displayMetrics.widthPixels
    private val HWR: Float = VP_HEIGHT.toFloat()/VP_WIDTH.toFloat() //height to width ratio


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),(MeasureSpec.getSize(widthMeasureSpec)*HWR).toInt())
    }
}

然后我在ListItem视图中将其用作:

<?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>

    </data>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="0dp">

        <com.example.myapp.RatioImageView
            android:id="@+id/target"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:contentDescription="image holder"
            android:scaleType="centerCrop"
            android:background="#757575"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintDimensionRatio="9:16" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

然后在适配器中,我正在使用DataBinding来更新内容如下的视图:

override fun onBindViewHolder(holder: HomeItemHolder, position: Int) {
        holder.binding.apply {

              //loadImage() is an extension function added to ImageView class
              target.loadImage(UiUtil.getCustomUrl(photos[position].urls.fullImage, height, width))
       
            root.setOnClickListener {
                handleClick(position)
            }
        }
}

在构建过程中,它显示以下错误:

Cannot access class 'RatioImageView'. Check your module classpath for missing or conflicting dependencies

即在{strong> OnBindViewHolder()

中写入target.loadImage(...)的行

此外,如果我不将DataBinding用于根布局,那么它可以正常工作。

所以问题是需要向RatioImageView添加什么?为了使其与DataBinding一起使用,请考虑到这里我不需要将XML布局与View类关联。

这里是onCreateViewHolder()

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): HomeItemHolder {
        return HomeItemHolder(ItemPhotoListLayoutBinding.inflate(LayoutInflater.from(parent.context)))
    }

下面是ViewHolder类:

inner class HomeItemHolder (val binding: ItemPhotoListLayoutBinding):
        RecyclerView.ViewHolder(binding.root) {
    }

如果我的代码在此处丢失了某些内容,这里也是回购:https://github.com/prafullmishra/CustomImageView

3 个答案:

答案 0 :(得分:1)

我在您在Github上发布的代码示例中发现了问题。实际上,从您发布的代码片段中很难解决这个问题,但是错误正确地表明了类名的问题。

您的XML引用了该类 com.example.bindingcustomimageview.CustomImage.RatioImageView。一无所知,RatioView看起来像是软件包CustomImagecom.example.bindingcustomimageview的公共内部类。

但是不是。它是软件包RatioImageView中的类com.example.bindingcustomimageview.CustomImage(其中“ CustomImage”是大写的软件包名称)。您可以通过将RatioImageView拖到与MainActivity相同的程序包中来快速修复该问题,一切正常。

为避免将来出现此类混乱,请勿使用大写字母命名您的软件包。

答案 1 :(得分:0)

您想将数据绑定到xml中的哪个属性? 也许您想将图像绑定到android:src属性? 在这种情况下:

  1. <variable name="image" type="Drawable"/>标签内添加<data>
  2. src属性添加一个binding expression,例如android:id="@{image}"
  3. 尝试以下操作:

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    holder.binding.apply {
    
        this.image = loadImage(UiUtil.getCustomUrl(photos[position].urls.fullImage, height, width))
    
        root.setOnClickListener {
            handleClick(position)
        }
    }
    

答案 2 :(得分:0)

任何自定义视图都应至少具有3种不同的构造函数实现,您需要提供它们才能方便地访问它:

  1. 带有1个参数的那个:RatioImageView(context)
  2. 具有2个参数的那个:RatioImageView(context, attrs)
  3. 具有3个参数的那个:RatioImageView(context, attrs, defStyleAttr)

虽然RatioImageView只有一个带有3个参数的实作ImageView(context, attrs, defStyleAttr)的参数。这就是为什么您会收到该错误。您还需要定义其他2个构造函数。