ViewPager+ScheduledExecutorService实现轮播图(Android)

在app中使用轮播图可以用来插入广告或者轮替显示图片信息,比较美观,所以要是某个页面感觉空空的,加上轮播图就能去掉留白,让页面看起来更加充实,本篇主要记录使用ViewPager和定时任务实现轮播图。

一、布局准备

首先在drawable文件夹中新建xml文件对应轮播图中图片标记点的两种状态,当翻页到指定页面时,对应位置的标记点颜色为深色,其他点颜色为浅色。
drawable/dot_normal.xml:

xml version="1.0" encoding="utf-8"?>
<!--正常状态-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="oval">
    <corners android:radius="5dip"/>
   <solid android:color="#aaFFFFFF"/>
</shape>

drawable/dot_focused.xml:

<?xml version="1.0" encoding="utf-8"?>
<!--指定状态-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="oval">
    <corners android:radius="5dip"/>
   <solid android:color="#55000000"/>
</shape>

然后在value文件夹中新建资源文件id.xml,这样之后才能根据图片设置的id建立点击事件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="pager_image1" type="id" />
    <item name="pager_image2" type="id" />
    <item name="pager_image3" type="id" />
    <item name="pager_image4" type="id" />
    <item name="pager_image5" type="id" />
</resources>

在layout布局中加入ViewPager用于显示可翻页的图片背景和标记点

<!--轮播图布局容器-->
<FrameLayout
    android:id="@+id/fl"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <!--轮播图控件-->
    <android.support.v4.view.ViewPager
        android:id="@+id/vp"
        android:layout_width="match_parent"
        android:layout_height="160dp"/>
    <!--小点以及文字布局容器-->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="30dp"
        android:layout_gravity="bottom"
        android:background="#33000000"
        android:gravity="center_vertical"
        android:orientation="horizontal">
        <!--轮播图文字-->
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="8"
            android:text="图片标题"
            android:textColor="#fff"/>
        <!--小点布局-->
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:gravity="center_vertical"
            android:orientation="horizontal">

            <View
                android:id="@+id/dot_0"
                android:layout_width="5dip"
                android:layout_height="5dip"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:background="@drawable/dot_focused"/>

            <View
                android:id="@+id/dot_1"
                android:layout_width="5dip"
                android:layout_height="5dip"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:background="@drawable/dot_normal"/>

            <View
                android:id="@+id/dot_2"
                android:layout_width="5dip"
                android:layout_height="5dip"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:background="@drawable/dot_normal"/>

            <View
                android:id="@+id/dot_3"
                android:layout_width="5dip"
                android:layout_height="5dip"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:background="@drawable/dot_normal"/>

            <View
                android:id="@+id/dot_4"
                android:layout_width="5dip"
                android:layout_height="5dip"
                android:layout_marginLeft="2dip"
                android:layout_marginRight="2dip"
                android:background="@drawable/dot_normal"/>

        </LinearLayout>
    </LinearLayout>
</FrameLayout>
二、实现翻页事件

首先创建ViewPager适配器,其中getCount()用于返回要滑动的VIew的个数,destroyItem()从当前容器中删除指定位置(position)的View,instantiateItem()用来将当前视图添加到container中并返回当前View,isViewFromObject()不用管,按照官方提示来重写即可。

// 自定义Adapter
private class ViewPagerAdapter extends PagerAdapter {
    //返回页卡的数量
    @Override
    public int getCount() {
        return images.size();
    }
    @Override
    public boolean isViewFromObject(View arg0, Object arg1) {
        return arg0 == arg1;
    }
    @Override
    public void destroyItem(ViewGroup view, int position, Object object) {
        // TODO Auto-generated method stub
        view.removeView(images.get(position)) ;//删除页卡
    }
    //这个方法用来实例化页卡
    @Override
    public Object instantiateItem(ViewGroup view, int position) {
        // TODO Auto-generated method stub
        //添加图片控件到轮播图控件
        view.addView(images.get(position));
        return images.get(position);
    }

创建图片点击事件

//图片点击事件
private class pagerImageOnClick implements View.OnClickListener{

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.pager_image1:
                Toast.makeText(MainActivity.this, "图片1被点击", Toast.LENGTH_SHORT).show();
                break;
            case R.id.pager_image2:
                Toast.makeText(MainActivity.this, "图片2被点击", Toast.LENGTH_SHORT).show();
                break;
            case R.id.pager_image3:
                Toast.makeText(MainActivity.this, "图片3被点击", Toast.LENGTH_SHORT).show();
                break;
            case R.id.pager_image4:
                Toast.makeText(MainActivity.this, "图片4被点击", Toast.LENGTH_SHORT).show();
                break;
            case R.id.pager_image5:
                Toast.makeText(MainActivity.this, "图片5被点击", Toast.LENGTH_SHORT).show();
                break;
        }
    }
}

设置ViewPager

fl = (FrameLayout)findViewById(R.id.fl);
//获取屏幕宽高
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
// 屏幕宽度(像素)
int width = metric.widthPixels;
//设置布局容器宽度
fl.getLayoutParams().width=width;
//设置布局容器的高度
fl.getLayoutParams().height=width/2;


//声明轮播图控件
mViewPaper = (ViewPager) findViewById(R.id.vp);

//初始化显示的图片
images = new ArrayList<ImageView>();
//添加图片到图片集合
for (int i = 0; i < imageDrawables.length; i++) {
    //初始化控件
    ImageView imageView = new ImageView(this);
    //设置图片背景
    imageView.setBackgroundResource(imageDrawables[i]);
    imageView.setId(imageIds[i]);
    //设置点击事件
    imageView.setOnClickListener(new pagerImageOnClick());
    //图片添加到集合
    images.add(imageView);
}

//初始化轮播图文字
title = (TextView) findViewById(R.id.title);
//设置轮播图显示文字
title.setText(titles[0]);

//小点集合
dots = new ArrayList<View>();
//初始化小点添加到集合
dots.add(findViewById(R.id.dot_0));
dots.add(findViewById(R.id.dot_1));
dots.add(findViewById(R.id.dot_2));
dots.add(findViewById(R.id.dot_3));
dots.add(findViewById(R.id.dot_4));

//初始化适配器
adapter = new ViewPagerAdapter();
//轮播图绑定适配器
mViewPaper.setAdapter(adapter);
//轮播图滑动事件监听
mViewPaper.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    //页面切换后触发
    @Override
    public void onPageSelected(int position) {
        //设置轮播图文字
        title.setText(titles[position]);
        //设置当前小点图片
        dots.get(position).setBackgroundResource(R.drawable.dot_focused);
        //设置前一个小点图片
        dots.get(oldPosition).setBackgroundResource(R.drawable.dot_normal);
        //记录小点id
        oldPosition = position;
        //记录当前位置
        currentItem = position;
    }
    @Override
    public void onPageScrolled(int arg0, float arg1, int arg2) {
    }
    @Override
    public void onPageScrollStateChanged(int arg0) {
    }
});
三、实现动画轮播自动翻页

利用线程池定时执行动画轮播,在活动开始时即开始定时任务实现自动每隔2s翻页

/**
 * 利用线程池定时执行动画轮播
 */
ScheduledFuture beeperHandle;
@Override
protected void onStart() {
    // TODO Auto-generated method stub
    super.onStart();

    //初始化定时线程
    scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
    // 设定执行线程计划,初始2s延迟,每次任务完成后延迟2s再执行一次任务
     beeperHandle=scheduledExecutorService.scheduleWithFixedDelay(
            new ViewPageTask(),
            2,
            2,
            TimeUnit.SECONDS);
}
private class ViewPageTask implements Runnable {
    @Override
    public void run() {
        currentItem = (currentItem + 1) % imageIds.length;
        //发送消息
        mHandler.sendEmptyMessage(0);
    }
}


/**
 * 接收子线程传递过来的数据
 */
private Handler mHandler = new Handler() {
    public void handleMessage(android.os.Message msg) {
        mViewPaper.setCurrentItem(currentItem);
    };
};

到这里就可以实现轮播图的手动滑动、点击、动画轮播了,但是还有一个要注意的问题,在活动结束或者置于后台时应该停止此定时任务,否则将app置于后台再点击进去后,轮播的速度会变快很多,因为按照活动的生命周期,启动活动时调用oncreate方法再调用onstart()方法,每进入一次,就会新建一个轮播动画的任务,再加上以前进入时的定时任务还没有终止,任务叠加的越多轮播的速度就会快。所以我们可以利用生命周期重写onPause方法,在onPause()中新建一个线程来取消任务。

Override
    protected void onPause() {

        super.onPause();
//        currentItem=0;
        new Thread(new Runnable() {
            public void run() {
                //取消任务
                beeperHandle.cancel(true);
            }
        }).start();
    }

效果如下:
在这里插入图片描述


完整代码已经上传到码云了点击查看 如果有帮助的话请点一个star呀,笔芯❤

猜你喜欢

转载自blog.csdn.net/tensixchuan/article/details/87989023