In most of our applications we tend to need to display a series of images. Images make our applications look more modern and interactive and they are a great way to pass information visually.
Sometimes you may even need to show your item lists horizontally. One way is to use a recyclerview with horizontal orientation. However in this case the items won’t be auto-flipped or faded.
Thus we will first look at how to create a custom carousel based on recyclerview, the we will curate some of the best libraries and examples already written by other developers and available for re-use. You could always customize them since they are all open source.
Most of them are actually based on recyclerview and some do need a custom adapter. This gives them flexibility and power.
In this article you will learn:
- How to create a custom image carousel in android based on recyclerview.
- How to use third party libraries to implement a carousel.
We use the following languages:
- Kotlin
- Java
NB/= This article is broken down into several pages. Each page teaches a unique concept. Here are the taught concepts:
Page 1: Implement a custom carousel
Page 2: Use libraries to implement a carousel
Concept 1: Creating a Custom Carousel
Example 1: Kotlin android Horizontal Carousel
How to implement a custom horizontal image carousel using recycelrview in Kotlin.
Step 1: Create Project
Start by creating an empty Android Studio
Kotlin project.
Step 2: Dependencies
No third party libraries are needed for this project.
Step 3: Create a Custom Carousel View
We will create a custom carousel view by extending the recyclerview:
HorizontalCarouselRecyclerView.kt
package supahsoftware.androidexamplecarousel
import android.animation.ArgbEvaluator
import android.content.Context
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
import android.util.AttributeSet
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
class HorizontalCarouselRecyclerView(
context: Context,
attrs: AttributeSet
) : RecyclerView(context, attrs) {
private val activeColor by lazy { ContextCompat.getColor(context, R.color.blue) }
private val inactiveColor by lazy { ContextCompat.getColor(context, R.color.gray) }
private var viewsToChangeColor: List<Int> = listOf()
fun <T : ViewHolder> initialize(newAdapter: Adapter<T>) {
layoutManager = LinearLayoutManager(context, HORIZONTAL, false)
newAdapter.registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() {
post {
val sidePadding = (width / 2) - (getChildAt(0).width / 2)
setPadding(sidePadding, 0, sidePadding, 0)
scrollToPosition(0)
addOnScrollListener(object : OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
onScrollChanged()
}
})
}
}
})
adapter = newAdapter
}
fun setViewsToChangeColor(viewIds: List<Int>) {
viewsToChangeColor = viewIds
}
private fun onScrollChanged() {
post {
(0 until childCount).forEach { position ->
val child = getChildAt(position)
val childCenterX = (child.left + child.right) / 2
val scaleValue = getGaussianScale(childCenterX, 1f, 1f, 150.toDouble())
child.scaleX = scaleValue
child.scaleY = scaleValue
colorView(child, scaleValue)
}
}
}
private fun colorView(child: View, scaleValue: Float) {
val saturationPercent = (scaleValue - 1) / 1f
val alphaPercent = scaleValue / 2f
val matrix = ColorMatrix()
matrix.setSaturation(saturationPercent)
viewsToChangeColor.forEach { viewId ->
val viewToChangeColor = child.findViewById<View>(viewId)
when (viewToChangeColor) {
is ImageView -> {
viewToChangeColor.colorFilter = ColorMatrixColorFilter(matrix)
viewToChangeColor.imageAlpha = (255 * alphaPercent).toInt()
}
is TextView -> {
val textColor = ArgbEvaluator().evaluate(saturationPercent, inactiveColor, activeColor) as Int
viewToChangeColor.setTextColor(textColor)
}
}
}
}
private fun getGaussianScale(
childCenterX: Int,
minScaleOffest: Float,
scaleFactor: Float,
spreadFactor: Double
): Float {
val recyclerCenterX = (left + right) / 2
return (Math.pow(
Math.E,
-Math.pow(childCenterX - recyclerCenterX.toDouble(), 2.toDouble()) / (2 * Math.pow(
spreadFactor,
2.toDouble()
))
) * scaleFactor + minScaleOffest).toFloat()
}
}
Step 4: Design Layouts
We will need two layouts for this project:
(a). list_item.xml
A layout to represent a single carousel item:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="24dp"
android:paddingStart="24dp"
android:paddingTop="64dp"
android:paddingEnd="24dp"
android:paddingBottom="64dp">
<ImageView
android:id="@+id/list_item_background"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:src="@drawable/icon_background_blue" />
<ImageView
android:id="@+id/list_item_icon"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_centerInParent="true" />
<TextView
android:id="@+id/list_item_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/list_item_background"
android:layout_centerHorizontal="true"
android:layout_marginTop="32dp"
android:textColor="@color/blue"
android:textSize="22sp" />
</RelativeLayout>
(b). activity_main.xml
Will contain our custom Horizontal Carousel recyclerview:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff">
<supahsoftware.androidexamplecarousel.HorizontalCarouselRecyclerView
android:id="@+id/item_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:clipToPadding="false"
android:overScrollMode="never" />
</LinearLayout>
Step 5: Create an Adapter
Create our carousel adapter:
ItemAdapter.kt
class ItemAdapter(val itemClick: (position:Int,item:Item) -> Unit) : RecyclerView.Adapter<ItemViewHolder>() {
private var items: List<Item> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder =
ItemViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.list_item, parent, false))
override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
holder.bind(items[position])
holder.itemView.setOnClickListener {
itemClick(position,items[position])
}
}
override fun getItemCount() = items.size
fun setItems(newItems: List<Item>) {
items = newItems
notifyDataSetChanged()
}
}
class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
fun bind(item: Item) {
view.list_item_text.text = "${item.title}"
view.list_item_icon.setImageResource(item.icon)
}
}
Step 6: Create MainActivity
Here is the code for MainActivity:
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val itemAdapter by lazy {
ItemAdapter { position: Int, item: Item ->
Toast.makeText([email protected], "Pos ${position}", Toast.LENGTH_LONG).show()
item_list.smoothScrollToPosition(position)
} }
private val possibleItems = listOf(
Item("Airplanes", R.drawable.ic_airplane),
Item("Cars", R.drawable.ic_car),
Item("Food", R.drawable.ic_food),
Item("Gas", R.drawable.ic_gas),
Item("Home", R.drawable.ic_home)
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
item_list.initialize(itemAdapter)
item_list.setViewsToChangeColor(listOf(R.id.list_item_background, R.id.list_item_text))
itemAdapter.setItems(getLargeListOfItems())
}
private fun getLargeListOfItems(): List<Item> {
val items = mutableListOf<Item>()
(0..40).map { items.add(possibleItems.random()) }
return items
}
}
data class Item(
val title: String,
@DrawableRes val icon: Int
)
Run
Copy the code or download it in the link below, build and run.
Reference
Here are the reference links:
Number | Link |
---|---|
1. | Download Example |
2. | Follow code author |
3. | Code: Apache 2.0 License |
Concepts 2: Best Android Image Carousel Libraries – 2021
Proceed to the next page to view the best android image carousel libraries this year.