Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reduce scroll area/size for scrollbar in recycler view

I want to reduce scrollbar size(attached image) for recycler view, I have tried with creating custom drawable for for Thumb & Track, but thumb is not underlying with in the track. Can someone help me in better approach to achieve this?

enter image description here

In above image, horizontal scrollbar at bottom which is small in size. I want to achieve something like this.

enter image description here

like image 591
T_V Avatar asked Nov 28 '25 12:11

T_V


2 Answers

Here is one way that you can do what you want:

Define the thumb:

enter image description here

custom_thumb.xml

<shape
    android:shape="rectangle">
    <corners android:radius="20dp" />
    <solid android:color="@android:color/holo_red_light" />
    <size
        android:width="40dp"
        android:height="10dp" />
</shape>

Define the progress drawable for the seekbar:

seekbar_drawable.xml

<layer-list>
    <item android:id="@android:id/progress">
        <clip android:drawable="@android:color/transparent" />
    </item>
</layer-list>

We will not show the progress for the seekbar, so we set the progress drawable to "transparent". Instead of the progress drawable, we will define another view that will show behind the progress bar. Why do we do this? It is because the seekbar wants to move the thumb outside the progress area and we want the thumb to remain entirely within the progress area. The second view encompasses all of the seekbar plus some area to the left and to the right to contain the thumb.

seekbar_background.xml

<shape>
    <corners android:radius="20dp"/>
    <solid android:color="@android:color/darker_gray" />
</shape>

Here is some sample XML to show how this looks:

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">

    <View
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@drawable/seekbar_background"
        app:layout_constraintBottom_toBottomOf="@id/seekBar"
        app:layout_constraintEnd_toEndOf="@id/seekBar"
        app:layout_constraintStart_toStartOf="@id/seekBar"
        app:layout_constraintTop_toTopOf="@id/seekBar" />

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="200dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:max="10000"
        android:min="0"
        android:paddingStart="20dp"
        android:paddingEnd="20dp"
        android:progressDrawable="@drawable/seekbar_drawable"
        android:thumb="@drawable/custom_thumb"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

enter image description here

Use a SeekBar.OnSeekBarChangeListener to scroll the RecyclerView using the RecyclerView's scrolling functions. When the RecyclerView is scrolled manually, use a RecyclerView.OnScrollListener to set the seekbar's progress. You will have to establish the mapping of the two views scroll states.

I have hard-coded some values that you will probably need to adjust.

One can change the width of the thumb programmatically with the following code to adjust for number of Recyclerview items or to any other value.

To change the width of the thumb by a factor of two as an example, you can do the following:

val thumb = binding.seekBar.thumb as GradientDrawable
thumb.setSize(thumb.intrinsicWidth * 2, thumb.intrinsicHeight)
like image 58
Cheticamp Avatar answered Nov 30 '25 02:11

Cheticamp


You can create your own custom scrollbar and tie it with recycler view. Following is extension method for recycler view to handle the above made scrollbar

fun RecyclerView.handleScroll(itemScrollerBinding: ItemScrollerBinding) {
    post {
        val parentWidth = itemScrollerBinding.parent.width
        val layoutParams = itemScrollerBinding.progress.layoutParams
        val initialX = itemScrollerBinding.progress.x
        layoutManager?.let {
            val totalWidth = this.computeHorizontalScrollRange()
            val visibleWidth = this.computeHorizontalScrollExtent()
            val percent =
                visibleWidth.toFloat() / totalWidth.toFloat()
            layoutParams.width = (parentWidth * percent).toInt()
            itemScrollerBinding.progress.layoutParams = layoutParams
            addOnScrollListener(object :
                RecyclerView.OnScrollListener() {
                override fun onScrolled(
                    recyclerView: RecyclerView,
                    dx: Int,
                    dy: Int,
                ) {
                    super.onScrolled(recyclerView, dx, dy)
                    val scrolledWidth =
                        [email protected]()
                    val updatedVisibleWidthRecyclerView =
                        visibleWidth + scrolledWidth
                    val scrolledWidthScroller =
                        ((parentWidth.toFloat() / totalWidth) * scrolledWidth)
                    itemScrollerBinding.progress.x =
                        initialX + scrolledWidthScroller
                }
            })
        }
    }
}

Following is xml code for ItemScrollerBinding

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/parent"
    android:layout_width="@dimen/size_48"
    android:layout_height="@dimen/size_6"
    android:background="@drawable/bg_scroller_background">
    <LinearLayout
        android:id="@+id/progress"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:background="@drawable/bg_scroller"
        android:orientation="horizontal" />
</FrameLayout>

You can place this below the recycler view and center it.

like image 33
likhit Avatar answered Nov 30 '25 03:11

likhit