为ViewPager添加一个indicator

注意: CirclePageIndicator不会覆盖 ViewPagerOnPageChangeListener

ViewPager是Android提供的一个良心组件,有了它分分钟就可以实现了一个水平滑动的分页功能,其中用ViewPager来全屏展示图片是一个比较经典的使用场景,先来看一下效果图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qMR1U56D-1575536848002)(https://raw.githubusercontent.com/LyndonChin/Android-ScreenSlidePager/master/screenslidepager.gif)]

在每个Page的底部中间位置有一排圆圈,实心的圆圈用来指示当前显示的图片,它会随着手指滑动而移动,我们可以称之为 ViewPager 的 indicator

实现这个功能也比较简单,首先定义一个水平方向的LinearLayout用来显示 indicator,然后把这个LinearLayout和ViewPager作为子元素放在一个FrameLayout中,这样 indicator 的 LinearLayout 会在显示在 ViewPager 的上层,初步达到了显示效果,但是滑动效果还没有实现。

首先新建一个LinearLayout的子类 - CirclePageIndicator

public class CirclePageIndicator extends LinearLayout

如果要优雅地实现这个类,可以参考Android中如何优雅地自定义一个View

根据 ViewPager 的 page 数添加 indicator, 这里先定义好这个方法,等到后看再用。

private void addIndicator(int count) {
    for (int i = 0;  i < count; i++) {
        ImageView img = new ImageView(getContext());
        LayoutParams params = new LayoutParams(
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        params.leftMargin = indicatorSpacing;
        params.rightMargin = indicatorSpacing;
        img.setImageResource(R.drawable.circle_indicator_stroke);
        addView(img, params);
    }

    if (count > 0) {
        ((ImageView) getChildAt(0)).setImageResource(R.drawable.circle_indicator_solid);
    }
}

我希望 CirclePageIndicator 的用法足够简单,简单到只需要一条语句就可以把它附加到 ViewPager 上。

CirclePageIndicator indicator = (CirclePageIndicator) findViewById(R.id.indicator);
indicator.setViewPager(pager);

那么我们就为 CirclePageIndicator 添加 setViewPager 方法。

public void setViewPager(ViewPager pager) {
    userDefinedPageChangeListener = getOnPageChangeListener(pager);
    pager.setOnPageChangeListener(this);
    addIndicator(pager.getAdapter().getCount());
}

为了能监听 ViewPager 中 PageChange 时间,让 CirclePageIndicator 实现了 ViewPager.OnPageChangeListener 这个接口,然后在 setViewPager 的时候,为 ViewPager 添加这个 listener。

但是,这样问题又来了,如果 ViewPager 在传入之前已经有了 listener ,这里很显然会把之前的 listener 给覆盖掉,这个也好办,稍微 hack 一下,用反射把之前的 listener 拿到就可以了。

private ViewPager.OnPageChangeListener getOnPageChangeListener(ViewPager pager) {
    try {
        Field f = pager.getClass().getDeclaredField("mOnPageChangeListener");
        f.setAccessible(true);
        return (ViewPager.OnPageChangeListener) f.get(pager);
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
    return null;
}

剩下的把 ViewPager.OnPageChangeListener 中的方法实现一下,根据 page 的变化更新 indicator 就完成了。

猛戳源码

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值