Warm tip: This article is reproduced from stackoverflow.com, please click
android android-custom-view android-databinding android-jetpack kotlin

How can I use my custom image view with DataBinding in Android?

发布于 2020-04-20 10:51:06

So I checked this codelab by Google for creating a custom view RatioImageView in Android. It simply extends the ImageView and overrides the OnMeasure() method according to device's viewport's aspect ratio. The code for the same is:

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())
    }
}

Then I am using this in ListItem view as:

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

Then in the Adapter, I am using DataBinding to update the views with content as follows:

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)
            }
        }
}

During building, it shows the following error:

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

i.e. for the line in which target.loadImage(...) is written in OnBindViewHolder()

Also, if I don't use DataBinding for the root layout, then it works fine.

So the question is what needs to be added to RatioImageView? To make it work with DataBinding, considering that here I don't require an XML layout to be associated with the View class.

Here's the onCreateViewHolder()

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

And below is the ViewHolder class:

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

Also here is the repo in case my code is missing something over here: https://github.com/prafullmishra/CustomImageView

Questioner
Lincoln
Viewed
15
Lisa Wray 2020-02-22 09:20

I found the problem in the code sample you posted on Github. Actually, this one was tricky to solve from the snippet you posted, but the error was correctly indicating a problem with the class name.

Your XML referred to the class com.example.bindingcustomimageview.CustomImage.RatioImageView. Without knowing anything more, RatioView looks like it's a public inner class of CustomImage in the package com.example.bindingcustomimageview.

But it wasn't. It was the class RatioImageView in the package com.example.bindingcustomimageview.CustomImage (where "CustomImage" is an uppercase package name). You can fix it quickly by dragging RatioImageView into the same package as your MainActivity, and everything will work correctly.

To avoid confusions like this in the future, don't name your packages with upper case names.