自定义ListView快速滑动条图标的几种方式

###前言
ListView快速滑动条FastScrolbar滚动条scrollbar是两个!!!

本文通过记录查找解决方法的思路和步骤。

快速定位查找

在listView源码中可以找到以下方法:

AbsListView类:

/**
 * Specifies the style of the fast scroller decorations.
 *
 * @param styleResId style resource containing fast scroller properties
 * @see android.R.styleable#FastScroll
 */
public void setFastScrollStyle(int styleResId) {
    if (mFastScroll == null) {
        mFastScrollStyle = styleResId;
    } else {
        mFastScroll.setStyle(styleResId);
    }
}

FastScroller类:

public void setStyle(@StyleRes int resId) {
       final Context context = mList.getContext();
       final TypedArray ta = context.obtainStyledAttributes(null,
               R.styleable.FastScroll, R.attr.fastScrollStyle, resId);
       //...省略
   }

可以看出,此方法就是listView用于设置快速滚动条样式的方法。那么下面我们需要知道的就是这个style里面有哪些属性是我们需要的。
可以通过R.attr.fastScrollStyle查看。

可以在AS的extLib目录下面的SDK里面找

SDK资源文件

↓↓↓↓

values文件夹

values文件夹2

通过values目录底下的三个xml可以找到fastScrollStyle相关的属性说明和默认主题。

找到默认主题:

theme.xml

<style name="Widget.FastScroll">
    <item name="thumbDrawable">?attr/fastScrollThumbDrawable</item>
    <item name="trackDrawable">?attr/fastScrollTrackDrawable</item>
    <item name="backgroundLeft">?attr/fastScrollPreviewBackgroundLeft</item>
    <item name="backgroundRight">?attr/fastScrollPreviewBackgroundRight</item>
    <item name="position">?attr/fastScrollOverlayPosition</item>
    <item name="textColor">?attr/fastScrollTextColor</item>
    <item name="thumbMinWidth">64dp</item>
    <item name="thumbMinHeight">52dp</item>
    <item name="textSize">52sp</item>
    <item name="minWidth">72dp</item>
    <item name="minHeight">72dp</item>
    <item name="padding">16dp</item>
</style>

默认主题里面的的属性也可以在attr.xml中找到注释说明

attrs.xml

 <!-- Drawable to use as the fast scroll thumb. -->
<attr name="fastScrollThumbDrawable" format="reference" />

所以可以通过fastScrollThumbDrawable设置快速滑动条图标

###方式一:theme修改。

Style.xml

<style name="cusFastScroll" parent="BaseAppTheme">
    <item name="android:fastScrollThumbDrawable">@mipmap/ic_clock</item>
</style>

AndroidMainfest.xml

activity android:name=".ui.activity.MainActivity"
    android:theme="@style/cusFastScroll"/>

通过主题设置滚动条样式,这种网络上蛮多例子的。这里就不做复述了。

###方式二:代码设置样式
通常在SDK开发中,无法修改AndroidMainfest相关设置,只能通过代码去设置activity的样式。

因为是主题设置,所以在getTheme()中查找相关的方法.找到如下方法:

/**
 * Place new attribute values into the theme.  The style resource
 * specified by <var>resid</var> will be retrieved from this Theme's
 * resources, its values placed into the Theme object.
 * 
 * <p>The semantics of this function depends on the <var>force</var>
 * argument:  If false, only values that are not already defined in
 * the theme will be copied from the system resource; otherwise, if
 * any of the style's attributes are already defined in the theme, the
 * current values in the theme will be overwritten.
 * 
 * @param resId The resource ID of a style resource from which to
 *              obtain attribute values.
 * @param force If true, values in the style resource will always be
 *              used in the theme; otherwise, they will only be used
 *              if not already defined in the theme.
 */
public void applyStyle(int resId, boolean force) {
    mThemeImpl.applyStyle(resId, force);
}

所以,我们可以通过applyStyle()在代码中动态设置样式。

getTheme().applyStyle(R.style.cusFastScroll,true);

###方式三:反射设置样式

try {
        Field f = AbsListView.class.getDeclaredField("mFastScroll");
        f.setAccessible(true);
        Object o=f.get(listView);
        f=f.getType().getDeclaredField("mThumbImage");
        //...
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

注:此方法没有经过测试

注意点:通过源码可以看到,fstScrollbar是通过setFastScrollEnabled(true)设置启用后才实例化的,所以必须setFastScrollEnabled(true)后,mFastScroll对象才不为空。才能通过反射获取到值。

##总结

  1. 解决问题通常先定位问题
  2. 找到解决问题的思路
  3. 对思路进行求证

上面就是对控件使用时候出现问题后的一个解决的步骤。

END

–Nowy

–2018.10.19

分享到