美文网首页
自定义轮播图-简单不需要引用第三方库

自定义轮播图-简单不需要引用第三方库

作者: suniney | 来源:发表于2018-10-18 15:48 被阅读10次

    简单的轮播图,实现自定义轮播icon,带标题,自动轮播,无限轮播

    S81018-154428_看图王.jpg
    S81018-154436_看图王.jpg

    1、自定义属性attr.xml

        <declare-styleable name="BannerView">
            <!-- 是否支持循环, 默认 true -->
            <attr name="bvIsLoop" format="boolean"/>
            <!-- 是否支持自动滚动, 默认 true -->
            <attr name="bvIsAuto" format="boolean"/>
            <!-- 滚动延时, 默认5000ms -->
            <attr name="bvDelay" format="integer"/>
            <!-- 滚动间隔, 默认5000ms -->
            <attr name="bvInterval" format="integer"/>
            <!-- 高宽比(height/width)-->
            <attr name="bvAspectRatio" format="float"/>
            <!-- 底部背景条颜色, 默认透明 -->
            <attr name="bvBarColor" format="color"/>
            <!-- 底部背景条在滚动到最后一个item时是否可见, 默认 true -->
            <attr name="bvBarVisibleWhenLast" format="boolean"/>
            <!-- 底部背景条padding, 默认10dp -->
            <attr name="bvBarPaddingLeft" format="dimension"/>
            <attr name="bvBarPaddingTop" format="dimension"/>
            <attr name="bvBarPaddingRight" format="dimension"/>
            <attr name="bvBarPaddingBottom" format="dimension"/>
            <!-- 标题文字颜色, 默认 #ffffff -->
            <attr name="bvTitleColor" format="color"/>
            <!-- 标题文字大小, 默认 14sp -->
            <attr name="bvTitleSize" format="dimension"/>
            <!-- 标题是否可见, 默认 false  -->
            <attr name="bvTitleVisible" format="boolean"/>
            <!-- 指示器是否可见, 默认 auto  -->
            <attr name="bvIndicatorVisible" format="integer">
                <enum name="auto" value="0"/>
                <enum name="always" value="1"/>
                <enum name="never" value="2"/>
            </attr>
            <!-- 指示器位置, 默认 center-->
            <attr name="bvIndicatorGravity">
                <enum name="center" value="17"/>
                <enum name="left" value="3"/>
                <enum name="right" value="5"/>
            </attr>
            <!-- 指示器项的 宽度/高度/间距, 默认 6dp -->
            <attr name="bvIndicatorWidth" format="dimension"/>
            <attr name="bvIndicatorHeight" format="dimension"/>
            <attr name="bvIndicatorSelectedWidth" format="dimension"/>
            <attr name="bvIndicatorSelectedHeight" format="dimension"/>
            <attr name="bvIndicatorGap" format="dimension"/>
            <!-- 指示器未选中颜色, 默认 #88ffffff  -->
            <attr name="bvIndicatorColor" format="color"/>
            <!-- 指示器选中颜色, 默认 #ffffff -->
            <attr name="bvIndicatorColorSelected" format="color"/>
            <!-- 指示器未选中drawable资源 -->
            <attr name="bvIndicatorDrawable" format="reference"/>
            <!-- 指示器选中drawable资源 -->
            <attr name="bvIndicatorDrawableSelected" format="reference"/>
        </declare-styleable>
    

    2、自定义BannerView

    public class BannerView<Item> extends FrameLayout {
        public static boolean DEBUG = false;
        private static final String TAG = BannerView.class.getSimpleName();
    
        public interface ViewFactory<Item> {
            View create(Item item, int position, ViewGroup container);
        }
    
        public interface TitleAdapter<Item> {
            CharSequence getTitle(Item item);
        }
    
        public static final int VISIBLE_AUTO = 0;
        public static final int VISIBLE_ALWAYS = 1;
        public static final int VISIBLE_NEVER = 2;
    
        // 设备密度
        private DisplayMetrics mDm;
    
        private long mDelay;        // 多久后开始滚动
        private long mInterval;     // 滚动间隔
        private boolean mIsAuto;    // 是否自动滚动
        private boolean mBarVisibleWhenLast;    // 最后一条 item 是否显示背景条
        private int mCurrentPosition;
    
        private boolean mIsStarted = false;
        private boolean mIsVisible = false;
        private boolean mIsResumed = true;
        private boolean mIsRunning = false;
        private final Runnable mRunnable = new Runnable() {
            @Override
            public void run() {
                if (DEBUG) {
                    Log.e("yanxu", "running=" + mIsRunning + ",pos=" + mCurrentPosition);
                }
                if (mIsRunning) {
                    vViewPager.setCurrentItem(mCurrentPosition + 1);
                    if (isLoop() || mCurrentPosition + 1 < mDataList.size()) {
                        postDelayed(mRunnable, mInterval);
                    } else {
                        mIsRunning = false;
                    }
                }
            }
        };
    
        // 内容宽高
        private int mItemWidth;
        private int mItemHeight = LayoutParams.WRAP_CONTENT;
    
        private ViewPager vViewPager;
        private LinearLayout vBottomBar;
        private TextView vTitleBar;
        private ViewPagerIndicator vIndicator;
    
        private int mIndicatorVisible;
    
        private List<Item> mDataList = new ArrayList();
        private ViewPager.OnPageChangeListener mOnPageChangeListener;
        private ViewFactory mViewFactory;
        private TitleAdapter mTitleAdapter = new TitleAdapter() {
            @Override
            public CharSequence getTitle(Object o) {
                return o.toString();
            }
        };
    
        public BannerView(Context context) {
            this(context, null, 0);
        }
    
        public BannerView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        @SuppressWarnings("all")
        public BannerView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            mDm = context.getResources().getDisplayMetrics();
    
            TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.BannerView);
    
            boolean hasAspectRatio = ta.hasValue(R.styleable.BannerView_bvAspectRatio);
            float aspectRatio = ta.getFloat(R.styleable.BannerView_bvAspectRatio, 0f);
            boolean isLoop = ta.getBoolean(R.styleable.BannerView_bvIsLoop, true);
            mDelay = ta.getInt(R.styleable.BannerView_bvDelay, 5000);
            mInterval = ta.getInt(R.styleable.BannerView_bvInterval, 5000);
            mIsAuto = ta.getBoolean(R.styleable.BannerView_bvIsAuto, true);
    
            mBarVisibleWhenLast = ta.getBoolean(R.styleable.BannerView_bvBarVisibleWhenLast, true);
    
            int indicatorGravity = ta.getInt(R.styleable.BannerView_bvIndicatorGravity, Gravity.CENTER);
            int barColor = ta.getColor(R.styleable.BannerView_bvBarColor, Color.TRANSPARENT);
            float barPaddingLeft = ta.getDimension(R.styleable.BannerView_bvBarPaddingLeft, dp2px(10));
            float barPaddingTop = ta.getDimension(R.styleable.BannerView_bvBarPaddingTop, dp2px(10));
            float barPaddingRight = ta.getDimension(R.styleable.BannerView_bvBarPaddingRight, dp2px(10));
            float barPaddingBottom = ta.getDimension(R.styleable.BannerView_bvBarPaddingBottom, dp2px(10));
    
            int titleColor = ta.getColor(R.styleable.BannerView_bvTitleColor, Color.WHITE);
            float titleSize = ta.getDimension(R.styleable.BannerView_bvTitleSize, sp2px(14f));
            boolean titleVisible = ta.getBoolean(R.styleable.BannerView_bvTitleVisible, false);
    
            // auto, aways, never
            mIndicatorVisible = ta.getInteger(R.styleable.BannerView_bvIndicatorVisible, VISIBLE_AUTO);
            Drawable indicatorDrawable = ta.getDrawable(R.styleable.BannerView_bvIndicatorDrawable);
            Drawable indicatorDrawableSelected = ta.getDrawable(R.styleable.BannerView_bvIndicatorDrawableSelected);
    
            int indicatorWidth = ta.getDimensionPixelSize(R.styleable.BannerView_bvIndicatorWidth, indicatorDrawable.getIntrinsicWidth());
            int indicatorHeight = ta.getDimensionPixelSize(R.styleable.BannerView_bvIndicatorHeight, indicatorDrawable.getIntrinsicHeight());
            int indicatorSelectedWidth = ta.getDimensionPixelSize(R.styleable.BannerView_bvIndicatorSelectedWidth, indicatorDrawableSelected.getIntrinsicWidth());
            int indicatorSelectedHeight = ta.getDimensionPixelSize(R.styleable.BannerView_bvIndicatorSelectedHeight, indicatorDrawableSelected.getIntrinsicHeight());
            int indicatorGap = ta.getDimensionPixelSize(R.styleable.BannerView_bvIndicatorGap, dp2px(0));
            int indicatorColor = ta.getColor(R.styleable.BannerView_bvIndicatorColor, 0x88ffffff);
            int indicatorColorSelected = ta.getColor(R.styleable.BannerView_bvIndicatorColorSelected, Color.WHITE);
    
            ta.recycle();
    
    
            //create ViewPager
            vViewPager = isLoop ? new LoopViewPager(context) : new ViewPager(context);
            vViewPager.setOffscreenPageLimit(1);
    
            int[] systemAttrs = {android.R.attr.layout_width, android.R.attr.layout_height};
            TypedArray a = context.obtainStyledAttributes(attrs, systemAttrs);
            mItemWidth = a.getLayoutDimension(0, mDm.widthPixels);
            mItemHeight = a.getLayoutDimension(1, mItemHeight);
            a.recycle();
    
            if (mItemWidth < 0) {
                mItemWidth = mDm.widthPixels;
            }
    
            if (aspectRatio > 0) {
                if (aspectRatio > 1) {
                    aspectRatio = 1;
                }
                mItemHeight = (int) (mItemWidth * aspectRatio);
            }
    
            Log.e(TAG, "w = " + mItemWidth + ", h = " + mItemHeight);
            LayoutParams lp = new LayoutParams(mItemWidth, mItemHeight);
            addView(vViewPager, lp);
    
            // bottom bar
            vBottomBar = new LinearLayout(context);
            vBottomBar.setBackgroundColor(barColor);
            vBottomBar.setPadding((int) barPaddingLeft, (int) barPaddingTop, (int) barPaddingRight, (int) barPaddingBottom);
            vBottomBar.setClipChildren(false);
            vBottomBar.setClipToPadding(false);
            vBottomBar.setOrientation(LinearLayout.VERTICAL);
            vBottomBar.setGravity(Gravity.CENTER);
            addView(vBottomBar, new LayoutParams(mItemWidth, LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));
    
            vIndicator = new ViewPagerIndicator(context);
            vIndicator.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
            vIndicator.setItemSize(indicatorWidth, indicatorHeight);
            vIndicator.setItemSelectedSize(indicatorSelectedWidth, indicatorSelectedHeight);
            vIndicator.setItemGap(indicatorGap);
    
            if (indicatorDrawable != null && indicatorDrawableSelected != null) {
                vIndicator.setItemDrawable(indicatorDrawable, indicatorDrawableSelected);
            } else {
                vIndicator.setItemColor(indicatorColor, indicatorColorSelected);
            }
    
            // title
            vTitleBar = new TextView(context);
            vTitleBar.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
            vTitleBar.setSingleLine(true);
            vTitleBar.setTextColor(titleColor);
            vTitleBar.setTextSize(TypedValue.COMPLEX_UNIT_PX, titleSize);
            vTitleBar.setEllipsize(TextUtils.TruncateAt.END);
            vTitleBar.setVisibility(titleVisible ? VISIBLE : INVISIBLE);
    
            if (indicatorGravity == Gravity.CENTER) {
                vBottomBar.addView(vTitleBar);
                vBottomBar.addView(vIndicator);
                vTitleBar.setPadding(0, 0, 0, dp2px(10));
                vTitleBar.setGravity(Gravity.CENTER);
            } else if (indicatorGravity == Gravity.RIGHT) {
                vBottomBar.addView(vTitleBar);
                vBottomBar.addView(vIndicator);
                vTitleBar.setPadding(0, 0, dp2px(10), 0);
                vTitleBar.setGravity(Gravity.LEFT);
            } else if (indicatorGravity == Gravity.LEFT) {
                vBottomBar.addView(vIndicator);
                vBottomBar.addView(vTitleBar);
                vTitleBar.setPadding(dp2px(10), 0, 0, 0);
                vTitleBar.setGravity(Gravity.RIGHT);
            }
    
    
        }
    
        public void setDelay(long delay) {
            this.mDelay = delay;
        }
    
        public void setInterval(long interval) {
            this.mInterval = interval;
        }
    
        public void setIsAuto(boolean isAuto) {
            this.mIsAuto = isAuto;
        }
    
        public void setIndicatorVisible(int value) {
            mIndicatorVisible = value;
        }
    
        public void setBarVisibleWhenLast(boolean value) {
            this.mBarVisibleWhenLast = value;
        }
    
        public void setBarColor(int barColor) {
            vBottomBar.setBackgroundColor(barColor);
        }
    
        public void setBarPadding(float left, float top, float right, float bottom) {
            vBottomBar.setPadding(dp2px(left), dp2px(top), dp2px(right), dp2px(bottom));
        }
    
        public void setTitleColor(int textColor) {
            vTitleBar.setTextColor(textColor);
        }
    
        public void setTitleSize(float sp) {
            vTitleBar.setTextSize(TypedValue.COMPLEX_UNIT_SP, sp);
        }
    
        public void setTitleVisible(boolean isTitleVisible) {
            vTitleBar.setVisibility(isTitleVisible ? VISIBLE : INVISIBLE);
        }
    
    
        public boolean isLoop() {
            return vViewPager instanceof LoopViewPager;
        }
    
        public ViewPager getViewPager() {
            return vViewPager;
        }
    
        public ViewPagerIndicator getIndicator() {
            return vIndicator;
        }
    
        public void setViewFactory(@NonNull ViewFactory factory) {
            mViewFactory = factory;
        }
    
        public void setTitleAdapter(@NonNull TitleAdapter adapter) {
            mTitleAdapter = adapter;
        }
    
        public void setDataList(@NonNull List<Item> list) {
            mDataList = list;
        }
    
        public void setOnPageChangeListener(@NonNull ViewPager.OnPageChangeListener listener) {
            mOnPageChangeListener = listener;
        }
    
    
        void initViewPager() {
            vViewPager.setAdapter(mInternalPagerAdapter);
            vViewPager.removeOnPageChangeListener(mInternalPageListener);
            vViewPager.addOnPageChangeListener(mInternalPageListener);
            vViewPager.setOffscreenPageLimit(mDataList.size());
            mInternalPagerAdapter.notifyDataSetChanged();
            try {
                if (isLoop()) {
                    setDuration(vViewPager, 500);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        void initIndicator() {
            vIndicator.setupWithViewPager(vViewPager);
            boolean visible = mIndicatorVisible == VISIBLE_ALWAYS || (mIndicatorVisible == VISIBLE_AUTO && mDataList.size() > 1);
            vIndicator.setVisibility(visible ? VISIBLE : INVISIBLE);
            vIndicator.setPosition(mCurrentPosition);
        }
    
        void setCurrentTitle(int position) {
            vTitleBar.setText(mTitleAdapter.getTitle(mDataList.get(position)));
        }
    
    
        boolean isValid() {
            if (vViewPager == null) {
                Log.e(TAG, "ViewPager is not exist!");
                return false;
            }
            if (mViewFactory == null) {
                Log.e(TAG, "ViewFactory must be not null!");
                return false;
            }
            if (mTitleAdapter == null) {
                Log.e(TAG, "TitleAdapter must be not null!");
                return false;
            }
            if (mDataList == null || mDataList.size() == 0) {
                Log.e(TAG, "DataList must be not empty!");
                return false;
            }
            return true;
        }
    
        public void start() {
            if (!isValid()) {
                return;
            }
    
            if (mCurrentPosition > mDataList.size() - 1) {
                mCurrentPosition = 0;
            }
            initViewPager();
            initIndicator();
    
            setCurrentTitle(mCurrentPosition);
            mIsStarted = true;
            update();
        }
    
        void update() {
            if (!isValid()) {
                return;
            }
            boolean running = mIsVisible && mIsResumed && mIsStarted && mIsAuto && mDataList.size() > 1 && (isLoop() || mCurrentPosition + 1 < mDataList.size());
            if (running != mIsRunning) {
                if (running) {
                    postDelayed(mRunnable, mDelay);
                } else {
                    removeCallbacks(mRunnable);
                }
                mIsRunning = running;
            }
            if (DEBUG) {
                Log.e("ezy", "update:running=" + mIsRunning + ",visible=" + mIsVisible + ",started=" + mIsStarted + ",resumed=" + mIsResumed);
                Log.e("ezy", "update:auto=" + mIsAuto + ",loop=" + isLoop() + ",size=" + mDataList.size() + ",current=" + mCurrentPosition);
            }
        }
    
        @Override
        protected void onDetachedFromWindow() {
            super.onDetachedFromWindow();
            mIsVisible = false;
            update();
        }
    
        @Override
        protected void onWindowVisibilityChanged(int visibility) {
            super.onWindowVisibilityChanged(visibility);
            mIsVisible = visibility == VISIBLE;
            update();
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            int action = ev.getAction();
            switch (action) {
                case MotionEvent.ACTION_DOWN:
                    mIsResumed = false;
                    update();
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    mIsResumed = true;
                    update();
                    break;
            }
            return super.dispatchTouchEvent(ev);
        }
    
        private int dp2px(float dp) {
            return (int) (dp * mDm.density + 0.5f);
        }
    
        private float sp2px(float sp) {
            return sp * mDm.scaledDensity;
        }
    
        private ViewPager.OnPageChangeListener mInternalPageListener = new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (mOnPageChangeListener != null) {
                    mOnPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
                }
            }
    
            @Override
            public void onPageSelected(int position) {
    
                if (DEBUG) {
                    Log.e("ezy", "onPageSelected, pos=" + mCurrentPosition);
                }
                mCurrentPosition = position % mDataList.size();
                setCurrentTitle(mCurrentPosition);
                vBottomBar.setVisibility(mCurrentPosition == mDataList.size() - 1 && !mBarVisibleWhenLast ? GONE : VISIBLE);
    
                if (mOnPageChangeListener != null) {
                    mOnPageChangeListener.onPageSelected(position);
                }
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
                if (mOnPageChangeListener != null) {
                    mOnPageChangeListener.onPageScrollStateChanged(state);
                }
            }
        };
    
        private PagerAdapter mInternalPagerAdapter = new PagerAdapter() {
            @Override
            public int getCount() {
                return mDataList.size();
            }
    
            @Override
            public Object instantiateItem(ViewGroup container, final int position) {
                View inflate = mViewFactory.create(mDataList.get(position), position, container);
                container.addView(inflate);
                return inflate;
            }
    
            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                container.removeView((View) object);
            }
    
            @Override
            public boolean isViewFromObject(View view, Object object) {
                return view == object;
            }
    
            public int getItemPosition(Object object) {
                return POSITION_NONE;
            }
        };
    
        private static void setDuration(ViewPager pager, int duration) {
            try {
                FixedSpeedScroller scroller = new FixedSpeedScroller(pager.getContext(), new AccelerateDecelerateInterpolator(), duration);
                Field field = ViewPager.class.getDeclaredField("mScroller");
                field.setAccessible(true);
                field.set(pager, scroller);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        private static class FixedSpeedScroller extends Scroller {
            private int mDuration = 450;
    
            public FixedSpeedScroller(Context context) {
                super(context);
            }
    
            public FixedSpeedScroller(Context context, Interpolator interpolator, int duration) {
                super(context, interpolator);
                this.mDuration = duration;
            }
    
            @Override
            public void startScroll(int startX, int startY, int dx, int dy, int duration) {
                super.startScroll(startX, startY, dx, dy, this.mDuration);
            }
        }
    }
    

    3、自定义指示器

    public class ViewPagerIndicator extends View {
    
        private float mPositionOffset = 0;
        private int mPosition;
    
        private int mItemCount;
        private int mItemWidth;
        private int mItemHeight;
        private int mItemSelectedWidth;
        private int mItemSelectedHeight;
        private int mItemGap;
    
        private Drawable mItemDrawable;
        private Drawable mItemDrawableSelected;
    
    
        public ViewPagerIndicator(Context context) {
            super(context);
            init(context, null);
        }
    
        public ViewPagerIndicator(Context context, AttributeSet attrs) {
            super(context, attrs);
            init(context, attrs);
        }
    
        public ViewPagerIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            init(context, attrs);
        }
    
        private void init(Context context, AttributeSet attrs) {
        }
    
        int mWidth = 0;
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            if (mItemCount > 1) {
                mWidth = (mItemSelectedWidth - mItemWidth + mItemGap) * mItemCount - mItemGap + mItemWidth;
            } else if (mItemCount == 1) {
                mWidth = mItemWidth;
            } else {
                mWidth = 0;
            }
            setMeasuredDimension(mWidth, mItemHeight);
        }
    
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int flags = Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas
                    .CLIP_TO_LAYER_SAVE_FLAG;
            int sc = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, flags);
    
            int wg = mItemSelectedWidth - mItemWidth + mItemGap;
            int x = (getWidth() - mWidth) / 2;
            int y = (getHeight() - mItemHeight) / 2;
    
            mItemDrawable.setBounds(0, 0, mItemWidth, mItemHeight);
            mItemDrawableSelected.setBounds(0, 0, mItemSelectedWidth, mItemSelectedHeight);
    
            for (int i = 0; i < mItemCount; i++) {
                canvas.save();
                canvas.translate(x + i * wg, y);
                mItemDrawable.draw(canvas);
                canvas.restore();
            }
    
            canvas.save();
            canvas.translate(x + (mPosition + mPositionOffset) * wg, y);
            mItemDrawableSelected.draw(canvas);
            canvas.restore();
    
            canvas.restoreToCount(sc);
        }
    
        public void setupWithViewPager(ViewPager pager) {
            mItemCount = pager.getAdapter().getCount();
            pager.removeOnPageChangeListener(onPageChangeListener);
            pager.addOnPageChangeListener(onPageChangeListener);
            requestLayout();
        }
    
        public void setPosition(int position) {
            mPosition = position;
            invalidate();
        }
    
    
        public ViewPagerIndicator setItemSize(int width, int height) {
            this.mItemWidth = width;
            this.mItemHeight = height;
            return this;
        }
    
        public ViewPagerIndicator setItemSelectedSize(int width, int height) {
            this.mItemSelectedWidth = width;
            this.mItemSelectedHeight = height;
            return this;
        }
    
        public ViewPagerIndicator setItemGap(int gap) {
            this.mItemGap = gap;
            return this;
        }
    
        public ViewPagerIndicator setItemColor(@ColorInt int color, @ColorInt int selected) {
            this.mItemDrawable = genDrawable(color);
            this.mItemDrawableSelected = genDrawable(selected);
            return this;
        }
    
        public ViewPagerIndicator setItemDrawable(@NonNull Drawable normal, @NonNull Drawable selected) {
            this.mItemDrawable = normal;
            this.mItemDrawableSelected = selected;
            return this;
        }
    
        Drawable genDrawable(int color) {
            ShapeDrawable drawable = new ShapeDrawable(new OvalShape());
            drawable.getPaint().setColor(color);
            drawable.getPaint().setAntiAlias(true);
            return drawable;
        }
    
        ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                mPosition = position;
                mPositionOffset = positionOffset;
                invalidate();
            }
    
            @Override
            public void onPageSelected(int position) {
                mPosition = position;
                mPositionOffset = 0;
                invalidate();
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
    
            }
        };
    }
    

    4、轮播的viewpager

    public class LoopViewPager extends ViewPager {
    
        private InnerLoopAdapter mAdapter;
    
        static int toRealPosition(int position, int count) {
            if (count <= 1) {
                return 0;
            }
            return (position - 1 + count) % count;
        }
    
        static int toInnerPosition(int real) {
            return real + 1;
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
            int count = getChildCount();
    
            if (count > 0) {
                int width = MeasureSpec.getSize(widthMeasureSpec);
                int height = MeasureSpec.getSize(heightMeasureSpec);
                View child = getChildAt(0);
                child.measure(widthMeasureSpec, heightMeasureSpec);
    
                if (width == ViewGroup.LayoutParams.WRAP_CONTENT || width == 0) {
                    widthMeasureSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), MeasureSpec.EXACTLY);
                }
                if (height == ViewGroup.LayoutParams.WRAP_CONTENT || height == 0) {
                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY);
                }
            }
    
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
        @Override
        public void setAdapter(PagerAdapter adapter) {
            mAdapter = adapter == null ? null : new InnerLoopAdapter(adapter);
            super.setAdapter(mAdapter);
            setCurrentItem(0, false);
        }
    
        @Override
        public PagerAdapter getAdapter() {
            return mAdapter != null ? mAdapter.pa : null;
        }
    
        @Override
        public int getCurrentItem() {
            return mAdapter != null ? mAdapter.getRealPosition(super.getCurrentItem()) : 0;
        }
    
        @Override
        public void setCurrentItem(int item, boolean smoothScroll) {
            super.setCurrentItem(toInnerPosition(item), smoothScroll);
        }
    
        @Override
        public void setCurrentItem(int item) {
            super.setCurrentItem(toInnerPosition(item), true);
        }
    
        @Override
        public void setOnPageChangeListener(OnPageChangeListener listener) {
            removeOnPageChangeListener(listener);
            addOnPageChangeListener(listener);
        }
    
        List<OnPageChangeListener> mOnPageChangeListeners;
        @Override
        public void addOnPageChangeListener(OnPageChangeListener listener) {
            if (mOnPageChangeListeners == null) {
                mOnPageChangeListeners = new ArrayList<>();
            }
            mOnPageChangeListeners.add(listener);
        }
        @Override
        public void removeOnPageChangeListener(OnPageChangeListener listener) {
            if (mOnPageChangeListeners != null) {
                mOnPageChangeListeners.remove(listener);
            }
        }
        @Override
        public void clearOnPageChangeListeners() {
            if (mOnPageChangeListeners != null) {
                mOnPageChangeListeners.clear();
            }
        }
    
        private void dispatchOnPageScrolled(int position, float offset, int offsetPixels) {
            if (mOnPageChangeListeners != null) {
                for (int i = 0, z = mOnPageChangeListeners.size(); i < z; i++) {
                    OnPageChangeListener listener = mOnPageChangeListeners.get(i);
                    if (listener != null) {
                        listener.onPageScrolled(position, offset, offsetPixels);
                    }
                }
            }
        }
    
        private void dispatchOnPageSelected(int position) {
            if (mOnPageChangeListeners != null) {
                for (int i = 0, z = mOnPageChangeListeners.size(); i < z; i++) {
                    OnPageChangeListener listener = mOnPageChangeListeners.get(i);
                    if (listener != null) {
                        listener.onPageSelected(position);
                    }
                }
            }
        }
    
        private void dispatchOnScrollStateChanged(int state) {
            if (mOnPageChangeListeners != null) {
                for (int i = 0, z = mOnPageChangeListeners.size(); i < z; i++) {
                    OnPageChangeListener listener = mOnPageChangeListeners.get(i);
                    if (listener != null) {
                        listener.onPageScrollStateChanged(state);
                    }
                }
            }
        }
    
        public LoopViewPager(Context context) {
            this(context, null);
        }
    
        public LoopViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
            super.addOnPageChangeListener(mInnerListener);
        }
    
        private OnPageChangeListener mInnerListener = new OnPageChangeListener() {
            private float mPreviousOffset = -1;
            private float mPreviousPosition = -1;
    
            @Override
            public void onPageSelected(int position) {
    
                int real = mAdapter.getRealPosition(position);
                if (mPreviousPosition == real) {
                    return;
                }
                mPreviousPosition = real;
    
                dispatchOnPageSelected(real);
            }
    
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (mAdapter == null) {
                    mPreviousOffset = positionOffset;
                    if (positionOffset > .5) {
                        dispatchOnPageScrolled(0, 0, 0);
                    } else {
                        dispatchOnPageScrolled(position, 0, 0);
                    }
                    return;
                }
                int realPosition = mAdapter.getRealPosition(position);
                int lastPosition = mAdapter.getCount() - 1;
    
                if (positionOffset == 0 && mPreviousOffset == 0 && lastPosition != 0 && (position == 0 || position == lastPosition)) {
                    setCurrentItem(realPosition, false);
                }
    
                mPreviousOffset = positionOffset;
    
                if (realPosition != mAdapter.getRealCount() - 1) {
                    dispatchOnPageScrolled(realPosition, positionOffset, positionOffsetPixels);
                } else if (positionOffset > .5) {
                    dispatchOnPageScrolled(0, 0, 0);
                } else {
                    dispatchOnPageScrolled(realPosition, 0, 0);
                }
            }
    
            @Override
            public void onPageScrollStateChanged(int state) {
                if (mAdapter != null) {
                    int position = LoopViewPager.super.getCurrentItem();
                    if (state == ViewPager.SCROLL_STATE_IDLE && (position == 0 || position == mAdapter.getCount() - 1)) {
                        setCurrentItem(mAdapter.getRealPosition(position), false);
                    }
                }
                dispatchOnScrollStateChanged(state);
            }
        };
    
        private static class InnerLoopAdapter extends PagerAdapter {
    
            final PagerAdapter pa;
    
            private SparseArray<Object> recycler = new SparseArray<Object>();
    
    
            InnerLoopAdapter(PagerAdapter adapter) {
                this.pa = adapter;
            }
    
            @Override
            public void notifyDataSetChanged() {
                recycler = new SparseArray<Object>();
                super.notifyDataSetChanged();
            }
    
            int getRealPosition(int position) {
                return toRealPosition(position, pa.getCount());
            }
    
            int getRealCount() {
                return pa.getCount();
            }
    
            @Override
            public int getCount() {
                int realCount = getRealCount();
                return realCount > 1 ? (realCount + 2) : realCount;
            }
    
            @Override
            public Object instantiateItem(ViewGroup container, int position) {
                int real = getRealPosition(position);
    
                Object destroy = recycler.get(position);
                if (destroy != null) {
                    recycler.remove(position);
                    return destroy;
                }
                return pa.instantiateItem(container, real);
            }
    
            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                int first = 1, last = getRealCount();
    
                if (position == first || position == last) {
                    recycler.put(position, object);
                } else {
                    pa.destroyItem(container, getRealPosition(position), object);
                }
            }
    
            @Override
            public void finishUpdate(ViewGroup container) {
                pa.finishUpdate(container);
            }
    
            @Override
            public boolean isViewFromObject(View view, Object object) {
                return pa.isViewFromObject(view, object);
            }
    
            @Override
            public void restoreState(Parcelable bundle, ClassLoader classLoader) {
                pa.restoreState(bundle, classLoader);
            }
    
            @Override
            public Parcelable saveState() {
                return pa.saveState();
            }
    
            @Override
            public void startUpdate(ViewGroup container) {
                pa.startUpdate(container);
            }
    
            @Override
            public void setPrimaryItem(ViewGroup container, int position, Object object) {
                pa.setPrimaryItem(container, position, object);
            }
        }
    
    }
    

    5、代码中引用

      public static String[] titles = new String[]{
                "每周7件Tee不重样",
                "俏皮又知性 适合上班族的漂亮衬衫",
                "名侦探柯南",
                "境界之轮回",
                "我的英雄学院",
                "全职猎人",
        };
        public static String[] urls = new String[]{//750x500
                "https://s2.mogucdn.com/mlcdn/c45406/170422_678did070ec6le09de3g15c1l7l36_750x500.jpg",
                "https://s2.mogucdn.com/mlcdn/c45406/170420_1hcbb7h5b58ihilkdec43bd6c2ll6_750x500.jpg",
                "http://s18.mogucdn.com/p2/170122/upload_66g1g3h491bj9kfb6ggd3i1j4c7be_750x500.jpg",
                "http://s18.mogucdn.com/p2/170204/upload_657jk682b5071bi611d9ka6c3j232_750x500.jpg",
                "http://s16.mogucdn.com/p2/170204/upload_56631h6616g4e2e45hc6hf6b7g08f_750x500.jpg",
                "http://s16.mogucdn.com/p2/170206/upload_1759d25k9a3djeb125a5bcg0c43eg_750x500.jpg"};
    
        public static class BannerItem {
            public String image;
            public String title;
    
            @Override
            public String toString() {
                return title;
            }
        }
    
        public static class BannerViewFactory implements BannerView.ViewFactory<BannerItem> {
            @Override
            public View create(final BannerItem item, int position, final ViewGroup container) {
                ImageView iv = new ImageView(container.getContext());
                iv.setScaleType(ImageView.ScaleType.CENTER_CROP);
                RequestOptions options = new RequestOptions().diskCacheStrategy(DiskCacheStrategy.DATA);
                Glide.with(container.getContext().getApplicationContext()).load(item.image).apply(options).into(iv);
                iv.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ToastUtil.showToast(container.getContext(), item.title, 0);
                    }
                });
                return iv;
            }
        }
      @Override
        protected void initViews(View view) {
            List<BannerItem> list = new ArrayList<>();
            for (int i = 0; i < urls.length; i++) {
                BannerItem item = new BannerItem();
                item.image = urls[i];
                item.title = titles[i];
    
                list.add(item);
            }
    
            banner.setViewFactory(new BannerViewFactory());
            banner.setDataList(list);
            banner.start();
        }
    

    6、xml布局文件

    <com.xxxx.banner.BannerView
      android:id="@+id/banner"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:background="@android:color/holo_red_dark"
      app:bvAspectRatio="0.5625"
      app:bvIndicatorDrawable="@mipmap/ic_banner_normal"
      app:bvIndicatorDrawableSelected="@mipmap/ic_banner_selected"
      app:bvIndicatorGravity="center"
      app:bvTitleVisible="true" />
    

    相关文章

      网友评论

          本文标题:自定义轮播图-简单不需要引用第三方库

          本文链接:https://www.haomeiwen.com/subject/ajcszftx.html