ViewPager中代码动态的添加小圆点作为指示器indicator,以及实现无限轮播

博客介绍了在Android中如何在ViewPager中动态添加小圆点作为指示器,并实现无限轮播。通过使用两个不同颜色的点图片,结合onPageSelected()方法更新选中状态,实现轮播效果。同时指出这种方法适用于头布局,且在onPageScrolled()中更新位置可观察到动画效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.首先我们需要一个相对布局装一个线性布局的容器和一个白色的小点作为选中的标识,用灰点表示未选中的情况。

    <android.support.v4.view.ViewPager
        android:id="@+id/view_pager"
        android:layout_width="match_parent"
        android:layout_height="230dp"/>

    <RelativeLayout
        android:layout_gravity="bottom|center_horizontal"
        android:layout_marginBottom="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">

        <LinearLayout
            android:id="@+id/ll_container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal">

        </LinearLayout>
        <View
            android:id="@+id/v_guide_white_point"
            android:layout_width="8dp"
            android:layout_height="8dp"
            android:background="@drawable/shape_point_white"/>

    </RelativeLayout>

两种颜色的小点的xml文件如下,使用自定义shape。
shape_point_gray.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <solid android:color="@android:color/darker_gray"/>

</shape>

shape_point_white.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">

    <solid android:color="@android:color/white"/>

</shape>

2.findViewById,其实轮播图大部分都是作为头布局的,所以我这就这样写了

        View headerView = View.inflate(mActivity, R.layout.header_view_pager, null);
        mViewPager = (ViewPager) headerView.findViewById(R.id.view_pager);
        llContainer= (LinearLayout) headerView.findViewById(R.id.ll_container);//小点的容器
        mWhiteView = headerView.findViewById(R.id.v_guide_white_point); //白点

3、根据viewpager数量动态添加小灰点

private void addPoints(int size) {
        for (int i = 0; i < size; i++) {
            //引导页下方的点
            View point = new View(mActivity);
            point.setBackgroundResource(R.drawable.shape_point_gray);
            //设置圆点大小
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(DensityUtil.dip2px(mActivity, 8), DensityUtil.dip2px(mActivity, 8));

            if (i > 0) {
                params.leftMargin = DensityUtil.dip2px(mActivity, 8);
            }
            point.setLayoutParams(params);
            llContainer.addView(point);
        }
    }

4.在我们滑动的时候,需要让白点移动到另一个灰点上覆盖,需要知道这个距离,这个距离需要在我们的线性布局llContainer布局完成后才能获得。

//布局完成的监听事件
        llContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mPointWidth = llContainer.getChildAt(1).getLeft() - llContainer.getChildAt(0).getLeft();
                llContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });

5.得到两个点之间的距离后,我们就需要在viewpager的监听事件中动态的更新白点的位置(也可以选择在onPageSelected()方法中在更新白点的位置),我们选择在onPageScrolled()方法中动态更新白点位置,这样还能看到动画的效果。

mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                //动态更新白点的位置
                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mWhiteView.getLayoutParams();
                params.leftMargin = (int) (mPointWidth * (position + positionOffset) + 0.5f);
                mWhiteView.setLayoutParams(params);
            }

            @Override
            public void onPageSelected(int position) {
                mTvTitle.setText(newsBean.top_stories.get(position).title);
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

其实上面一种方法比较坑,不管是实现无限轮播,还是自动轮播动态更新点的位置是一个坑。—>所以给我的感觉比较适合用在引导页中。

所以最方便方法还是使用两个小点的图片,在onPageSelected()中更换图片即可

1.也是先动态添加小点到容器中,一下方法都类似,所以简单说下

        for (int i = 0; i < mData.size(); i++) {
            //添加轮播图小点
            View indicatorView = new View(UIUtils.getContext());
            indicatorView.setBackgroundResource(R.drawable.indicator_normal);

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(DensityUtil.dip2px(UIUtils.getContext(), 5), DensityUtil.dip2px(UIUtils.getContext(), 5));
            params.leftMargin = DensityUtil.dip2px(UIUtils.getContext(), 5);
            params.bottomMargin = DensityUtil.dip2px(UIUtils.getContext(), 5);
            indicatorView.setLayoutParams(params);
            //默认选中第一个
            if (i == 0) {
                indicatorView.setBackgroundResource(R.drawable.indicator_selected);
            }

            mLinearLayout.addView(indicatorView);

2.监听事件

//监听滑动事件
        mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                for (int i = 0; i < mData.size(); i++) {
                    position = position % mData.size();
                    //还原背景
                    View indicatorView = mLinearLayout.getChildAt(i);
                    indicatorView.setBackgroundResource(R.drawable.indicator_normal);

                    if (i == position) {
                        indicatorView.setBackgroundResource(R.drawable.indicator_selected);
                    }
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });

3.实现无限轮播

//实现无限轮播的左边
        int extra = Integer.MAX_VALUE / 2 % mData.size();
        int index = Integer.MAX_VALUE / 2 - extra;
        mViewPager.setCurrentItem(index);
        //实现自动轮播
        final AutoScrollTask autoScrollTask = new AutoScrollTask();
        autoScrollTask.start();
        //实现自动轮播点击不滑动,松开滑动
        mViewPager.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:

                        autoScrollTask.stop();
                        break;
                    case MotionEvent.ACTION_UP:

                        autoScrollTask.start();
                        break;
                    default:
                        break;
                }
                return false;
            }
        });
    }

    class AutoScrollTask implements Runnable{

        //开始轮播
        private void start(){
            UIUtils.postSafelyDelayed(this,2000);
        }
        //停止轮播
        private void stop(){
            UIUtils.removeTast(this);
        }

        @Override
        public void run() {
            int item = mViewPager.getCurrentItem();
            ++item;
            mViewPager.setCurrentItem(item);
            start();
        }
    }

4.viewpager的getCount()需要改变,以及所以涉及到position的地方需要改变

private class PictureAdapter extends PagerAdapter {


        @Override
        public int getCount() {
            //实现无限轮播:对所有position的地方进行处理,防止越界
            return Integer.MAX_VALUE;
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            position = position % mData.size();
            ImageView iv = new ImageView(UIUtils.getContext());
            iv.setScaleType(ImageView.ScaleType.FIT_XY);
            iv.setImageResource(R.drawable.ic_default);

            BitmapHelper.display(iv, Constants.URLS.ICON + mData.get(position));
            container.addView(iv);
            return iv;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }

    }

    public View getHolderView() {

        return holderView;
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值