android自定义轮播图广告

前段时间自己自定义了一个轮播图,使用起来很简单,分享给大家使用,如有什么缺陷或是问题,请留言提出建议。

我自定义的类叫做BannerView.java,整个轮播图的实现都在这个类里面,在这个类里面我向外提供了很多方法,可以根据项目情况或是个人喜欢定义,比如有一个设置指示器位置的方法(左中右,默认是居中),一个设置指示器样式的方法,默认是引用我自己画的圆点,想要其他样式可以自己去定义,还有一个就是播放的时间方法,BannerView里面注释都很清楚。

先看看效果图吧,因为图片颜色原因在这里指示器看不是很清楚

轮播图效果图

在看看使用的方法

一。在布局文件中添加自定义的轮播图控件

二。添加图片资源,这里添加了三张图片

三。最后一步,让轮播图轮播起来,那就是开启定时器,关闭页面是关闭定时器,在生命周期中调用

自此,轮播图功能就实现了,是不是很简单,好了接下来就是BannerView.java这个最重要的类了,简单说一下某些主要的实现功能,下文后面会给出完整代码

既然是自定义View,不关联任何布局xml文件,那么首先当然是动态创建最外层布局,我用了一个FrameLayout,里面包含一个ViewPager,在最下面是一个LinearLayout,用来存放指示器的,实现代码如下:

接下来是指示器的实现,也是动态创建的,同时还要设置指示器的位置,动态创建的过程代码量比较多,就不贴出。

这个自定义轮播图的原理是使用ViewPager来实现的,所以肯定需要一个ViewPager的适配器,里面最主要的方法是根据外面setData()时传入的List<String> 的size来动态创建ImageView,然后使用Glide来加载图片,代码如下:

还有一点就是轮播图是可以手动滑动的,所以有一个需要注意的问题就是,当你手动滑动的时候,轮播图的自动播放功能要失效,当你不手动去滑动的时候,轮播图又可以自动去轮播,所以需要一个boolean去判断当前是否是出于手动滑动状态,若是,定时器就不向handler发送信息,不做切换图片的操作,当没有手动滑动,定时器就像handler发送信息,实现图片切换,代码如下:

好了就讲这么多了,其实挺简单的,若觉得不好,请给出建议,大家一起学习,若觉得好,就关注分享给身边需要的朋友吧

BannerView.java代码:

package qin.zszc.com.basiclib.widget.custom;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.bumptech.glide.Glide;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import qin.zszc.com.basiclib.R;

/**
 * Created by xcfor on 2018/7/11.
 */

public class BannerView extends FrameLayout implements ViewPager.OnPageChangeListener {

    public final int INDICATOR_LOCATION_CENTER_BUTTON = 0x1;//指示器居中
    public final int INDICATOR_LOCATION_LEFT_BUTTON = 0x2;//指示器居左
    public final int INDICATOR_LOCATION_RIGHT_BUTTON = 0x3;//指示器居右
    public final int BANNER_DELAY_TIME = 1000; //轮播图延迟时间
    public final int BANNER_DEF_TIIME = 5000;//轮播图默认切换时间

    /**
     * 存放圆点指示器
     */
    private LinearLayout mIndecatorLayout;
    private PagerAdapter mAdapter;
    private List<String> mUrls; //图片路径list
    private Context mContext;
    private ViewPager mViewPager;


    private boolean mIsScrollingByUser;// 用户手动滑动广告中
    private int mIndicatorDotWidth;//轮播切换小圆点宽度默认宽度
    private int mCurrentPos = 0;//当前页pos
    private int mPrePos = 0; //历史页pos
    private int mCount;//轮播图总数
    private int mIndicatorLocation = 1;//默认值为1:居中  2:左  3:右
    private boolean mChangeIndecatorStyle = false;//是否自定义指示器的样式
    private float mScale;//显示度量的密度

    /**
     * 定时滚动定时器
     */
    private Timer mTimer;
    private TimerTask mTask;


    /**
     * 接收定时器信息的handler
     */
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            int what = msg.what;
            switch (what) {
                case 0:
                    if (mViewPager != null) {
                        if (!mIsScrollingByUser) {
                            if (mCurrentPos == mUrls.size()) {
                                mCurrentPos = 0;
                            } else {
                                mCurrentPos++;
                            }
                        }
                        mViewPager.setCurrentItem(mCurrentPos);
                    }
                    break;
            }
        }
    };

    public BannerView(@NonNull Context context) {
        super(context);
        this.mContext = context;
    }

    public BannerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        this.mContext = context;
    }

    public BannerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    public void init() {

        if (mUrls.size() != 1) {
            mViewPager.addOnPageChangeListener(this);
        }
        //切换画面
        mViewPager.setPageTransformer(true, new MyPageTransformer());
        mIndecatorLayout.removeAllViews();
        //向线性布局中添加小圆点指示器
        if (mUrls.size()>1){
            View dot;
            LinearLayout.LayoutParams params;
            WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics displayMetrics = new DisplayMetrics();
            windowManager.getDefaultDisplay().getMetrics(displayMetrics);
            int width = displayMetrics.widthPixels;
            for (int i = 0; i < mCount; i++) {
                dot = new View(mContext);
                params = new LinearLayout.LayoutParams(mIndicatorDotWidth, mIndicatorDotWidth);
                params.setMargins(mIndicatorDotWidth, 0, 0, dip2px(10));
                dot.setLayoutParams(params);
                dot.setBackgroundResource(R.drawable.basiclib_dot_bg_selector);
                dot.setEnabled(false);//默认设为非选中
                mIndecatorLayout.addView(dot);
            }
            //指示器图标的位置
            switch (mIndicatorLocation){
                case INDICATOR_LOCATION_CENTER_BUTTON:
                    if (mCount % 2 == 0) {
                        mIndecatorLayout.setPadding(width / 2 - (mCount * mIndicatorDotWidth), 0, 0, 8);
                    } else {
                        mIndecatorLayout.setPadding(width / 2 - (mCount * mIndicatorDotWidth), 0, 0, 8);
                    }
                    break;
                case INDICATOR_LOCATION_LEFT_BUTTON:
                    mIndecatorLayout.setPadding(0, 0, 0, 8);
                    break;
                case INDICATOR_LOCATION_RIGHT_BUTTON:
                    mIndecatorLayout.setPadding(width - ((mCount * 2+1) * mIndicatorDotWidth), 0, 0, 8);
                    break;
            }
            int midPos = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % mCount;
            mCurrentPos = midPos;
            mIndecatorLayout.getChildAt(0).setEnabled(true);
            mViewPager.setCurrentItem(midPos);
        }else {
            mIndecatorLayout.setVisibility(GONE);
        }

    }

    /**
     * 设置指示器的位置
     *
     * @param location
     */
    public void relayoutIndicator(int location) {
        mIndicatorLocation = location;
    }


    /**
     * 自定义指示器入口
     *
     * @param style
     */
    public void customerIndicatorEntry(int style) {
        if (!mChangeIndecatorStyle) {
            return;
        } else {
            changeIndicator(style);
        }
    }

    /**
     * 改变指示器
     * @param style
     */
    public void changeIndicator(int style) {
        for (int i = 0; i < mCount; i++) {
            mIndecatorLayout.getChildAt(i).setBackgroundResource(style);
        }
    }


    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        //动态创建轮播图最外围布局
        mIndicatorDotWidth = dip2px(4);
        FrameLayout fl = new FrameLayout(mContext);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 
        	ViewGroup.LayoutParams.MATCH_PARENT);
        mViewPager = new ViewPager(mContext);
        mViewPager.setLayoutParams(params);
        fl.addView(mViewPager);

        //动态创建指示器外围布局
        mIndecatorLayout = new LinearLayout(mContext);
        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        params.gravity = Gravity.BOTTOM;
        mIndecatorLayout.setLayoutParams(params);
        mIndecatorLayout.setOrientation(LinearLayout.HORIZONTAL);
        fl.addView(mIndecatorLayout);
        addView(fl);
    }

    /**
     * 获取数据
     */
    public void setData(List<String> urls) {
        if (urls.isEmpty()) {
            return;
        }
        this.mUrls = urls;
        mCount = mUrls.size();
        if (mAdapter == null) {
            mAdapter = new MyAdapter(mUrls);
            mViewPager.setAdapter(mAdapter);
        }else{
            //更新viewpager视图
            //--更新原点指示器
            mAdapter.notifyDataSetChanged();
        }
        init();
    }

    /**
     * 默认时间启动定时器
     */
    public void startBannerScrollTask(){
        if (mUrls.size() != 1){
            startBannerScrollTask(BANNER_DEF_TIIME);
        }
    }

    /**
     * 给外边调用,可以使用外边的适配器
     * @param timer
     */
    public void setScrollTask(Timer timer ,long timeSpace){
        if (mCount == 0){
            return;
        }
        mTask = new TimerTask() {
            @Override
            public void run() {
                if (!mIsScrollingByUser){
                    mHandler.sendEmptyMessage(0);
                }

            }
        };
        timer.schedule(mTask,BANNER_DELAY_TIME, timeSpace);
    }


    //开启轮播图定时器
    public void startBannerScrollTask(long timeSpace) {
        if (mCount == 0) {
            return;
        }
        mTimer = new Timer(true);
        mTask = new TimerTask() {
            @Override
            public void run() {
                if (!mIsScrollingByUser){
                    mHandler.sendEmptyMessage(0);
                }

            }
        };
        mTimer.schedule(mTask, BANNER_DELAY_TIME, timeSpace);//1000ms后按指定时间间隔轮播
    }

    /**
     * 关闭轮播图定时器
     */
    public void stopBannerTask() {
        if (mTask != null) {
            mTask.cancel();
        }
    }



    /**
     * 根据手机的分辨率从 dip 的单位 转成为 px(像素)
     * 改全变量
     */
    public  int dip2px(float dpValue) {
        mScale = mContext.getResources().getDisplayMetrics().density;
        return (int) (dpValue * mScale + 0.5f);
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        mCurrentPos = position;
        mIndecatorLayout.getChildAt(mPrePos % mUrls.size()).setEnabled(false);
        mIndecatorLayout.getChildAt(mCurrentPos % mUrls.size()).setEnabled(true);//设置true放后面,防止初始化时两个pos都为0时。没有默认选中
        mPrePos = mCurrentPos;
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        if (state == 0) {//用户手动滑动广告时,取消自动翻页响应
            mIsScrollingByUser = false;
        } else {
            //用户手动滑动中
            mIsScrollingByUser = true;
        }
    }

    /**
     * 轮播图ViewPager适配器
     */
    class MyAdapter extends PagerAdapter {
        List<String> addUrls;

        public MyAdapter(List<String> addUrls) {
            this.addUrls = addUrls;
        }

        @Override
        public int getCount() {
            if (addUrls.size() == 1){
                return addUrls.size();
            }else {
                return Integer.MAX_VALUE;
            }
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            ImageView imageView = new ImageView(mContext);
            String currentUrl = addUrls.get(position % addUrls.size());
            imageView.setScaleType(ImageView.ScaleType.FIT_XY);
            Glide.with(mContext).load(currentUrl).into(imageView);
            container.addView(imageView);
            return imageView;
        }

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

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

    }

    /**
     * 添加viewPager页面切换效果
     */
    class MyPageTransformer implements ViewPager.PageTransformer {

        @Override
        public void transformPage(View page, float position) {
            final float normalizedposition = Math.abs(Math.abs(position) - 1);
            page.setAlpha(normalizedposition);
        }
    }




}
原创文章 10 获赞 29 访问量 2万+

猜你喜欢

转载自blog.csdn.net/taoyuxin1314/article/details/81586675