一、显示ListView快速滑动块图标
设想这样一个场景,当ListView的内容有大于100页的情况下,如果想滑动到第80页,用手指滑动到指定位置,无疑是一件很费时的事情,如果想快速滑动到指定的位置,只需加上ListView的fastScrollEnabled属性等于true,启用快速滑动功能即可。
1
2
3
4
5
|
<ListView
android:id= "@android:id/list"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:fastScrollEnabled= "true" />
|
注意:默认只有当ListView的内容大于4页时,才会显示快速滑动块。读者可能会问,我是怎么知道要大于4页时,ListView才会显示快速滑动块图标。想知道原因,查一下ListView源码中fastScrollEnabled这个属性是怎么被初始化的吧。打开ListView的源码,你发现在ListView中并没有fastScrollEnabled这个属性,那就去父类AbsListView中找找吧,发现在AbsListView的构造方法中发现了初始化快速滑动块的代码(4.1.2源码在788-789行):
1
2
|
boolean enableFastScroll = a.getBoolean(R.styleable.AbsListView_fastScrollEnabled,
false
);
setFastScrollEnabled(enableFastScroll);
|
下面定位到setFastScrollEnabled方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
/**
* Enables fast scrolling by letting the user quickly scroll through lists by
* dragging the fast scroll thumb. The adapter attached to the list may want
* to implement {@link SectionIndexer} if it wishes to display alphabet preview and
* jump between sections of the list.
* @see SectionIndexer
* @see #isFastScrollEnabled()
* @param enabled whether or not to enable fast scrolling
*/
public void setFastScrollEnabled(boolean enabled) {
mFastScrollEnabled = enabled;
if
(enabled) {
if
(mFastScroller ==
null
) {
mFastScroller =
new
FastScroller(getContext(),
this
);
}
}
else
{
if
(mFastScroller !=
null
) {
mFastScroller.stop();
mFastScroller =
null
;
}
}
}
|
从setFastScrollEnabled方法得知,ListView的快速滑动块是通过FastScroller这个类来创建的,接下来打开FastScroller的构造方法,来看下它创建滑动块的流程。(FastScroller这个类在Eclipse关联的源码中看不到,要到Android Framework源码中才能找到,Demo下载地址中包含了这个文件),下面我们来看看FastScroller这个类的关键代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
package android.widget;
class FastScroller {
//....省略部分源码
// Minimum number of pages to justify showing a fast scroll thumb
private static int MIN_PAGES = 4;
private static final int THUMB_DRAWABLE = 1;
private static final int[] ATTRS =
new
int[] {
android.R.attr.fastScrollTextColor,
android.R.attr.fastScrollThumbDrawable,
// 定义快速滑动块图标的属性
android.R.attr.fastScrollTrackDrawable,
android.R.attr.fastScrollPreviewBackgroundLeft,
android.R.attr.fastScrollPreviewBackgroundRight,
android.R.attr.fastScrollOverlayPosition
};
//....省略部分源码
private Drawable mThumbDrawable;
// 快速滑动块图标
public FastScroller(Context context, AbsListView listView) {
mList = listView;
init(context);
}
private void init(Context context) {
// Get both the scrollbar states drawables
TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS);
useThumbDrawable(context, ta.getDrawable(THUMB_DRAWABLE));
// 获取当前主题ListView的快速滑动块图标
//....省略部分源码
}
private void useThumbDrawable(Context context, Drawable drawable) {
mThumbDrawable = drawable;
if
(drawable
instanceof
NinePatchDrawable) {
mThumbW = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.fastscroll_thumb_width);
mThumbH = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.fastscroll_thumb_height);
}
else
{
mThumbW = drawable.getIntrinsicWidth();
mThumbH = drawable.getIntrinsicHeight();
}
mChangedBounds =
true
;
}
void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
// Are there enough pages to require fast scroll? Recompute only if total count changes
if
(mItemCount != totalItemCount && visibleItemCount > 0) {
mItemCount = totalItemCount;
mLongList = mItemCount / visibleItemCount >= MIN_PAGES;
// 至少4页才显示滑动块
}
if
(mAlwaysShow) {
// android:fastScrollAlwaysVisible="true"
mLongList =
true
;
}
//....省略部分源码
}
//....省略部分源码
}
|
由上述代码得知,快速滑动块图标是由fastScrollThumbDrawable定义的,第8行定义了显示快速滑动块的最少页数,第51行onScroll方法负责处理显示快速滑动块的逻辑。
二、自定义快速滑动块图标
在eoe上看到有个贴子通过反射,动态修改FastScroller对象的mThumbDrawable属性来改变快速滑动块的图标,这也不为于一种实现方式,但反射的效率较低。下面将介绍使用Style的方式来自定义图标。
从FastScroller类的init方法中可以得知,mThumbDrawable是通过获取当前Activity主题的android.R.attr.fastScrollThumbDrawable属性赋值,既然是这样的话,我们完全可以自定义一个主题,覆盖android.R.attr.fastScrollThumbDrawable属性对应的Drawable不就搞定了!
1、定义一个主题
1
2
3
|
<style name=
"ListViewFastScrollThumb"
parent=
"@android:style/Theme.Light.NoTitleBar.Fullscreen"
>
<item name=
"android:fastScrollThumbDrawable"
>@drawable/ic_launcher</item>
</style>
|
2、当前ListView所在Activity应用自定义的主题
1
2
3
4
5
6
7
8
9
|
<activity
android:name=
"com.example.actionbardemo.MainActivity"
android:label=
"@string/app_name"
android:theme=
"@style/ListViewFastScrollThumb"
>
<intent-filter>
<action android:name=
"android.intent.action.MAIN"
/>
<category android:name=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
|
3、验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class MainActivity extends ListActivity {
private static final int[] ATTRS =
new
int[] {
android.R.attr.fastScrollThumbDrawable,
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setListAdapter(
new
ArrayAdapter<String>(
this
, android.R.layout.simple_list_item_1, Cheeses.sCheeseStrings));
ImageView imageView = (ImageView) findViewById(R.id.fastScrollDrawable);
Theme theme = getTheme();
TypedArray a = theme.obtainStyledAttributes(ATTRS);
Drawable drawable = a.getDrawable(0);
imageView.setBackgroundDrawable(drawable);
}
}
|
布局:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
<LinearLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id=
"@+id/container"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:orientation=
"vertical"
>
<ImageView
android:id=
"@+id/fastScrollDrawable"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
/>
<ListView
android:id=
"@android:id/list"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:fastScrollEnabled=
"true"
/>
</LinearLayout>
|
4、 原生的和自定义的快速滑动块效果图对比:
Demo下载地址: http://download.csdn.net/detail/xyang81/6788411