c-an
c-an

Reputation: 4090

How can I set all the items width are the same in RecyclerView?

I'd like to set all the items' width the same. because the view has line around it and some text are long and the others are short. So, the items look like stair case or something but I want them to look clean. (Maybe, I need to set the heights the same as well in the future.)

I want to set all the width & height with the longest text among the items.

I have set these three values,

var maxLength = 0
var maxWidth = 0
var longestP = 0

And, init the values whenever it sets new data.

    fun setData(data: ArrayList<AnswerData>?, min: Int?, max: Int?) {
        if (data == null) {
            items = ArrayList()
        } else {
            data.forEach {
                it.isChecked = false
            }
            this.items = data
        }

        this.min = min ?: -1
        this.max = max ?: 30
        maxLength = 0
        maxWidth = 0
        longestP = 0

        notifyDataSetChanged()
    }

This is the logic that I thought it would work. (But didn't)

for( i in 0 until items.size){
    val length = items[i].label!!.length
    if( length > maxLength){
        maxLength = length
        longestP = i
    }
}

if(longestP == position){
    maxWidth = holder.cb!!.measuredWidth
}else{
    resizeView(holder.cb!!, maxWidth, holder.cb!!.measuredHeight)
    notifyItemChanged(position)
}

It's resizeView().

    private fun resizeView(view: View, newWidth: Int, newHeight: Int) {
        Log.d("size", "$newWidth, $newHeight")
        val params = view.layoutParams
        params.width = newWidth
        params.height = newHeight
        view.layoutParams = params
    }

What's the problem?

Upvotes: 1

Views: 1992

Answers (2)

LCZ
LCZ

Reputation: 729

You can set the width of your individual views to be match_parent, and the width of the RecyclerView to be wrap_content. This way, all the views will have same width, and not fixed width, dependent on the longest view. If the text is too long, TextView will automatically wrap the text to the next line.

My code:

For recycler view

<androidx.recyclerview.widget.RecyclerView
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    tools:listitem="@layout/single_item" />

For single item(I am using CardView)

<androidx.cardview.widget.CardView 
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

Upvotes: 0

c-an
c-an

Reputation: 4090

I changed some part in Adapter, and it works.

    var maxLength = 0
    var maxWidth = 0
    var maxHeight = 0
    var longestP = 0
    fun setData(data: ArrayList<AnswerData>?) {
        ...

        maxLength = 0
        maxWidth = 0
        maxHeight = 0
        longestP = 0

        ...
    }
    for( i in 0 until items.size){
        val length = items[i].label!!.length
        if( length > maxLength){
            maxLength = length
            longestP = i
        }
    }

    if(longestP == position){
        maxWidth = holder.tv!!.width
        maxHeight = holder.tv!!.height
        items[position].width = maxWidth
        items[position].height = maxHeight
    }else if(holder.tv!!.width < maxWidth){
        items[position].width = maxWidth
        items[position].height = maxHeight
        resizeView(holder.tv!!, items[position].width, items[position].height)
    }

The trick is the data model has width and height values. And set the item view's width or height when they are higher than 0.

Upvotes: 1

Related Questions