Taimoor Khan
Taimoor Khan

Reputation: 667

Make horizontal RecyclerView first and last item with rounded corner

All images inside recyclerView are in square shape. I have to provide corner radius to recyclerView but the inner items are square

I tried giving a shape to recyclerview but unable to achieve

Is there a way to round first and last item in android easy

round_recycler.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white"/>

    <stroke android:width="1dp"
        android:color="@android:color/transparent"
        />

    <padding android:left="8dp"
        android:top="8dp"
        android:right="8dp"
        android:bottom="8dp"
        />

    <corners android:bottomRightRadius="7dp"
        android:bottomLeftRadius="7dp"
        android:topLeftRadius="7dp"
        android:topRightRadius="7dp"/>
</shape>

Only i have to rounded first and last item or RecylerView I also try clipOutline true to my item_row_layout

item_row_layout.xml

<?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>
        <import type="android.view.View" />
        <variable
            name="item"
            type="planet.beyond.domain.models.RecentBO" />

    </data>

    <planet.beyond.gallerycleanarchitecture.utis.AspectRatioImageView
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/ivPhoto"
        imagePath="@{item.imageUrl}"
        android:layout_width="90dp"
        android:clipToOutline="true"
        android:layout_height="90dp"
        android:foreground="?android:attr/selectableItemBackground"
        android:scaleType="centerCrop"
        tools:src="@tools:sample/avatars" />
</layout>

enter image description here

Upvotes: 1

Views: 1736

Answers (3)

Milad Mohammadi
Milad Mohammadi

Reputation: 54

I give you two ways to do this, you can choose based on what you need

  1. add these to your model data class:
val isFirst: Boolean = false,
val isLast: Boolean = false

and in your onBindViewHolder act based on variables that you defined before for your items.

  1. define different view types and show your item layout based on your view type. this is an example that shows how it works: ‍‍‍‍‍‍
class SampleAdapter: RecyclerView.Adapter<SampleAdapter.ViewHolder>() {
    // I consider you are using DiffUtil, change the implementation based on your adapter structure

    companion object {
        private const val VIEW_TYPE_FIRST = -1
        private const val VIEW_TYPE_MIDDLE = 0
        private const val VIEW_TYPE_LAST = 1
    }

    override fun getItemViewType(position: Int): Int {
        return when {
            position == 0 -> VIEW_TYPE_FIRST
            position == differ.currentList.size - 1 -> VIEW_TYPE_LAST
            else -> VIEW_TYPE_MIDDLE
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return when {
            VIEW_TYPE_FIRST -> ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_first_row_layout, parent, false))
            VIEW_TYPE_LAST -> ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_last_row_layout, parent, false))
            else -> ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_middle_row_layout, parent, false))
        }
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        val viewType = getItemViewType(position)

        holder.itemView.apply {
            when (viewType) {
                VIEW_TYPE_FIRST -> loadFirstItem(this)
                VIEW_TYPE_MIDDLE -> loadMiddleItem(this, position)
                VIEW_TYPE_LAST -> loadLastItem(this)
            }
        }
    }


    private fun loadFirstItem(itemView: View) {
        val item = differ.currentList[0]
        // your code...
    }

    private fun loadMiddleItem(itemView: View, position: Int) {
        val item = differ.currentList[position]
        // your code...
    }

    private fun loadLastItem(itemView: View) {
        val item = differ.currentList.last()
        // your code...
    }
}

Upvotes: 1

Some random IT boy
Some random IT boy

Reputation: 8467

Since you're using Kotlin and DataBinding an easy way of performing such thing could be to map your item's collection to determine which one is the first item and which one is the last one.

There are many ways you can perform this and for simplicity's sake I'll just provide a wrapper class to illustrate how I'd approach the problem:

data class RecentBOItem(
  val data: RecentBO,
  val isFirst: Boolean,
  val isLast: Boolean
)

And having the viewmodel do something like the following:

suspend fun getSomething(): List<RecentBOItem> {
  val recentBos = getRecentBOsFromNetwork()
  val lastIndex = recentBos.lastIndex
  return recent.withIndex().map { (index, recentBo) ->
    RecentBOItem(
      data = recentBo,
      isFirst = index == 0,
      isLast = index == lastIndex
    )
  }
}

And then provide a @BindingAdapter for the RecentBOItem that sets the round corners shape based off the isFirst and isLast flags. (That is setting the suitable R.drawable as background)

Upvotes: 1

Yoav Gibri
Yoav Gibri

Reputation: 168

You can use RecyclerView's Adapter's viewType in onCreateViewHolder method. You override getItemViewType(int position) method and return different "type" by position. In onCreateViewHolder method you can then inflate different layouts or apply different settings to the view.

Check this link: https://blog.mindorks.com/recyclerview-multiple-view-types-in-android

Upvotes: 0

Related Questions