登录 立即注册
安币:

查看: 626|回复: 4

Android轮播图实现教程,android开发视频教程

[复制链接]

317

主题

730

帖子

709

安币

手工艺人

发表于 2017-11-20 11:55:14 | 显示全部楼层 |阅读模式

        

        ListView的headerView设置为轮播图之后结合上/下拉刷新/加载的模式成为现在大多数APP的一个必须具备的功能,对于许多初学者来说想要实现轮播图这样一个集线程睡眠、自动处理、替换过程中刷新UI界面的组合功能非常困难,没有思路,感觉无从下手,去搜索各种实现方案,发现目前充斥着大量的类似于使用弃用组件Gallery这样的例子。

        本篇博客将通过分析轮播图的各个注意事项及实现思路来实现一个简易的轮播图。

        首先看下一下效果图;

        需求: 1.轮播,如轮播四张图:到第四张之后不会回到第一张而是继续向下一张切换;

        2.初始状态即可向前滑动

        3.轮播过程中会有状态切换以白点和黑点的方式呈现;

        

        

        ps:这里的魂斗罗见到有没有热血沸腾,情怀所在;

        实现步骤:

        一、轮播图部分采用的是ViewPager显示Layout布局,替换图片的方式

        1.为了让图片滑到最后一张不是以翻页的形式回到首页,getCount方法返回的是int最大值,这样就会有很多页;

        2.由于getCount方法返回整型最大值,所以使用的position采用取余的计算方法,虽然position会一直增加,但是显示的数据始终为固定数量;

[Java] 查看源文件 复制代码
package com.wu.rotateimgdemo;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by wubihang on 16/9/12.
 */
public class RotateVpAdapter extends PagerAdapter{

    private List datas;
    private Context context;
    private LayoutInflater inflater;

    public RotateVpAdapter(Context context) {
        this.context = context;
        inflater = LayoutInflater.from(context);
    }

    public void setDatas(List datas) {
        this.datas = datas;
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        // 为了让ViewPager到最后一页不会像翻书一样回到第一页
        // 设置页数为int最大值,这样向下滑动永远都是下一页
        return datas == null ? 0 : Integer.MAX_VALUE;
    }

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

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // position是int最大值所以这里可能是几百甚至上千,因此取余避免数组越界
        int newPosition = position % datas.size();
        View convertView = inflater.inflate(R.layout.item_vp, container, false);
        ImageView imageView = (ImageView) convertView.findViewById(R.id.item_iv);
        TextView textView = (TextView) convertView.findViewById(R.id.item_tv);
        textView.setText("文字内容" + newPosition);
        imageView.setImageResource(datas.get(newPosition).getImgId());

        container.addView(convertView);
        return convertView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {

    }
}

        二、设置轮播的线程

        1.轮播采用Handler对象的postDelayed方法,发送一个延时的任务;

        任务的内容是每隔固定时间让ViewPager当前页自增1,如果处于轮播状态再次延时执行该任务,这样只要轮播状态isRotate为true,就像死循环一样一直执行此轮播任务;

[Java] 查看源文件 复制代码
/**
     * 开始轮播
     */
    private void startRotate() {
        rotateRunnable = new Runnable() {
            @Override
            public void run() {
                int nowIndex = viewPager.getCurrentItem();
                viewPager.setCurrentItem(++nowIndex);
                if (isRotate) {
                    handler.postDelayed(rotateRunnable, TIME);
                }
            }
        };
        handler.postDelayed(rotateRunnable, TIME);
    }

        在onPause和onResume里对于轮播状态进行了处理

[Java] 查看源文件 复制代码
@Override
    protected void onResume() {
        super.onResume();
        isRotate = true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        isRotate = false;
    }

        三、设置轮播状态切换的小圆点

        1.设置的方式是动态的,有多少张轮播图就循环加入多少个小圆点;

        2.将position==0时的小圆点设置为黑色,默认选中第一张,剩下的设置为白色;

        这里的mipmap是我自己做的两张黑色的和白色的小圆点图片;

[Java] 查看源文件 复制代码
    /**
     * 添加轮播切换小点
     */
    private void addPoints() {
        // 有多少张图加载多少个小点
        for (int i = 0; i < datas.size(); i++) {
            ImageView pointIv = new ImageView(this);
            pointIv.setPadding(5,5,5,5);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(20,20);
            pointIv.setLayoutParams(params);

            // 设置第0页小点的为灰色
            if (i == 0) {
                pointIv.setImageResource(R.mipmap.point_grey);
            } else {
                pointIv.setImageResource(R.mipmap.point_white);
            }
            pointLl.addView(pointIv);
        }
    }

        四、设置ViewPager页切换时小圆点的颜色跟着改变

        1.当页切换时,获取所有的小圆点,将他们都设置为白色;

        2.获取当前页的小圆点,将它设置为黑色;

[Java] 查看源文件 复制代码
private void changePoints() {
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                if (isRotate) {
                    // 把所有小点设置为白色
                    for (int i = 0; i < datas.size(); i++) {
                        ImageView pointIv = (ImageView) pointLl.getChildAt(i);
                        pointIv.setImageResource(R.mipmap.point_white);
                    }
                    // 设置当前位置小点为灰色
                    ImageView iv = (ImageView) pointLl.getChildAt(position % datas.size());
                    iv.setImageResource(R.mipmap.point_grey);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

        这样简单的完成了一个ViewPager实现的轮播线程;

        分析及实现过程完毕,下面贴上全部代码!

        1.布局文件

        activity_main.xml

        分别是装载轮播图的ViewPager和装载小圆点的容器;

[Java] 查看源文件 复制代码




    <framelayout android:layout_height="300dp" android:layout_width="match_parent">

        

        
    </framelayout>



        ViewPager的页布局

        item_vp.xml

        分别是显示轮播图的ImageView和显示上面文字的TextView;

[Java] 查看源文件 复制代码

<framelayout android:layout_height="match_parent" android:layout_width="match_parent" xmlns:android="http://schemas.android.com/apk/res/android">


    

    

</framelayout>

        2.数据实体类

        这里运用的是本地图片,因此使用的是imgId;

        如果网络图片也可以加入,将图片源更改即可;

[Java] 查看源文件 复制代码
package com.wu.rotateimgdemo;

import java.io.Serializable;

/**
 * Created by wubihang on 16/9/12.
 */
public class RotateBean implements Serializable{

    private int imgId;
    private String imgUrl;

    public RotateBean() {
    }

    public RotateBean(String imgUrl) {
        this.imgUrl = imgUrl;
    }

    public RotateBean(int imgId) {
        this.imgId = imgId;
    }

    public RotateBean(int imgId, String imgUrl) {
        this.imgId = imgId;
        this.imgUrl = imgUrl;
    }

    public int getImgId() {
        return imgId;
    }

    public void setImgId(int imgId) {
        this.imgId = imgId;
    }

    public String getImgUrl() {
        return imgUrl;
    }

    public void setImgUrl(String imgUrl) {
        this.imgUrl = imgUrl;
    }
}

        3.适配器

        适配器部分需要注意:

        1)getCount的返回值

        2)使用时position取余的运用(防止数组越界)

[Java] 查看源文件 复制代码
package com.wu.rotateimgdemo;

import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

/**
 * Created by wubihang on 16/9/12.
 */
public class RotateVpAdapter extends PagerAdapter{

    private List datas;
    private Context context;
    private LayoutInflater inflater;

    public RotateVpAdapter(List datas, Context context) {
        this.datas = datas;
        this.context = context;
        inflater = LayoutInflater.from(context);
    }

    public RotateVpAdapter(Context context) {
        this.context = context;
        inflater = LayoutInflater.from(context);
    }

    public void setDatas(List datas) {
        this.datas = datas;
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        // 为了让ViewPager到最后一页不会像翻书一样回到第一页
        // 设置页数为int最大值,这样向下滑动永远都是下一页
        return datas == null ? 0 : Integer.MAX_VALUE;
    }

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

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // position是int最大值所以这里可能是几百甚至上千,因此取余避免数组越界
        int newPosition = position % datas.size();
        View convertView = inflater.inflate(R.layout.item_vp, container, false);
        ImageView imageView = (ImageView) convertView.findViewById(R.id.item_iv);
        TextView textView = (TextView) convertView.findViewById(R.id.item_tv);
        textView.setText(&quot;文字内容&quot; + newPosition);
        imageView.setImageResource(datas.get(newPosition).getImgId());

        container.addView(convertView);
        return convertView;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {

    }
}

        4.Activity部分,此部分代码比较多,请阅读时仔细梳理;

[Java] 查看源文件 复制代码
package com.wu.rotateimgdemo;

import android.os.Handler;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private static final int TIME = 3000;

    private ViewPager viewPager;
    private LinearLayout pointLl;// 轮播状态改变的小圆点容器
    private List datas;
    private RotateVpAdapter vpAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager = (ViewPager) findViewById(R.id.rotate_vp);
        pointLl = (LinearLayout) findViewById(R.id.rotate_point_container);

        buildDatas();// 构造数据
        vpAdapter = new RotateVpAdapter(datas, this);
        viewPager.setAdapter(vpAdapter);
        // ViewPager的页数为int最大值,设置当前页多一些,可以上来就向前滑动
        // 为了保证第一页始终为数据的第0条 取余要为0,因此设置数据集合大小的倍数
        viewPager.setCurrentItem(datas.size() * 100);

        // 开始轮播
        handler = new Handler();
        startRotate();
        // 添加轮播小点
        addPoints();
        // 随着轮播改变小点
        changePoints();
    }

    private void changePoints() {
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                if (isRotate) {
                    // 把所有小点设置为白色
                    for (int i = 0; i < datas.size(); i++) {
                        ImageView pointIv = (ImageView) pointLl.getChildAt(i);
                        pointIv.setImageResource(R.mipmap.point_white);
                    }
                    // 设置当前位置小点为灰色
                    ImageView iv = (ImageView) pointLl.getChildAt(position % datas.size());
                    iv.setImageResource(R.mipmap.point_grey);
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {

            }
        });
    }

    /**
     * 添加轮播切换小点
     */
    private void addPoints() {
        // 有多少张图加载多少个小点
        for (int i = 0; i < datas.size(); i++) {
            ImageView pointIv = new ImageView(this);
            pointIv.setPadding(5,5,5,5);
            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(20,20);
            pointIv.setLayoutParams(params);

            // 设置第0页小点的为灰色
            if (i == 0) {
                pointIv.setImageResource(R.mipmap.point_grey);
            } else {
                pointIv.setImageResource(R.mipmap.point_white);
            }
            pointLl.addView(pointIv);
        }
    }


    private Handler handler;
    private boolean isRotate = false;
    private Runnable rotateRunnable;

    /**
     * 开始轮播
     */
    private void startRotate() {
        rotateRunnable = new Runnable() {
            @Override
            public void run() {
                int nowIndex = viewPager.getCurrentItem();
                viewPager.setCurrentItem(++nowIndex);
                if (isRotate) {
                    handler.postDelayed(rotateRunnable, TIME);
                }
            }
        };
        handler.postDelayed(rotateRunnable, TIME);
    }

    @Override
    protected void onResume() {
        super.onResume();
        isRotate = true;
    }

    @Override
    protected void onPause() {
        super.onPause();
        isRotate = false;
    }

    private void buildDatas() {
        datas = new ArrayList<>();
        datas.add(new RotateBean(R.mipmap.big_image));
        datas.add(new RotateBean(R.mipmap.btn_normal));
        datas.add(new RotateBean(R.mipmap.icon_baoman));
        datas.add(new RotateBean(R.mipmap.btn_pressed));
    }
}

                                               
发表于 2017-11-20 23:37:51 | 显示全部楼层
感谢分享,楼主V5~

14

主题

9216

帖子

4745

安币

码皇(巴士元老)

Rank: 8Rank: 8

发表于 2017-11-21 16:32:03 | 显示全部楼层
不错不错,楼主辛苦了。。。

9

主题

9210

帖子

1827

安币

Android大神

Rank: 6Rank: 6

QQ达人

发表于 2017-11-22 13:47:12 | 显示全部楼层
楼主威武,以后多发干货,多办活动~!

8

主题

9066

帖子

3560

安币

码皇(巴士元老)

Rank: 8Rank: 8

发表于 2017-11-23 15:11:26 | 显示全部楼层
感谢分享,安卓巴士有你更精彩:lol
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

站长推荐

通过邮件订阅最新安卓weekly信息
上一条 /4 下一条

下载安卓巴士客户端

全国最大的安卓开发者社区
联系我们
关闭
合作电话:
15618560077
Email:
805941275@qq.com
商务市场合作/投稿
问题反馈及帮助
联系我们

广告投放| 下载客户端|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

快速回复 返回顶部 返回列表