如何以编程方式查看 android listView 快速滚动缩略图?

How to get view of android listView fast scroll thumb programmatically?

我正在使用此 github 库 https://github.com/amlcurran/ShowcaseView 在用户入门期间(或安装后首次打开应用程序)显示我应用程序的视图元素上的叠加层。

此库需要将视图作为输入并在您的 activity 上显示叠加层,专注于该视图,以便您可以告诉用户更多关于该视图的信息。

我有一个启用了快速滚动的列表视图。我想在快速滚动拇指上显示覆盖。因此,我想查看我的 listView 的快速滚动拇指,但由于在 absListView 实现中缺少任何 public 方法,我无法执行此操作。

请帮忙。

ListViewFastScroller 实现因 Android 版本而异。在 KitKat (API 19) 之前,拇指是直接绘制在 ListView 上的 Drawable。从 KitKat 开始,拇指是添加到 ListViewViewGroupOverlayImageView。无论哪种情况,我们都可以很容易地通过反射得到我们需要的东西。

由于最终目标是将其与 ShowcaseView 一起使用,因此只关心拇指的尺寸和坐标是有意义的,而不管其具体类型如何。这样我们就可以使用ShowcaseViewPointTarget了,不管Android版本是什么

以下反射方法获取 ListViewFastScroller 实例,使用适当的类型确定拇指的大小和位置,并 returns 一个 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 一起使用,我们只需检查 returned Point 是否为空,然后将 Builder 传递给 PointTarget来自 return.

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();
}