一.自定义Banner无限轮播图式样

1.效果图:(一屏三页自定义,用RecyclerView实现无限轮播图,有普通版和3d版,包括上下滑动效果)

图一:

Android 列表左右轮播 android banner轮播图_Android 列表左右轮播

图二: 

Android 列表左右轮播 android banner轮播图_自定义_02

 

图三: 

 

Android 列表左右轮播 android banner轮播图_自定义_03

支持自定义圆形、圆角矩形、椭圆形等指示器(支持所有shape标签的形状显示)

支持无限轮播

支持轮播图点击事件

支持快速活动

支持上下滑动

支持当前图片缩放比列等等

属性

属性名称 

方法

意义

类型

默认值

app:showIndicator

setShowIndicator(boolean showIndicator)

是否显示指示器

boolean

true

app:interval

setAutoPlayDuration(int autoPlayDuration)

轮播时间间隔

int

4000

app:isAutoPlaying

setAutoPlaying(boolean isAutoPlaying)

是否开启自动轮播

boolean

true

app:orientation

setOrientation(int orientation)

轮播图方向

enum

horizontal

app:itemSpace

setItemSpace(int itemSpace)

图片间距

int

20

app:centerScale

setCenterScale(float centerScale)

当前图片缩放比列

float

1.2

app:moveSpeed

setMoveSpeed(float moveSpeed)

滚动速度,越大越快

float

1.0

2.主要函数代码:(JAVA)

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Toast;

import com.example.library.banner.BannerLayout;
import com.renny.recyclerbanner.adapter.WebBannerAdapter;

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

public class MainActivity extends AppCompatActivity implements BannerLayout.OnBannerItemClickListener {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        BannerLayout  recyclerBanner =  findViewById(R.id.recycler);
        BannerLayout bannerVertical =  findViewById(R.id.recycler_ver);

        List<String> list = new ArrayList<>();
        list.add("http://img0.imgtn.bdimg.com/it/u=1352823040,1166166164&fm=27&gp=0.jpg");
        list.add("http://img3.imgtn.bdimg.com/it/u=2293177440,3125900197&fm=27&gp=0.jpg");
        list.add("http://img3.imgtn.bdimg.com/it/u=3967183915,4078698000&fm=27&gp=0.jpg");
        list.add("http://img0.imgtn.bdimg.com/it/u=3184221534,2238244948&fm=27&gp=0.jpg");
        list.add("http://img4.imgtn.bdimg.com/it/u=1794621527,1964098559&fm=27&gp=0.jpg");
        list.add("http://img4.imgtn.bdimg.com/it/u=1243617734,335916716&fm=27&gp=0.jpg");
        WebBannerAdapter webBannerAdapter=new WebBannerAdapter(this,list);
        webBannerAdapter.setOnBannerItemClickListener(new BannerLayout.OnBannerItemClickListener() {
            @Override
            public void onItemClick(int position) {
                Toast.makeText(MainActivity.this, "点击了第  " + position+"  项", Toast.LENGTH_SHORT).show();
            }
        });

        WebBannerAdapter WebBannerAdapter2 =new WebBannerAdapter(this,list);
        WebBannerAdapter2.setOnBannerItemClickListener(new BannerLayout.OnBannerItemClickListener() {
            @Override
            public void onItemClick(int position) {
                Toast.makeText(MainActivity.this, "点击了第  " + position+"  项", Toast.LENGTH_SHORT).show();
            }
        });
        recyclerBanner.setAdapter(webBannerAdapter);
        bannerVertical.setAdapter(WebBannerAdapter2);
    }


    public void jump(View view) {
        startActivity(new Intent(MainActivity.this, NormalActivity.class));
    }
    public void jumpOverFlying(View view) {
        startActivity(new Intent(MainActivity.this, OverFlyingActivity.class));
    }

    @Override
    public void onItemClick(int position) {

    }
}

主要函数代码:(Kotlin)

val webBannerAdapter = WebBannerAdapter(mActivity,it);
            webBannerAdapter.setOnBannerItemClickListener(object :
                BannerLayout.OnBannerItemClickListener {

                override fun onItemClick(position: Int) {
                    Toast.makeText(mActivity ,"点击了第  " + position+"  项", Toast.LENGTH_SHORT).show();
                }
            });
            binding!!.banner.setAdapter(webBannerAdapter)

3.自定义Banner(图一的两个效果)

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.GravityCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.example.library.R;
import com.example.library.banner.layoutmanager.CenterSnapHelper;
import com.example.library.banner.layoutmanager.BannerLayoutManager;

import static android.view.Gravity.CENTER;
import static android.widget.AbsListView.OnScrollListener.SCROLL_STATE_IDLE;

public class BannerLayout extends FrameLayout {

    private int autoPlayDuration;//刷新间隔时间

    private boolean showIndicator;//是否显示指示器
    private RecyclerView indicatorContainer;
    private Drawable mSelectedDrawable;
    private Drawable mUnselectedDrawable;
    private IndicatorAdapter indicatorAdapter;
    private int indicatorMargin;//指示器间距
    private RecyclerView mRecyclerView;

    private BannerLayoutManager mLayoutManager;

    private int WHAT_AUTO_PLAY = 1000;

    private boolean hasInit;
    private int bannerSize = 1;
    private int currentIndex;
    private boolean isPlaying = false;

    private boolean isAutoPlaying = true;
    int itemSpace;
    float centerScale;
    float moveSpeed;
    protected Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == WHAT_AUTO_PLAY) {
                if (currentIndex == mLayoutManager.getCurrentPosition()) {
                    ++currentIndex;
                    mRecyclerView.smoothScrollToPosition(currentIndex);
                    mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
                    refreshIndicator();
                }
            }
            return false;
        }
    });

    public BannerLayout(Context context) {
        this(context, null);
    }

    public BannerLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BannerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs);
    }

    protected void initView(Context context, AttributeSet attrs) {

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BannerLayout);
        showIndicator = a.getBoolean(R.styleable.BannerLayout_showIndicator, true);
        autoPlayDuration = a.getInt(R.styleable.BannerLayout_interval, 4000);
        isAutoPlaying = a.getBoolean(R.styleable.BannerLayout_autoPlaying, true);
        itemSpace = a.getInt(R.styleable.BannerLayout_itemSpace, 20);
        centerScale = a.getFloat(R.styleable.BannerLayout_centerScale, 1.2f);
        moveSpeed = a.getFloat(R.styleable.BannerLayout_moveSpeed, 1.0f);
        if (mSelectedDrawable == null) {
            //绘制默认选中状态图形-- 自定义椭圆形指示器,圆角矩形
            GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg52);
//            drawable .setColor(Color.parseColor("#ff4400"));
            mSelectedDrawable = new LayerDrawable(new Drawable[]{drawable});

            //绘制默认选中状态图形 --  圆形
//            GradientDrawable selectedGradientDrawable = new GradientDrawable();
//            selectedGradientDrawable.setShape(GradientDrawable.OVAL);
//            selectedGradientDrawable.setColor(Color.RED);
//            selectedGradientDrawable.setSize(dp2px(5), dp2px(5));
//            selectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
//            mSelectedDrawable = new LayerDrawable(new Drawable[]{selectedGradientDrawable});
        }
        if (mUnselectedDrawable == null) {
            //绘制默认未选中状态图形 -- 自定义椭圆形指示器,圆角矩形
            GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg53);
//            drawable .setColor(Color.parseColor("#ff4400"));
            mUnselectedDrawable = new LayerDrawable(new Drawable[]{drawable});

            //绘制默认未选中状态图形 -- 圆形
//            GradientDrawable unSelectedGradientDrawable = new GradientDrawable();
//            unSelectedGradientDrawable.setShape(GradientDrawable.OVAL);
//            unSelectedGradientDrawable.setColor(Color.GRAY);
//            unSelectedGradientDrawable.setSize(dp2px(5), dp2px(5));
//            unSelectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
//            mUnselectedDrawable = new LayerDrawable(new Drawable[]{unSelectedGradientDrawable});
        }

        indicatorMargin = dp2px(4);
        int marginLeft = dp2px(16);
        int marginRight = dp2px(0);
        int marginBottom = dp2px(11);
        int gravity = GravityCompat.START;
        int o = a.getInt(R.styleable.BannerLayout_orientation, 0);
        int orientation = 0;
        if (o == 0) {
            orientation = OrientationHelper.HORIZONTAL;
        } else if (o == 1) {
            orientation = OrientationHelper.VERTICAL;
        }
        a.recycle();
        //轮播图部分
        mRecyclerView = new RecyclerView(context);
        LayoutParams vpLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        addView(mRecyclerView, vpLayoutParams);
        mLayoutManager = new BannerLayoutManager(getContext(), orientation);
        mLayoutManager.setItemSpace(itemSpace);
        mLayoutManager.setCenterScale(centerScale);
        mLayoutManager.setMoveSpeed(moveSpeed);
        mRecyclerView.setLayoutManager(mLayoutManager);
        new CenterSnapHelper().attachToRecyclerView(mRecyclerView);


        //指示器部分
        indicatorContainer = new RecyclerView(context);
        LinearLayoutManager indicatorLayoutManager = new LinearLayoutManager(context, orientation, false);
        indicatorContainer.setLayoutManager(indicatorLayoutManager);
        indicatorAdapter = new IndicatorAdapter();
        indicatorContainer.setAdapter(indicatorAdapter);
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
//        params.gravity = Gravity.BOTTOM | gravity;
        params.gravity = Gravity.BOTTOM | CENTER;;
//        params.setMargins(marginLeft, 0, marginRight, marginBottom);
        params.setMargins(0, 0, 0, 0);
        addView(indicatorContainer, params);
        if (!showIndicator) {
            indicatorContainer.setVisibility(GONE);
        }
    }

    // 设置是否禁止滚动播放
    public void setAutoPlaying(boolean isAutoPlaying) {
        this.isAutoPlaying = isAutoPlaying;
        setPlaying(this.isAutoPlaying);
    }

    public boolean isPlaying() {
        return isPlaying;
    }

    //设置是否显示指示器
    public void setShowIndicator(boolean showIndicator) {
        this.showIndicator = showIndicator;
        indicatorContainer.setVisibility(showIndicator ? VISIBLE : GONE);
    }

    //设置当前图片缩放系数
    public void setCenterScale(float centerScale) {
        this.centerScale = centerScale;
        mLayoutManager.setCenterScale(centerScale);
    }

    //设置跟随手指的移动速度
    public void setMoveSpeed(float moveSpeed) {
        this.moveSpeed = moveSpeed;
        mLayoutManager.setMoveSpeed(moveSpeed);
    }

    //设置图片间距
    public void setItemSpace(int itemSpace) {
        this.itemSpace = itemSpace;
        mLayoutManager.setItemSpace(itemSpace);
    }

    /**
     * 设置轮播间隔时间
     *
     * @param autoPlayDuration 时间毫秒
     */
    public void setAutoPlayDuration(int autoPlayDuration) {
        this.autoPlayDuration = autoPlayDuration;
    }

    public void setOrientation(int orientation) {
        mLayoutManager.setOrientation(orientation);
    }

    /**
     * 设置是否自动播放(上锁)
     *
     * @param playing 开始播放
     */
    protected synchronized void setPlaying(boolean playing) {
        if (isAutoPlaying && hasInit) {
            if (!isPlaying && playing) {
                mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
                isPlaying = true;
            } else if (isPlaying && !playing) {
                mHandler.removeMessages(WHAT_AUTO_PLAY);
                isPlaying = false;
            }
        }
    }


    /**
     * 设置轮播数据集
     */
    public void setAdapter(RecyclerView.Adapter adapter) {
        hasInit = false;
        mRecyclerView.setAdapter(adapter);
        bannerSize = adapter.getItemCount();
        mLayoutManager.setInfinite(bannerSize >= 3);
        setPlaying(true);
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if (dx != 0) {
                    setPlaying(false);
                }
            }

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                int first = mLayoutManager.getCurrentPosition();
                Log.d("xxx", "onScrollStateChanged");
                if (currentIndex != first) {
                    currentIndex = first;
                }
                if (newState == SCROLL_STATE_IDLE) {
                    setPlaying(true);
                }
                refreshIndicator();
            }
        });
        hasInit = true;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                setPlaying(false);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                setPlaying(true);
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        setPlaying(true);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        setPlaying(false);
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if (visibility == VISIBLE) {
            setPlaying(true);
        } else {
            setPlaying(false);
        }
    }

    /**
     * 标示点适配器
     */
    protected class IndicatorAdapter extends RecyclerView.Adapter {

        int currentPosition = 0;

        public void setPosition(int currentPosition) {
            this.currentPosition = currentPosition;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            ImageView bannerPoint = new ImageView(getContext());
            RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            lp.setMargins(indicatorMargin, indicatorMargin, indicatorMargin, indicatorMargin);
            bannerPoint.setLayoutParams(lp);
            return new RecyclerView.ViewHolder(bannerPoint) {
            };
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            ImageView bannerPoint = (ImageView) holder.itemView;
            bannerPoint.setImageDrawable(currentPosition == position ? mSelectedDrawable : mUnselectedDrawable);

        }

        @Override
        public int getItemCount() {
            return bannerSize;
        }
    }

    protected int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                Resources.getSystem().getDisplayMetrics());
    }

    /**
     * 改变导航的指示点
     */
    protected synchronized void refreshIndicator() {
        if (showIndicator && bannerSize > 1) {
            indicatorAdapter.setPosition(currentIndex % bannerSize);
            indicatorAdapter.notifyDataSetChanged();
        }
    }

    public interface OnBannerItemClickListener {
        void onItemClick(int position);
    }


}

图二的第二个效果:

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.GravityCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.example.library.R;
import com.example.library.banner.layoutmanager.BannerLayoutManager;
import com.example.library.banner.layoutmanager.CenterSnapHelper;

import static android.view.Gravity.CENTER;
import static android.widget.AbsListView.OnScrollListener.SCROLL_STATE_IDLE;

public class BannerLayout2 extends FrameLayout {

    private int autoPlayDuration;//刷新间隔时间

    private boolean showIndicator;//是否显示指示器
    private RecyclerView indicatorContainer;
    private Drawable mSelectedDrawable;
    private Drawable mUnselectedDrawable;
    private IndicatorAdapter indicatorAdapter;
    private int indicatorMargin;//指示器间距
    private RecyclerView mRecyclerView;

    private BannerLayoutManager mLayoutManager;

    private int WHAT_AUTO_PLAY = 1000;

    private boolean hasInit;
    private int bannerSize = 1;
    private int currentIndex;
    private boolean isPlaying = false;

    private boolean isAutoPlaying = true;
    int itemSpace;
    float centerScale;
    float moveSpeed;
    protected Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            if (msg.what == WHAT_AUTO_PLAY) {
                if (currentIndex == mLayoutManager.getCurrentPosition()) {
                    ++currentIndex;
                    mRecyclerView.smoothScrollToPosition(currentIndex);
                    mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
                    refreshIndicator();
                }
            }
            return false;
        }
    });

    public BannerLayout2(Context context) {
        this(context, null);
    }

    public BannerLayout2(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BannerLayout2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs);
    }

    protected void initView(Context context, AttributeSet attrs) {

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BannerLayout);
        showIndicator = a.getBoolean(R.styleable.BannerLayout_showIndicator, true);
        autoPlayDuration = a.getInt(R.styleable.BannerLayout_interval, 4000);
        isAutoPlaying = a.getBoolean(R.styleable.BannerLayout_autoPlaying, true);
        itemSpace = a.getInt(R.styleable.BannerLayout_itemSpace, 20);
        centerScale = a.getFloat(R.styleable.BannerLayout_centerScale, 1.2f);
        moveSpeed = a.getFloat(R.styleable.BannerLayout_moveSpeed, 1.0f);
        if (mSelectedDrawable == null) {
            //绘制默认选中状态图形-- 自定义椭圆形指示器,圆角矩形
            GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg521);
//            drawable .setColor(Color.parseColor("#ff4400"));
            mSelectedDrawable = new LayerDrawable(new Drawable[]{drawable});

            //绘制默认选中状态图形 --  圆形
//            GradientDrawable selectedGradientDrawable = new GradientDrawable();
//            selectedGradientDrawable.setShape(GradientDrawable.OVAL);
//            selectedGradientDrawable.setColor(Color.RED);
//            selectedGradientDrawable.setSize(dp2px(5), dp2px(5));
//            selectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
//            mSelectedDrawable = new LayerDrawable(new Drawable[]{selectedGradientDrawable});
        }
        if (mUnselectedDrawable == null) {
            //绘制默认未选中状态图形 -- 自定义椭圆形指示器,圆角矩形
            GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg522);
//            drawable .setColor(Color.parseColor("#ff4400"));
            mUnselectedDrawable = new LayerDrawable(new Drawable[]{drawable});

            //绘制默认未选中状态图形 -- 圆形
//            GradientDrawable unSelectedGradientDrawable = new GradientDrawable();
//            unSelectedGradientDrawable.setShape(GradientDrawable.OVAL);
//            unSelectedGradientDrawable.setColor(Color.GRAY);
//            unSelectedGradientDrawable.setSize(dp2px(5), dp2px(5));
//            unSelectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
//            mUnselectedDrawable = new LayerDrawable(new Drawable[]{unSelectedGradientDrawable});
        }
//        indicatorMargin = dp2px(4);
        indicatorMargin = (int) -0.2;
        int marginLeft = dp2px(16);
        int marginRight = dp2px(0);
        int marginBottom = dp2px(11);
        int gravity = GravityCompat.START;
        int o = a.getInt(R.styleable.BannerLayout_orientation, 0);
        int orientation = 0;
        if (o == 0) {
            orientation = OrientationHelper.HORIZONTAL;
        } else if (o == 1) {
            orientation = OrientationHelper.VERTICAL;
        }
        a.recycle();
        //轮播图部分
        mRecyclerView = new RecyclerView(context);
        LayoutParams vpLayoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        addView(mRecyclerView, vpLayoutParams);
        mLayoutManager = new BannerLayoutManager(getContext(), orientation);
        mLayoutManager.setItemSpace(itemSpace);
        mLayoutManager.setCenterScale(centerScale);
        mLayoutManager.setMoveSpeed(moveSpeed);
        mRecyclerView.setLayoutManager(mLayoutManager);
        new CenterSnapHelper().attachToRecyclerView(mRecyclerView);


        //指示器部分
        indicatorContainer = new RecyclerView(context);
        LinearLayoutManager indicatorLayoutManager = new LinearLayoutManager(context, orientation, false);
        indicatorContainer.setLayoutManager(indicatorLayoutManager);
        indicatorAdapter = new IndicatorAdapter();
        indicatorContainer.setAdapter(indicatorAdapter);
        LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
//        params.gravity = Gravity.BOTTOM | gravity;//指示器位置居左显示,可以设置上下左右的距离
//        params.gravity = Gravity.BOTTOM | RIGHT;//设置指示器居右显示
//        params.gravity = Gravity.BOTTOM | LEFT;//设置指示器居左显示
        params.gravity = Gravity.BOTTOM | CENTER;//设置指示器居中显示
//        params.setMargins(marginLeft, 0, marginRight, marginBottom);
        params.setMargins(0, 0, 0, marginBottom);
//        params.setMargins(0, 0, 0, 0);
        addView(indicatorContainer, params);
        if (!showIndicator) {
            indicatorContainer.setVisibility(GONE);
        }
    }

    // 设置是否禁止滚动播放
    public void setAutoPlaying(boolean isAutoPlaying) {
        this.isAutoPlaying = isAutoPlaying;
        setPlaying(this.isAutoPlaying);
    }

    public boolean isPlaying() {
        return isPlaying;
    }

    //设置是否显示指示器
    public void setShowIndicator(boolean showIndicator) {
        this.showIndicator = showIndicator;
        indicatorContainer.setVisibility(showIndicator ? VISIBLE : GONE);
    }

    //设置当前图片缩放系数
    public void setCenterScale(float centerScale) {
        this.centerScale = centerScale;
        mLayoutManager.setCenterScale(centerScale);
    }

    //设置跟随手指的移动速度
    public void setMoveSpeed(float moveSpeed) {
        this.moveSpeed = moveSpeed;
        mLayoutManager.setMoveSpeed(moveSpeed);
    }

    //设置图片间距
    public void setItemSpace(int itemSpace) {
        this.itemSpace = itemSpace;
        mLayoutManager.setItemSpace(itemSpace);
    }

    /**
     * 设置轮播间隔时间
     *
     * @param autoPlayDuration 时间毫秒
     */
    public void setAutoPlayDuration(int autoPlayDuration) {
        this.autoPlayDuration = autoPlayDuration;
    }

    public void setOrientation(int orientation) {
        mLayoutManager.setOrientation(orientation);
    }

    /**
     * 设置是否自动播放(上锁)
     *
     * @param playing 开始播放
     */
    protected synchronized void setPlaying(boolean playing) {
        if (isAutoPlaying && hasInit) {
            if (!isPlaying && playing) {
                mHandler.sendEmptyMessageDelayed(WHAT_AUTO_PLAY, autoPlayDuration);
                isPlaying = true;
            } else if (isPlaying && !playing) {
                mHandler.removeMessages(WHAT_AUTO_PLAY);
                isPlaying = false;
            }
        }
    }


    /**
     * 设置轮播数据集
     */
    public void setAdapter(RecyclerView.Adapter adapter) {
        hasInit = false;
        mRecyclerView.setAdapter(adapter);
        bannerSize = adapter.getItemCount();
        mLayoutManager.setInfinite(bannerSize >= 3);
        setPlaying(true);
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                if (dx != 0) {
                    setPlaying(false);
                }
            }

            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                int first = mLayoutManager.getCurrentPosition();
                Log.d("xxx", "onScrollStateChanged");
                if (currentIndex != first) {
                    currentIndex = first;
                }
                if (newState == SCROLL_STATE_IDLE) {
                    setPlaying(true);
                }
                refreshIndicator();
            }
        });
        hasInit = true;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                setPlaying(false);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                setPlaying(true);
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        setPlaying(true);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        setPlaying(false);
    }

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if (visibility == VISIBLE) {
            setPlaying(true);
        } else {
            setPlaying(false);
        }
    }

    /**
     * 标示点适配器
     */
    protected class IndicatorAdapter extends RecyclerView.Adapter {

        int currentPosition = 0;

        public void setPosition(int currentPosition) {
            this.currentPosition = currentPosition;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            ImageView bannerPoint = new ImageView(getContext());
            RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
//            lp.setMargins(indicatorMargin, indicatorMargin, indicatorMargin, indicatorMargin);
            lp.setMargins(0, 0, 0, 0);
            bannerPoint.setLayoutParams(lp);
            return new RecyclerView.ViewHolder(bannerPoint) {
            };
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            ImageView bannerPoint = (ImageView) holder.itemView;
            bannerPoint.setImageDrawable(currentPosition == position ? mSelectedDrawable : mUnselectedDrawable);

        }

        @Override
        public int getItemCount() {
            return bannerSize;
        }
    }

    protected int dp2px(int dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                Resources.getSystem().getDisplayMetrics());
    }

    /**
     * 改变导航的指示点
     */
    protected synchronized void refreshIndicator() {
        if (showIndicator && bannerSize > 1) {
            indicatorAdapter.setPosition(currentIndex % bannerSize);
            indicatorAdapter.notifyDataSetChanged();
        }
    }

    public interface OnBannerItemClickListener {
        void onItemClick(int position);
    }


}

 bg521.xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- 矩形圆角+左右两边为一个圆弧 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    android:useLevel="true">

    <size
        android:width="18dp"
        android:height="1.1dp" />

    <solid android:color="#ff00ff" />

    <!-- 圆角半径是高度的一般就是一个圆弧了 -->
    <corners android:radius="20dp" />

</shape>

图二的第二个效果的布局:

<com.example.library.banner.BannerLayout2
        android:id="@+id/recycler2"
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="130dp"
        app:autoPlaying="true"
        app:centerScale="1.3"
        app:itemSpace="20"
        app:moveSpeed="1.0"/>

 

4.布局及属性:

attr.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <attr name="interval" format="integer"/>
    <attr name="showIndicator" format="boolean"/>
    <attr name="orientation" format="enum">
        <enum name="horizontal" value="0"/>
        <enum name="vertical" value="1"/>
    </attr>
    <attr name="autoPlaying" format="boolean"/>
    <declare-styleable name="RecyclerViewBannerBase">
        <attr name="interval"/>
        <attr name="showIndicator" />
        <attr name="orientation" />
        <attr name="autoPlaying"/>
        <attr name="indicatorSelectedSrc" format="color|reference"/>
        <attr name="indicatorUnselectedSrc" format="color|reference"/>
        <attr name="indicatorSpace" format="dimension|reference"/>
        <attr name="indicatorMarginLeft" format="dimension|reference"/>
        <attr name="indicatorMarginRight" format="dimension|reference"/>
        <attr name="indicatorMarginBottom" format="dimension|reference"/>
        <attr name="indicatorGravity" format="enum">
            <enum name="left" value="0"/>
            <enum name="center" value="1"/>
            <enum name="right" value="2"/>
        </attr>
    </declare-styleable>

    <declare-styleable name="BannerLayout">
        <attr name="interval" />
        <attr name="showIndicator" />
        <attr name="orientation" />
        <attr name="autoPlaying"/>
        <attr name="itemSpace" format="integer"/>
        <attr name="centerScale" format="float"/>
        <attr name="moveSpeed" format="float"/>
    </declare-styleable>


</resources>

主布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.renny.recyclerbanner.MainActivity">

    <com.example.library.banner.BannerLayout
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        app:autoPlaying="true"
        app:centerScale="1.3"
        app:itemSpace="20"
        app:moveSpeed="1.8"/>

    <com.example.library.banner.BannerLayout
        android:id="@+id/recycler_ver"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:layout_marginTop="10dp"
        app:orientation="vertical"
        app:showIndicator="false"/>


    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        android:onClick="jump"
        android:text="查看基础版"/>

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        android:onClick="jumpOverFlying"
        android:text="查看层叠版"/>
</LinearLayout>

自定义默认的椭圆形背景xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- 矩形圆角+左右两边为一个圆弧 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    android:useLevel="true">

    <size
        android:width="8dp"
        android:height="3dp" />

    <solid android:color="#00ff00" />

    <!-- 圆角半径是高度的一般就是一个圆弧了 -->
    <corners android:radius="20dp" />

</shape>

自定义选中椭圆形背景xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- 矩形圆角+左右两边为一个圆弧 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    android:useLevel="true">

    <size
        android:width="8dp"
        android:height="3dp" />

    <solid android:color="#ff00ff" />

    <!-- 圆角半径是高度的一般就是一个圆弧了 -->
    <corners android:radius="20dp" />

</shape>

5.适配器:

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.example.library.banner.BannerLayout;
import com.renny.recyclerbanner.R;

import java.util.List;

/**
 * Created by test on 2017/11/22.
 */


public class WebBannerAdapter extends RecyclerView.Adapter<WebBannerAdapter.MzViewHolder> {

    private Context context;
    private List<String> urlList;
    private BannerLayout.OnBannerItemClickListener onBannerItemClickListener;

    public WebBannerAdapter(Context context, List<String> urlList) {
        this.context = context;
        this.urlList = urlList;
    }

    public void setOnBannerItemClickListener(BannerLayout.OnBannerItemClickListener onBannerItemClickListener) {
        this.onBannerItemClickListener = onBannerItemClickListener;
    }

    @Override
    public WebBannerAdapter.MzViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MzViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, parent, false));
    }

    @Override
    public void onBindViewHolder(WebBannerAdapter.MzViewHolder holder, final int position) {
        if (urlList == null || urlList.isEmpty())
            return;
        final int P = position % urlList.size();
        String url = urlList.get(P);
        ImageView img = (ImageView) holder.imageView;
        Glide.with(context).load(url).into(img);
        img.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (onBannerItemClickListener != null) {
                    onBannerItemClickListener.onItemClick(P);
                }

            }
        });
    }

    @Override
    public int getItemCount() {
        if (urlList != null) {
           return urlList.size();
        }
       return 0;
    }


    class MzViewHolder extends RecyclerView.ViewHolder {
        ImageView imageView;

        MzViewHolder(View itemView) {
            super(itemView);
            imageView = (ImageView) itemView.findViewById(R.id.image);
        }
    }

}

 适配器布局:(使用CardView来实现轮播图图片圆角效果,注意适配器布局的高度和banner布局的高度是否贴合)

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="250dp"
    android:layout_height="100dp"
    app:cardCornerRadius="5dp">
    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"/>
</android.support.v7.widget.CardView>

 6.注意:

若需要设置自定义的指示器圆形、圆角矩形、椭圆形等可以在自定义的Banner中设置,代码已经添加了注释,其中包括设置指示器的位置居左、居中、居右等等。

//绘制默认选中状态图形-- 自定义椭圆形指示器,圆角矩形
            GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg52);
//            drawable .setColor(Color.parseColor("#ff4400"));
            mSelectedDrawable = new LayerDrawable(new Drawable[]{drawable});

            //绘制默认选中状态图形 --  圆形
//            GradientDrawable selectedGradientDrawable = new GradientDrawable();
//            selectedGradientDrawable.setShape(GradientDrawable.OVAL);
//            selectedGradientDrawable.setColor(Color.RED);
//            selectedGradientDrawable.setSize(dp2px(5), dp2px(5));
//            selectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
//            mSelectedDrawable = new LayerDrawable(new Drawable[]{selectedGradientDrawable});
//绘制默认未选中状态图形 -- 自定义椭圆形指示器,圆角矩形
            GradientDrawable drawable = (GradientDrawable) context.getResources().getDrawable(R.drawable.bg53);
//            drawable .setColor(Color.parseColor("#ff4400"));
            mUnselectedDrawable = new LayerDrawable(new Drawable[]{drawable});

            //绘制默认未选中状态图形 -- 圆形
//            GradientDrawable unSelectedGradientDrawable = new GradientDrawable();
//            unSelectedGradientDrawable.setShape(GradientDrawable.OVAL);
//            unSelectedGradientDrawable.setColor(Color.GRAY);
//            unSelectedGradientDrawable.setSize(dp2px(5), dp2px(5));
//            unSelectedGradientDrawable.setCornerRadius(dp2px(5) / 2);
//            mUnselectedDrawable = new LayerDrawable(new Drawable[]{unSelectedGradientDrawable});

 

LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
//        params.gravity = Gravity.BOTTOM | gravity;
        params.gravity = Gravity.BOTTOM | CENTER;//设置指示器据中显示
//        params.setMargins(marginLeft, 0, marginRight, marginBottom);
        params.setMargins(0, 0, 0, 0);
        addView(indicatorContainer, params);
indicatorMargin = dp2px(4);
        int marginLeft = dp2px(16);
        int marginRight = dp2px(0);
        int marginBottom = dp2px(11);
        int gravity = GravityCompat.START;
        ...
           LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        params.gravity = Gravity.BOTTOM | gravity;//指示器位置居左显示,可以设置上下左右的距离
//        params.gravity = Gravity.BOTTOM | RIGHT;//设置指示器居右显示
//        params.gravity = Gravity.BOTTOM | LEFT;//设置指示器居左显示
//        params.gravity = Gravity.BOTTOM | CENTER;//设置指示器居中显示
        params.setMargins(marginLeft, 0, marginRight, marginBottom);
//        params.setMargins(0, 0, 0, 0);
        addView(indicatorContainer, params);