Android中级:轮播图(一):实现ViewPager的无线自动循环

无限自动循环 = 无限循环 + 自动循环
无限循环 = 无限向左循环 + 无限向右循环
向左:图片由;右向左滑动
向右:图片由右向左滑动

这里写图片描述
接下来我们通过demo一步步的实现无限向右循环–>无限向左循环–>自动循环

Demo中viewpager中放有5张图片,我们可以向左向右滑动,但是
若当前页是第一页,则无法再向右滑动。
若当前页是最后一页,则无法再向左滑动。

一般情况:没有循环,需手滑

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#1A237E"
    tools:context=".MainActivity" >

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_centerInParent="true" />

</RelativeLayout>

MainActivity.java

public class MainActivity extends Activity {

    protected static final String tag = "MainActivity";
    private ViewPager viewpager;
    private List<ImageView> imageList = new ArrayList<ImageView>();
    private Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        initData();
        viewpager = (ViewPager) findViewById(R.id.viewpager);
        viewpager.setAdapter(new MyAdapter());
    }

    private void initData() {
        imageList.clear();
        ImageView iva = new ImageView(context);
        iva.setBackgroundResource(R.drawable.a);

        ImageView ivb = new ImageView(context);
        ivb.setBackgroundResource(R.drawable.b);

        ImageView ivc = new ImageView(context);
        ivc.setBackgroundResource(R.drawable.c);

        ImageView ivd = new ImageView(context);
        ivd.setBackgroundResource(R.drawable.d);

        ImageView ive = new ImageView(context);
        ive.setBackgroundResource(R.drawable.e);

        imageList.add(iva);
        imageList.add(ivb);
        imageList.add(ivc);
        imageList.add(ivd);
        imageList.add(ive);
    }

    public class MyAdapter extends PagerAdapter{
        //表示viewpager共存放了多少个页面
        @Override
        public int getCount() {
            return imageList.size();
        }

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

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            container.addView(imageList.get(position));
            return imageList.get(position);
        }

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

添加无限向左循环

可以无限次的向左滑动,需要对PagerAdapter的2个方法进行修改

return Integer.MAX_VALUE:viewpager里面有几乎无穷多个object
imageList.get(position % imageList.size());防止角标越界
//表示viewpager共存放了多少个页面
@Override
public int getCount() {
    return Integer.MAX_VALUE;//我们设置viewpager中有Integer.MAX_VALUE个页面
}
/**
 * position % imageList.size() 而不是position,是为了防止角标越界异常
 * 因为我们设置了viewpager子页面的数量有Integer.MAX_VALUE,而imageList的数量只是5。
 */
@Override
public Object instantiateItem(ViewGroup container, int position) {
    container.addView(imageList.get(position % imageList.size()));
    return imageList.get(position % imageList.size());
}
但是这样暴露一个缺点,就是可以向左滑动,但是当前页是第一页的时候,无法向右滑动,因为第一页的position是0。

解决方法:
    给viewpager设置当前页是第1000页,这样当前页的左边还有999页,右边还有Integer.MAX_VALUE - 1000页,
    无论是999,还是(Integer.MAX_VALUE - 1000),一般情况下是滑不到第一页或最后一页的。
    当然1000是自己设置的,也可以设置多加几个0。

添加无限向右循环

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    context = this;
    initData();
    viewpager = (ViewPager) findViewById(R.id.viewpager);
    viewpager.setAdapter(new MyAdapter());
    viewpager.setCurrentItem(1000);//当前页是第1000页 
}

添加自动循环

上面只是实现了无限循环,但还是用手动的,我们需要它每个一段时间(2秒)滑动一次。这就需要用到handler

int msgWhat = 0;
private Handler handler = new Handler(){
    public void handleMessage(android.os.Message msg) {
        viewpager.setCurrentItem(viewpager.getCurrentItem() + 1);//收到消息,指向下一个页面
        handler.sendEmptyMessageDelayed(msgWhat, 2000);//2S后在发送一条消息,由于在handleMessage()方法中,造成死循环。
        Log.d(tag, "handleMessage");
    };
};
同时在onCreat()方法中发送消息:handler.sendEmptyMessageDelayed(msgWhat, 2000);

出现的bug

Bug1:内存泄露

Bug:虽然我们实现了 无限自动循环功能,但当我们由MainActivity调转到SecondActivity的时候,通过Log.d(tag, “handleMessage”);发现handler还在发送消息,这就是内存泄露,所以我们需要在ManiActivity不可见不可交互的时候移除message。

解决方法:在onStop()里移除message
/**
 * 当MainActivity不可见的时候让handler停止发送消息
 * 防止内存泄露
 */
@Override
protected void onStop() {
    super.onStop();
    handler.removeMessages(msgWhat);
}

Bug2:再次回到 当前页,viewpager不再自动循环

由于我们把handler.sendEmptyMessageDelayed(msgWhat, 2000);写在了onCreate(),当我们由MainActivity调转到SecondActivity的时候,在回来MainActivity的时候,MainActivity并没有被销毁,onCreate()方法并不会再执行。

解决方法:写在onResume()里面
/**
 * activity可见可交互的时候就开始发送消息,开启循环
 */
@Override
protected void onResume() {
    super.onResume();
    handler.sendEmptyMessageDelayed(msgWhat, 2000);
}

所以,最后的完整代码是:

public class MainActivity extends Activity {

    protected static final String tag = "MainActivity";
    private ViewPager viewpager;
    private List<ImageView> imageList = new ArrayList<ImageView>();
    private Context context;
    int msgWhat = 0;
    private Handler handler = new Handler(){
        public void handleMessage(android.os.Message msg) {
            viewpager.setCurrentItem(viewpager.getCurrentItem() + 1);//收到消息,指向下一个页面
            handler.sendEmptyMessageDelayed(msgWhat, 2000);//2S后在发送一条消息,由于在handleMessage()方法中,造成死循环。
            Log.d(tag, "handleMessage");
        };
    };
    private Button btn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        initData();
        viewpager = (ViewPager) findViewById(R.id.viewpager);
        viewpager.setAdapter(new MyAdapter());
        viewpager.setCurrentItem(1000);//当前页是第1000页

        // Button只是为了验证内存泄露
        btn = (Button) findViewById(R.id.btn);
        btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(context, SecondActivity.class);
                startActivity(intent);
            }
        });
    }

    private void initData() {
        imageList.clear();
        ImageView iva = new ImageView(context);
        iva.setBackgroundResource(R.drawable.a);

        ImageView ivb = new ImageView(context);
        ivb.setBackgroundResource(R.drawable.b);

        ImageView ivc = new ImageView(context);
        ivc.setBackgroundResource(R.drawable.c);

        ImageView ivd = new ImageView(context);
        ivd.setBackgroundResource(R.drawable.d);

        ImageView ive = new ImageView(context);
        ive.setBackgroundResource(R.drawable.e);

        imageList.add(iva);
        imageList.add(ivb);
        imageList.add(ivc);
        imageList.add(ivd);
        imageList.add(ive);
    }

    public class MyAdapter extends PagerAdapter{
        //表示viewpager共存放了多少个页面
        @Override
        public int getCount() {
            return Integer.MAX_VALUE;//我们设置viewpager中有Integer.MAX_VALUE个页面
        }

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

        /**
         * position % imageList.size() 而不是position,是为了防止角标越界异常
         * 因为我们设置了viewpager子页面的数量有Integer.MAX_VALUE,而imageList的数量只是5。
         */
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            container.addView(imageList.get(position % imageList.size()));
            return imageList.get(position % imageList.size());
        }

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

    /**
     * activity可见可交互的时候就开始发送消息,开启循环
     */
    @Override
    protected void onResume() {
        super.onResume();
        handler.sendEmptyMessageDelayed(msgWhat, 2000);
    }

    /**
     * 当MainActivity不可见的时候让handler停止发送消息
     * 防止内存泄露
     */
    @Override
    protected void onStop() {
        super.onStop();
        handler.removeMessages(msgWhat);
    }
}
也可以不使用`Integer.MAX_VALUE`,还是以前的

@Override
public int getCount() {
return imgsList.size();
// return Integer.MAX_VALUE;
}

```
int index = (viewPager.getCurrentItem() + 1) % imgsList.size();
viewPager.setCurrentItem(index);

“`

源码

ViewPager无线自动循环

这样我们就实现了viewpager的自动无限循环功能,而且手动向左滑、向右滑都可以,接下来我们添加indicator。

Android中级:轮播图(二):实现indicator。地址:http://blog.csdn.net/ss1168805219/article/details/52294657

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值