的FastScroller
实现ListView
因 Android 版本而异。在 KitKat (API 19) 之前,拇指是Drawable
直接绘制在ListView
. 从 KitKat 开始,拇指是ImageView
添加到ListView
's 的ViewGroupOverlay
. 无论哪种情况,通过反射很容易得到我们需要的东西。
由于最终目标是将其与 一起使用ShowcaseView
,因此只关注拇指的尺寸和坐标是有意义的,无论其具体类型如何。这样,无论安卓版本,我们都可以使用ShowcaseView
's 。PointTarget
以下反射方法获取 aListView
的FastScroller
实例,使用适当的类型确定拇指的大小和位置Point
,如果可能,返回一个带有拇指中心点坐标的对象。
private Point getFastScrollThumbPoint(final ListView listView) {
try {
final Class<?> fastScrollerClass = Class.forName("android.widget.FastScroller");
final int[] listViewLocation = new int[2];
listView.getLocationInWindow(listViewLocation);
int x = listViewLocation[0];
int y = listViewLocation[1];
final Field fastScrollerField;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
fastScrollerField = AbsListView.class.getDeclaredField("mFastScroll");
}
else {
fastScrollerField = AbsListView.class.getDeclaredField("mFastScroller");
}
fastScrollerField.setAccessible(true);
final Object fastScroller = fastScrollerField.get(listView);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
final Field thumbImageViewField = fastScrollerClass.getDeclaredField("mThumbImage");
thumbImageViewField.setAccessible(true);
final ImageView thumbImageView = (ImageView) thumbImageViewField.get(fastScroller);
final int[] thumbViewLocation = new int[2];
thumbImageView.getLocationInWindow(thumbViewLocation);
x += thumbViewLocation[0] + thumbImageView.getWidth() / 2;
y += thumbViewLocation[1] + thumbImageView.getHeight() / 2;
}
else {
final Field thumbDrawableField = fastScrollerClass.getDeclaredField("mThumbDrawable");
thumbDrawableField.setAccessible(true);
final Drawable thumbDrawable = (Drawable) thumbDrawableField.get(fastScroller);
final Rect bounds = thumbDrawable.getBounds();
final Field thumbYField = fastScrollerClass.getDeclaredField("mThumbY");
thumbYField.setAccessible(true);
final int thumbY = (Integer) thumbYField.get(fastScroller);
x += bounds.left + bounds.width() / 2;
y += thumbY + bounds.height() / 2;
}
return new Point(x, y);
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
要将它与 一起使用ShowcaseView
,我们只需检查返回Point
值是否不为空,并传递从返回值创建的Builder
a PointTarget
。
Point thumbPoint = getFastScrollThumbPoint(listView);
if (thumbPoint != null) {
new ShowcaseView.Builder(this)
.setTarget(new PointTarget(thumbPoint))
.setContentTitle("ShowcaseView")
.setContentText("This is highlighting the fast scroll thumb")
.hideOnTouchOutside()
.build();
}