Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customizing the ScrollBar programmatically

My requirements are to display a vertical list of views with a scrollbar whenever the total height of the views is bigger than the allowed height for the list.

Additionally, I need to customize the scrollBar appearance (background and thumb) programmatically. (At runtime, my activity will receive all the data to do the rendering : the bitmap to use as scrollbar background, the scrollbar width and the bitmap to use as scrollbar's thumb.)

A ListView seems a good candidate for this, except that I can't find a way to customize the scrollBar programmatically. I read this question scrollBar in a listView...customizing it. but, it's using a theme, and AFAIK it's not possible the create a new theme programmatically.

So my question(s):

  1. Is there a way to customize the appearance of a scrollbar (within a ListView) programmatically ?

  2. [only if the answer to the first one is "definitively not possible"] do you see any other way to achieve those requirements (and some working example of doing it)

Thanks.

EDIT (23/12)

I found this hidden class android.widget.ScrollBarDrawable. May be a good starting point to build a solution (no time to investigate it right now).

like image 411
ben75 Avatar asked Dec 14 '12 14:12

ben75


People also ask

How do I customize my scrollbar?

Scrollbar Selectors For webkit browsers, you can use the following pseudo elements to customize the browser's scrollbar: ::-webkit-scrollbar the scrollbar. ::-webkit-scrollbar-button the buttons on the scrollbar (arrows pointing upwards and downwards). ::-webkit-scrollbar-thumb the draggable scrolling handle.

How do I create a custom scrollbar for a div?

If you want to add a scrollbar to an element like a <div>, you'll have to use the CSS overflow property. Scrollbars can be vertical (Y-axis) or horizontal (X-axis). Implementing a custom scrollbar to elements is the same. In this example, I'll create vertical custom scrollbar on a <div>, which is just 5px wide.

How do I change the scrollbar position in CSS?

We can use the CSS “::-webkit-scrollbar” property which is responsible for changing the shape, color, size, shade, shadow, etc. of the scroll bar. But, here the property which we will use is the direction property of CSS for changing the position of the scroll bar.

Can we change color of scrollbar in CSS?

The scrollbar-color property is used to set the color of an element's scrollbar. It can be used to control both the scrollbar track and scrollbar thumb colors separately.


2 Answers

is there a way to customize the appearance of a scrollbar (within a ListView) programmatically ?

Literally, it does not look like it, simply because there are no setters for manipulating it.

It is conceivable that you could create your own BenView subclass of View that replaces the hidden ScrollBarDrawable with BenScrollBarDrawable that handles dynamic changes. But then you would need to create BenViewGroup, BenAbsListView, and BenListView, cloning their Ben-less counterparts' source code, to have them chain up to BenView to inherit this behavior. And, since one of ViewGroup, AbsListView, or ListView is bound to change in any Android release, you will actually need N copies of these classes and choose the right copy based on API level at runtime. And then your app may still behave oddly on some devices where the manufacturer went in and tinkered with ViewGroup, AbsListView, or ListView, and you will not be using their code.

I doubt that this is worth it, particularly since scrollbars are not visible by default except while scrolling.

do you see any other way to achieve those requirements (and some working example of doing it)

Handle your own touch events to do your own scrolling and do your own scrollbar stuff. Whether this is less work than the above solution is up for debate.

like image 114
CommonsWare Avatar answered Sep 29 '22 11:09

CommonsWare


I just faced the same problem for RecyclerView and solved it like this

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.support.annotation.ColorInt;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;

/**
 * Created on 22.3.2016.
 *
 * @author Bojan Kseneman
 * @description A recycler view that will draw the scroll bar with a different color
 */
public class CustomScrollBarRecyclerView extends RecyclerView {

    private int scrollBarColor = Color.RED;

    public CustomScrollBarRecyclerView(Context context) {
        super(context);
    }

    public CustomScrollBarRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomScrollBarRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public void setScrollBarColor(@ColorInt int scrollBarColor) {
        this.scrollBarColor = scrollBarColor;
    }

    /**
     * Called by Android {@link android.view.View#onDrawScrollBars(Canvas)}
     **/
    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b) {
        scrollBar.setColorFilter(scrollBarColor, PorterDuff.Mode.SRC_ATOP);
        scrollBar.setBounds(l, t, r, b);
        scrollBar.draw(canvas);
    }

    /**
     * Called by Android {@link android.view.View#onDrawScrollBars(Canvas)}
     **/
    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b) {
        scrollBar.setColorFilter(scrollBarColor, PorterDuff.Mode.SRC_ATOP);
        scrollBar.setBounds(l, t, r, b);
        scrollBar.draw(canvas);
    }
}

These methods are defined in View class, so the same princible should work of other views like ScrollView and ListView.

like image 25
Bojan Kseneman Avatar answered Sep 29 '22 11:09

Bojan Kseneman