美文网首页安卓Android Tipstab
Android自定义View——ScrollChooseView

Android自定义View——ScrollChooseView

作者: 超神的菠萝 | 来源:发表于2017-03-01 22:41 被阅读1551次

    图纸

    图片.png
    使用viewpager的效果图
    ScreenGif.gif
    自定义View的效果图
    ScreenGif.gif

    github地址

    点击这里

    使用

    compile 'com.github.superSp:ScrollChooseView:v1.0.2'
    
     String titles[] = new String[]{"早餐前", "早餐后", "午餐前", "午餐后", "晚餐前", "晚餐后", "睡前"};
     private int picIds[] = new int[]{
                R.mipmap.time_bg_breakfastbefore, R.mipmap.time_bg_breakfastafter,
                R.mipmap.time_bg_lunchbefore, R.mipmap.time_bg_lunchafter,
                R.mipmap.time_bg_dinnerbefor, R.mipmap.time_bg_dinnerafter,
                R.mipmap.time_bg_sleep
        };
    
     scrollChooseView.setTitles(titles);
     scrollChooseView.setPicIds(picIds);
     scrollChooseView.setOnScrollEndListener(new ScrollChooseView.OnScrollEndListener() {
                @Override
                public void currentPosition(int position) {
                    Log.d(TAG, "当前positin=" + position + " " + titles[position]);
                }
            });
    

    实现方式

    构造方法
    
    
    public ScrollChooseView(Context context) {
          this(context, null);
      }
    
      public ScrollChooseView(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
    
      public ScrollChooseView(Context context, AttributeSet attrs, int defStyleAttr) {
          super(context, attrs, defStyleAttr);
    
          textBound = new Rect();
          paint = new Paint();
          paint.setAntiAlias(true);
          paint.setColor(Color.WHITE);
          paint.setTextSize(DensityUtils.sp2px(getContext(), 10));
    
          mScroller = new Scroller(context);
    
      }
    
    onMeasure

    当设置为wrap时候 高度显示为200

    @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            int widhtMode = MeasureSpec.getMode(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    
            setMeasuredDimension(widhtMode == MeasureSpec.EXACTLY ? widthSize : widthSize, heightMode == MeasureSpec.EXACTLY ? heightSize : DensityUtils.dp2px(getContext(),100));
        }
        }
    

    onDraw

    绘制text并且根据当前position切换背景和字体大小以及底部线

     @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (titles == null) {
                return;
            }
            drawText(canvas);
        }
    
        private void drawText(Canvas canvas) {
            for (int i = 0; i < titles.length; i++) {
                if (getCurrentPosition() == i) {
                    paint.setTextSize(DensityUtils.sp2px(getContext(), 20));
                    paint.getTextBounds(titles[i], 0, titles[i].length(), textBound);
                    canvas.drawText(titles[i], getMeasuredWidth() / 6 * (2 * i + 1) - (textBound.width() / 2), (getMeasuredHeight() / 2) + textBound.height() / 2, paint);
                    paint.setStrokeWidth(3);
                    canvas.drawLine(getMeasuredWidth() / 6 * (2 * i + 1) - (textBound.width() / 2) - 10, (getMeasuredHeight() / 2) + textBound.height(),
                            getMeasuredWidth() / 6 * (2 * i + 1) + (textBound.width() / 2) + 10, (getMeasuredHeight() / 2) + textBound.height(), paint);
    
                } else {
                    paint.setTextSize(DensityUtils.sp2px(getContext(), 10));
                    paint.getTextBounds(titles[i], 0, titles[i].length(), textBound);
                    canvas.drawText(titles[i], getMeasuredWidth() / 6 * (2 * i + 1) - (textBound.width() / 2), (getMeasuredHeight() / 2) + textBound.height() / 2, paint);
                }
                setBackgroundResource(picIds[getCurrentPosition()]);
            }
        }
    

    getCurrentPosition() 获取当前所处的位置

    这个等以后有时间完善吧。。目前item最多支持7个。。不过你想要支持更多,只要按照这个格式继续添加就好了。。。

     //当前的位置
        private int getCurrentPosition() {
            int position = 1;
    
            if (getScrollX() > getMeasuredWidth() / 6 * 1 * -3 && getScrollX() <= getMeasuredWidth() / 6 * 1 * -1) {
                position = 0;
            } else if (getScrollX() > getMeasuredWidth() / 6 * 1 * -1 && getScrollX() <= getMeasuredWidth() / 6 * 1 * 1) {
                position = 1;
            } else if (getScrollX() > getMeasuredWidth() / 6 * 1 * 1 && getScrollX() <= getMeasuredWidth() / 6 * 1 * 3) {
                position = 2;
            } else if (getScrollX() > getMeasuredWidth() / 6 * 1 * 3 && getScrollX() <= getMeasuredWidth() / 6 * 1 * 5) {
                position = 3;
            } else if (getScrollX() > getMeasuredWidth() / 6 * 1 * 5 && getScrollX() <= getMeasuredWidth() / 6 * 1 * 7) {
                position = 4;
            } else if (getScrollX() > getMeasuredWidth() / 6 * 1 * 7 && getScrollX() <= getMeasuredWidth() / 6 * 1 * 9) {
                position = 5;
            } else if (getScrollX() > getMeasuredWidth() / 6 * 1 * 9 && getScrollX() <= getMeasuredWidth() / 6 * 1 * 11) {
                position = 6;
            } else if (getScrollX() > getMeasuredWidth() / 6 * 1 * 11 && getScrollX() <= getMeasuredWidth() / 6 * 1 * 13) {
                position = 7;
            } else if (getScrollX() > getMeasuredWidth() / 6 * 1 * 13 && getScrollX() <= getMeasuredWidth() / 6 * 1 * 15) {
                position = 8;
            }
    
            return position;
    
        }
    

    onTouchEvent() 处理滑动

     @Override
        public boolean onTouchEvent(MotionEvent event) {
            if (titles.length <= 1) {
                return super.onTouchEvent(event);
            }
            int x = (int) event.getX();
            switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    isClick = true;
                    downX = x;
                    break;
                case MotionEvent.ACTION_MOVE:
                    isClick = false;
                    int offset = x - downX;
                    if (getScrollX() < -getMeasuredWidth() / 3 || getScrollX() > getMeasuredWidth() / 3 * titles.length - getMeasuredWidth() + getMeasuredWidth() / 3) {
                        return super.onTouchEvent(event);
                    } else {
                        scrollX(lastScrollX - offset, true);
                    }
                    break;
                case MotionEvent.ACTION_UP:
                    if (isClick) {
                        return true;
                    }
                    if (getScrollX() < -getMeasuredWidth() / 3) {
                        scrollX(-getMeasuredWidth() / 3, true);
                    }
                    if (getScrollX() > getMeasuredWidth() / 3 * titles.length - getMeasuredWidth() + getMeasuredWidth() / 3) {
                        scrollX(getMeasuredWidth() / 3 * titles.length - getMeasuredWidth() + getMeasuredWidth() / 3, true);
                    }
    
                    scrollX(getMeasuredWidth() / 3 * (getCurrentPosition() - 1), false);
    
                    break;
            }
            return true;
        }
    

    接下来是Scroller自动滑动的普遍写法。。

         /**
         * b 是代表手动滑 还是自动滑动。。
         *
         * @param endX
         * @param b
         */
        private void scrollX(int endX, boolean b) {
            if (b) {
                scrollTo(endX, 0);
            } else {
                isScroll = true;
                lastScrollX = endX;
                smoothScrollTo(endX, 0);
            }
        }
    
        public void smoothScrollTo(int destX, int destY) {
            // 第二步,调用startScroll()方法来初始化滚动数据并刷新界面
            mScroller.startScroll(getScrollX(), 0, destX - getScrollX(), 0, 200);
            invalidate();
        }
    
        @Override
        public void computeScroll() {
            // 第三步,重写computeScroll()方法,并在其内部完成平滑滚动的逻辑
            if (mScroller.computeScrollOffset()) {
                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                invalidate();
            } else {
                if (isScroll) {
                    setScrollX(lastScrollX);
                    isScroll = false;
                    if (onScrollEndListener != null) {
                        onScrollEndListener.currentPosition(getCurrentPosition());
                    }
                }
            }
        }
    

    供外部使用的接口和方法

    设置标题
     public void setTitles(String titles[]) {
            this.titles = titles;
            invalidate();
        }
    设置背景图片
    public void setPicIds(int[] picIds) {
            this.picIds = picIds;
        }
    设置滑动结束后的position监听
    public void setOnScrollEndListener(OnScrollEndListener onScrollEndListener) {
            this.onScrollEndListener = onScrollEndListener;
        }
    

    相关文章

      网友评论

        本文标题:Android自定义View——ScrollChooseView

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