Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set scrollbar thumb programmatically in Android?

I know listview can set scrollbar thumb in XML like this Android:scrollbarThumbVertical etc.

But I'm creating a listview instance in the java code and I maybe need to set different scrollbar thumb. Is there a method can set scrollbar thumb programmatically?

like image 724
dreamtale Avatar asked Mar 15 '12 04:03

dreamtale


3 Answers

You can achieve that via reflection:

try
{
    Field mScrollCacheField = View.class.getDeclaredField("mScrollCache");
    mScrollCacheField.setAccessible(true);
    Object mScrollCache = mScrollCacheField.get(listview);
    Field scrollBarField = mScrollCache.getClass().getDeclaredField("scrollBar");
    scrollBarField.setAccessible(true);
    Object scrollBar = scrollBarField.get(mScrollCache);
    Method method = scrollBar.getClass().getDeclaredMethod("setVerticalThumbDrawable", Drawable.class);
    method.setAccessible(true);
    method.invoke(scrollBar, getResources().getDrawable(R.drawable.scrollbar_style));
}
catch(Exception e)
{
    e.printStackTrace();
}

The above code executes as:

listview.mScrollCache.scrollBar.setVerticalThumbDrawable(getResources().getDrawable(R.drawable.scrollbar_style));
like image 198
Eng.Fouad Avatar answered Nov 01 '22 20:11

Eng.Fouad


I modified the answer to make it a method 100% programmatically

   public static void ChangeColorScrollBar(View Scroll, int Color, Context cxt){

   try
   {
       Field mScrollCacheField = View.class.getDeclaredField("mScrollCache");
       mScrollCacheField.setAccessible(true);
       Object mScrollCache = mScrollCacheField.get(Scroll);
       Field scrollBarField = mScrollCache.getClass().getDeclaredField("scrollBar");
       scrollBarField.setAccessible(true);
       Object scrollBar = scrollBarField.get(mScrollCache);
       Method method = scrollBar.getClass().getDeclaredMethod("setVerticalThumbDrawable", Drawable.class);
       method.setAccessible(true);

       Drawable[] layers = new Drawable[1];
       ShapeDrawable sd1 = new ShapeDrawable(new RectShape());
       sd1.getPaint().setColor(cxt.getResources().getColor(Color));
       sd1.setIntrinsicWidth(Math.round(cxt.getResources().getDimension(R.dimen.dp_3)));
       layers[0] = sd1;

       method.invoke(scrollBar, layers);
   }
   catch(Exception e)
   {
       e.printStackTrace();
   }

}

like image 37
toni Avatar answered Nov 01 '22 20:11

toni


I didn't know the answer to this, but after a bit of digging around I don't think it's possible without a load of hassle.

This xml attribute is actually associated with a View, not a ListView - In the Android View source code, it seems that the only place that it is setting the vertical thumb drawable is the 'initializeScrollbars' method. Now this method isn't private, so we can extend any child of View and override this method, but the issue is that a crucial component needed to set the thumb drawable, the ScrollabilityCache, is private without any getter methods.

So without rewriting a lot of the code I don't think there's any easy way to do this - sorry!

like image 2
Martyn Avatar answered Nov 01 '22 20:11

Martyn