ViewPager实现图片轮播,下方带小点显示当前位置

先来张效果图

还是从布局文件开始说,使用到的布局文件就一个content_main.xml,因为小点图片是覆盖在大图片的上面的,所以这里要用Framelayout,包含了两个linearLayout,一个放置大图片,一个放置小图片的,这里在代码中动态添加,具体代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main" tools:context=".MainActivity">

    <TextView
        android:id="@+id/test_hello"
        android:text="点击切换" android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/newsHead_layout"/>
    <FrameLayout
        android:id="@+id/newsHead_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

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

        </LinearLayout>

        <LinearLayout
            android:id="@+id/news_headView_dot"
            android:layout_width="wrap_content"
            android:layout_height="20dp"
            android:layout_gravity="bottom|right"
            android:layout_marginRight="10dp"
            android:gravity="center"
            android:orientation="horizontal"></LinearLayout>
    </FrameLayout>
</RelativeLayout>

对应的类为MainActivity,具体代码如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener,
        ListView.OnItemClickListener{
    private ImageHandler handler = new ImageHandler(new WeakReference<MainActivity>(this));
    private ViewPager vp;
    private List<View> ivs;//大图集合
    private List<ImageView> dotIvs;//小点集合
    private int currentPosition = 0;// 记录当前图片的位置

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.content_main);
        ivs = new ArrayList<View>();
        dotIvs = new ArrayList<ImageView>();
        initHeadView();
        TextView tvHello = (TextView)findViewById(R.id.test_hello);
        tvHello.setOnClickListener(this);

    }
    private void initHeadView() {
        LinearLayout pagerLayout = (LinearLayout) findViewById(R.id.view_pager_content);
        vp = new ViewPager(this);
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        //设置viewpager的宽高,高是宽度的特定比例,我的手机宽是720的,做了下适配
        vp.setLayoutParams(new LinearLayout.LayoutParams(dm.widthPixels, dm.widthPixels * 462 / 720));
        pagerLayout.addView(vp);

        ivs.clear();
        dotIvs.clear();
        //这里有三张图片,所以i<3
        for (int i = 0; i < 3; i++) {
            ImageView iv = new ImageView(this);
            iv.setId(i);// 处理其点击事件
            iv.setOnClickListener(this);

            iv.setScaleType(ImageView.ScaleType.FIT_XY);
            // manager.bindBitmap(iv, mainNews.get(i).getPicUrl());
            // iv.setBackgroundResource(R.id.main_logo);
            if (i == 0) {
                iv.setImageResource(R.drawable.rolling1);
            } else if (i == 1) {
                iv.setImageResource(R.drawable.rolling2);
            } else if (i == 2) {
                iv.setImageResource(R.drawable.rolling3);
            }
            ivs.add(iv);// 加入大图集合
            ImageView dotIv = new ImageView(this);
            dotIv.setImageResource(R.drawable.s_banner_unselect);
            dotIv.setPadding(5, 0, 5, 0);//设置小点的间距left top right bottom
            dotIvs.add(dotIv);// 加入小点集合
        }

        //小点所在的linearlayout
        LinearLayout dotsLl = (LinearLayout) findViewById(R.id.news_headView_dot);
        dotsLl.removeAllViews();

        for (int i = 0; i < dotIvs.size(); i++) {
            dotsLl.addView(dotIvs.get(i));
        }
        // TODO Auto-generated method stub
        if (ivs.size() == 0) {
            return;
        }
        vp.setAdapter(new FVpAdapter());
//        vp.setCurrentItem(Integer.MAX_VALUE/2);//默认在中间,使用户看不到边界
        //开始轮播效果
        handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);
        vp.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageSelected(int arg0) {
                // TODO Auto-generated method stub
//				 Toast.makeText(MainSlidingMenuActivity.this, "这是第" + arg0 % dotIvs.size() + "张图片", Toast.LENGTH_SHORT).show();
                currentPosition = arg0;
                handler.sendMessage(Message.obtain(handler, ImageHandler.MSG_PAGE_CHANGED, arg0, 0));
                //
                selector(currentPosition);
            }
            //覆写该方法实现轮播效果的暂停和恢复
            @Override
            public void onPageScrollStateChanged(int arg0) {
                switch (arg0) {
                    case ViewPager.SCROLL_STATE_DRAGGING:
                        handler.sendEmptyMessage(ImageHandler.MSG_KEEP_SILENT);
                        break;
                    case ViewPager.SCROLL_STATE_IDLE:
                        handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);
                        break;
                    default:
                        break;
                }

            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
                // TODO Auto-generated method stub

            }

        });

        // 更改viewPager的属性
        try {
            Field mScroller;
            mScroller = ViewPager.class.getDeclaredField("mScroller");
            mScroller.setAccessible(true);

           FixedSpeedScroller scroller = new FixedSpeedScroller(
                    vp.getContext());// 调用这个构造方法即可
            // scroller.setFixedDuration(5000);
            mScroller.set(vp, scroller);
        } catch (NoSuchFieldException e) {
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }

        vp.setCurrentItem(currentPosition);// 从这个位置开始前后都可以无限滑动
        vp.getNextFocusUpId();
        selector(currentPosition);

    }
    //选择小点的方法
    private void selector(int index) {
        if (dotIvs.size() == 0) {
            return;

        }
        index = index % dotIvs.size();
        int len = dotIvs.size();
        for (int i = 0; i < len; i++) {
            if (index == i) {
                dotIvs.get(i).setImageResource(R.drawable.s_banner_select);
            } else {
                dotIvs.get(i).setImageResource(R.drawable.s_banner_unselect);
            }
        }
    }


    @Override
    public void onClick(View v) {
            switch (v.getId()){
                case R.id.test_hello:
                    Toast.makeText(MainActivity.this, "hello", Toast.LENGTH_SHORT).show();
                    int count = ivs.size();
                    //设置点击切换,如果到头则重新开始
                    int item = currentPosition+1 == count? 0 : currentPosition+1;
                    vp.setCurrentItem(item,true);
                    break;
            }
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    }

    class FVpAdapter extends PagerAdapter {

        @Override
        public int getCount() {
            // TODO Auto-generated method stub
            // return ivs.size();
            return Integer.MAX_VALUE;
        }

        @Override
        public boolean isViewFromObject(View arg0, Object arg1) {
            // TODO Auto-generated method stub
            return arg0 == arg1;
        }

        @Override
        public void destroyItem(View arg0, int arg1, Object arg2) {
            // TODO Auto-generated method stub
        //不把划过去的View清空,否则再往回滑的话会变空白的View
			//((ViewPager) arg0).removeView(ivs.get(arg1 % ivs.size()));
        }

        @Override
        public Object instantiateItem(View arg0, int arg1) {
            // TODO Auto-generated method stub

            try {
                // ((ViewPager) arg0).addView(list.get(arg1),0);
//                ((ViewPager) arg0).removeView(ivs.get(arg1 % ivs.size()));
                ((ViewPager) arg0)
                        .addView(ivs.get(arg1 % ivs.size()));
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
            }

            return ivs.get(arg1 % ivs.size());

        }

    }
    // 自定义scroller更改viewPager默认的切换时间
    class FixedSpeedScroller extends Scroller {
        //切换一秒钟
        private int mDuration = 1000;

        public FixedSpeedScroller(Context context) {
            super(context);
        }

        public FixedSpeedScroller(Context context, Interpolator interpolator) {
            super(context, interpolator);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy,
                                int duration) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }

        @Override
        public void startScroll(int startX, int startY, int dx, int dy) {
            // Ignore received duration, use fixed one instead
            super.startScroll(startX, startY, dx, dy, mDuration);
        }
    }

    private static class ImageHandler extends Handler{
        /**
         * 请求更新显示的View。
         */
        protected static final int MSG_UPDATE_IMAGE  = 1;
        /**
         * 请求暂停轮播。
         */
        protected static final int MSG_KEEP_SILENT   = 2;
        /**
         * 请求恢复轮播。
         */
        protected static final int MSG_BREAK_SILENT  = 3;
        /**
         * 记录最新的页号,当用户手动滑动时需要记录新页号,否则会使轮播的页面出错。
         * 例如当前如果在第一页,本来准备播放的是第二页,而这时候用户滑动到了末页,
         * 则应该播放的是第一页,如果继续按照原来的第二页播放,则逻辑上有问题。
         */
        protected static final int MSG_PAGE_CHANGED  = 4;

        //轮播间隔时间
        protected static final long MSG_DELAY = 3000;

        //使用弱引用避免Handler泄露.这里的泛型参数可以不是Activity,也可以是Fragment等
        private WeakReference<MainActivity> weakReference;
        private int currentItem = 0;

        protected ImageHandler(WeakReference<MainActivity> wk){
            weakReference = wk;
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MainActivity activity = weakReference.get();
            if (activity==null){
                //Activity已经回收,无需再处理UI了
                return ;
            }
            //检查消息队列并移除未发送的消息,这主要是避免在复杂环境下消息出现重复等问题。
            if (activity.handler.hasMessages(MSG_UPDATE_IMAGE)){
                //次句不加,更换变得很不稳定
                activity.handler.removeMessages(MSG_UPDATE_IMAGE);
            }
            switch (msg.what) {
                case MSG_UPDATE_IMAGE:
                    currentItem++;
                    activity.vp.setCurrentItem(currentItem);
                    //准备下次播放
                    activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
                    break;
                case MSG_KEEP_SILENT:
                    //只要不发送消息就暂停了
                    break;
                case MSG_BREAK_SILENT:
                    activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY);
                    break;
                case MSG_PAGE_CHANGED:
                    //记录当前的页号,避免播放的时候页面显示不正确。
                    currentItem = msg.arg1;
                    break;
                default:
                    break;
            }
        }
    }


}
代码中注释已经很详细了,这里就不在说明,大家有问题的可以给我留言
源码下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值