美文网首页
自定义Banner

自定义Banner

作者: 资本家大恶人 | 来源:发表于2020-08-25 16:15 被阅读0次

    使用自定义Banner

    思路
    1.添加自定义ViewPager
    2.添加title背景
    3.添加指示器
    4.添加title
    5.使用Handler实现自动滑动

    自定义Banner

    
    public class Banner extends ConstraintLayout implements LifecycleObserver {
        private int mId;
        private ArrayList<? extends IBannerData> mBannerData;
        private ViewPager2 viewPager2;
        private TextView tilte;
        LifecycleOwner mLifecycleOwner;
        private CirlcleIndicator mCirlcleIndicator;
    /**
    * 构造方法
    */
        public Banner(Context context) {
            super(context);
        }
    
        public Banner(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView();
        }
    
        public Banner(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
    
        }
    /*
    * 进行测量
    */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
        private void initView() {
    //        得到设置布局对象
            ConstraintSet constraintSet = new ConstraintSet();
    //        克隆布局所有属性
            constraintSet.clone(this);
            /*step1 创建ViewPager2得到ID和添加View*/
            viewPager2 = new ViewPager2(getContext());
            viewPager2.setId(mId++);
            viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
                @Override
                public void onPageSelected(int position) {
    
                    tilte.setText(mBannerData.get(position % mBannerData.size()).getTitle());
                    mCirlcleIndicator.setCurrentCount(position % mBannerData.size());
    
                }
            });
    
            addView(viewPager2);
    //        连线
            constraintSet.connect(viewPager2.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);
            constraintSet.connect(viewPager2.getId(), ConstraintSet.TOP, ConstraintSet.PARENT_ID, ConstraintSet.TOP);
            constraintSet.connect(viewPager2.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM);
            constraintSet.connect(viewPager2.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
    //        设置大小
            constraintSet.constrainWidth(viewPager2.getId(), ConstraintSet.MATCH_CONSTRAINT);
            constraintSet.constrainHeight(viewPager2.getId(), ConstraintSet.MATCH_CONSTRAINT);
            /*step2 给字体设置背景*/
            ImageView mask = new ImageView(getContext());
            mask.setBackgroundColor(Color.parseColor("#40000000"));
            mask.setId(mId++);
            addView(mask);
    //    连线
            constraintSet.connect(mask.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
            constraintSet.connect(mask.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);
            constraintSet.connect(mask.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM);
    //        设置大小
            constraintSet.constrainWidth(mask.getId(), ConstraintSet.MATCH_CONSTRAINT);
            constraintSet.constrainHeight(mask.getId(), dipTopx(30));
            /* step3 设置指示器*/
            mCirlcleIndicator = new CirlcleIndicator(getContext());
            mCirlcleIndicator.setSelectorColor(Color.WHITE);
            mCirlcleIndicator.setUnSelectorColor(Color.GREEN);
            mCirlcleIndicator.setRadio(8);
            mCirlcleIndicator.setMargin(dipTopx(5));
            mCirlcleIndicator.setId(mId++);
    //        添加View
            addView((View) mCirlcleIndicator);
    //        连线
            constraintSet.connect(mCirlcleIndicator.getId(), ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END);
            constraintSet.connect(mCirlcleIndicator.getId(), ConstraintSet.TOP, mask.getId(), ConstraintSet.TOP);
            constraintSet.connect(mCirlcleIndicator.getId(), ConstraintSet.BOTTOM, mask.getId(), ConstraintSet.BOTTOM);
    
    //        设置大小
            constraintSet.constrainWidth(mCirlcleIndicator.getId(), ConstraintSet.WRAP_CONTENT);
            constraintSet.constrainHeight(mCirlcleIndicator.getId(), ConstraintSet.WRAP_CONTENT);
    
    
            /*      step4  设置标题*/
            tilte = new TextView(getContext());
            tilte.setId(mId++);
            tilte.setTextColor(Color.WHITE);
            tilte.setSingleLine(true);
            boolean mTitleMarquee=true;
            if(mTitleMarquee){
                tilte.setEllipsize(TextUtils.TruncateAt.MARQUEE);
                tilte.setSelected(true);
                tilte.setMarqueeRepeatLimit(-1);
            }else{
                tilte.setEllipsize(TextUtils.TruncateAt.END);
            }
    
    //        添加文字
            addView(tilte);
    
    //        连线
            constraintSet.connect(tilte.getId(), ConstraintSet.START,ConstraintSet.PARENT_ID, ConstraintSet.START);
            constraintSet.connect(tilte.getId(), ConstraintSet.END, mCirlcleIndicator.getId(), ConstraintSet.END);
            constraintSet.connect(tilte.getId(), ConstraintSet.BOTTOM, mask.getId(), ConstraintSet.BOTTOM);
            constraintSet.connect(tilte.getId(), ConstraintSet.TOP, mask.getId(), ConstraintSet.TOP);
    //        设置大小
            constraintSet.constrainWidth(tilte.getId(), ConstraintSet.MATCH_CONSTRAINT);
            constraintSet.constrainHeight(tilte.getId(), ConstraintSet.WRAP_CONTENT);
    
    
    //        应用该布局
            constraintSet.applyTo(this);
        }
    
        //    给banner控件设置数据
        public void setBannerData(BannerAdapter adapter) {
    //        得到banner数据
            mBannerData = adapter.getBannerData();
    //        设置数据
            viewPager2.setAdapter(adapter);
            viewPager2.setUserInputEnabled(true);
    //      得到当前banner的位置
            int position = Integer.MAX_VALUE / 2 - Integer.MAX_VALUE / 2 % mBannerData.size();
            viewPager2.setCurrentItem(position, false);
    
    //        设置指示器
            mCirlcleIndicator.setCount(mBannerData.size());
            mCirlcleIndicator.setCurrentCount(position % mBannerData.size());
        }
    
    
        //    dip转px
        public int dipTopx(float dpValue) {
            final float scale = getContext().getResources().getDisplayMetrics().density;
            return (int) (dpValue * scale + 0.5f);
        }
    
        /**
         * 设置循环轮播
         */
        private Runnable mLoopTask = new Runnable() {
            @Override
            public void run() {
    //            获取当前下标
                int cIndex = viewPager2.getCurrentItem();
    //            下标加一
                viewPager2.setCurrentItem(++cIndex, true);
                viewPager2.postDelayed(this, 3000);
            }
        };
    
        public void startLoop() {
            //   循环轮播
            if ((mBannerData != null && mBannerData.size() > 1) && (getVisibility() == VISIBLE)) {
                viewPager2.postDelayed(mLoopTask, 3000);
    
            }
        }
    
        //    停止轮播
        public void stopLoop() {
    //        移除该任务
            viewPager2.removeCallbacks(mLoopTask);
    
        }
    
        //  查看当前页面是否可见
        @Override
        protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
            super.onVisibilityChanged(changedView, visibility);
            if (visibility == VISIBLE) {
                startLoop();
            } else {
                stopLoop();
            }
        }
    
        /**
         *
         * @param lifecycleOwner
         * 获得lifecycle监听生命周期
         */
        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
            this.mLifecycleOwner = lifecycleOwner;
            mLifecycleOwner.getLifecycle().addObserver(this);
        }
    
        //   通过Lifecycle监听生命周期
    
        private boolean isOnResume = false;
    
        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        public void onResume() {
            isOnResume = true;
            startLoop();
        }
    
        //   通过Lifecycle监听生命周期
    
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        public void onPause() {
            isOnResume = false;
            Log.d("TAG", "onPause: ");
            stopLoop();
        }
    
        /**
         * 解决滑动冲突
         * @param ev
         * @return
         */
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
    
    
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN: {
                    stopLoop();
                    break;
                }
                case MotionEvent.ACTION_MOVE: {
    //                阻止滑动事件交给ViewGroup让子view自己处理
                    getParent().requestDisallowInterceptTouchEvent(true);
                }
                case MotionEvent.ACTION_UP: {
                    startLoop();
                }
            }
            return super.dispatchTouchEvent(ev);
    
        }
    
        /**
         * 解决滑动时间
         * @return
         */
        public int getScrollTime() {
            return 0;
        }
    
        public ViewPager2 getViewPager2() {
            return viewPager2;
        }
    }
    
    

    创建指示器

    思路
    1.创建接口设置需要的数据
    2.设置画笔
    3.得到数量测量需要的绘制的大小
    4.调用onMeasure()方法重新测量
    5.进行绘制圆

    创建指示器接口

    
    interface Indicator {
        //    设置半径
        void setRadio(int radio);
    
        //  设置条目数量
        void setCount(int current);
    
        // 设置当前下标
        void setCurrentCount(int current);
    
        //  设置为选中的颜色
        void setUnSelectorColor(int unSelectColor);
    
        //  设置选中的颜色
        void setSelectorColor(int selectColor);
    
        //    设置边距
        void setMargin(int margin);
    
        //   设置ID
        void setId(int id);
    
        int getId();
    }
    
    

    创建指示器

    
    public class CirlcleIndicator extends View implements Indicator {
    
        private static final int MAX_COUNT = 10;
        private int mRadio;//半径
        private int mCurrent;//当前条目
        private int mRealCount;//真正的数量
        private int mUnSelectColor;//为选中yanse
        private int mSelectColor;//选中颜色
        private int mMargin;//边距
        private int mCount = 10;
        private Paint mPaint;
        private int mHeight;
        private int mWidth;
    
    
        public CirlcleIndicator(Context context) {
            super(context);
            initPaint();
        }
    
        public CirlcleIndicator(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            initPaint();
        }
    
        public CirlcleIndicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initPaint();
        }
    
        //  设置画笔
        private void initPaint() {
            mPaint = new Paint();
            mPaint.setAntiAlias(true);//消除边距
            mPaint.setStyle(Paint.Style.FILL);//绘画的风格
            mPaint.setColor(Color.WHITE);
        }
    //   计算绘制的长度
        private void calculation() {
    //        得到指示器最大长度
            mCount = Math.min(mRealCount, MAX_COUNT);
            mHeight = mRadio * 2;
            mWidth = (mCount * mRadio * 2) + (mCount - 1) * mMargin;
    //        刷新页面重新走onDrawer(),onLayout(),onMeasuer();
            invalidate();
        }
    
        /**
         *
         * @param widthMeasureSpec
         * @param heightMeasureSpec
         * 测量
         */
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    //  重新计算绘制的高度和宽度
            setMeasuredDimension(MeasureSpec.makeMeasureSpec(mWidth, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(mHeight, MeasureSpec.EXACTLY));
        }
    //绘制
        @Override
        protected void onDraw(Canvas canvas) {
    //        super.onDraw(canvas);
            for (int i = 0; i < mCount; i++) {
    //            如果等于当前下标
                if (i == mCurrent % mCount) {
                    mPaint.setColor(mSelectColor);
                } else {
    //                如果不等于
                    mPaint.setColor(mUnSelectColor);
                }
    //            开始绘制
                canvas.drawCircle((i * (mRadio * 2) + (i * mMargin) + mRadio), mRadio, mRadio, mPaint);
            }
    
        }
    
        @Override
        public void setRadio(int radio) {
            mRadio = radio;
        }
    
        /**
         * 计数
         * @param count
         */
        @Override
        public void setCount(int count) {
    //        如果真是数量发生改变
            if (mRealCount != count) {
    //            设置真是数量
                mRealCount = count;
    //            计算
                calculation();
            }
        }
    
        @Override
        public void setCurrentCount(int current) {
    //        如果传入当前下标与当前下标不一样刷新
            if (mCurrent != current) {
                mCurrent = current;
                invalidate();
            }
        }
    //  设置未选中的颜色
        @Override
        public void setUnSelectorColor(int unSelectColor) {
            mUnSelectColor = unSelectColor;
        }
    //   设置未选中的颜色
         @Override
        public void setSelectorColor(int selectColor) {
            mSelectColor = selectColor;
        }
    
    //  设置margin
        @Override
        public void setMargin(int margin) {
            mMargin = margin;
        }
    }
    
    

    相关文章

      网友评论

          本文标题:自定义Banner

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