仿IOS没去标尺控件

 基于VIEW,参考别人代码实现,十分简单。

标尺刻度使用默认使用1,2,3,4,5

自定义刻度标签传入参数String数组,选中值使用数组索引值,设置默认值也可以索引。

根据数组长度划分刻度,根据传入的默认值选中刻度

 
 
@SuppressLint("ClickableViewAccessibility")
public class NewWheelView extends View {

    public interface OnValueChangeListener {
        void onValueChange(int value);
    }

    private int mTextSize = 16;
    private float mDensity;
    //默认选中值
    private int mValue = 7;
    //总项数
    private int mMaxValue = 10;
    //标尺间隔,可由控件宽度除以mMaxNum算出
    private int mLineDivider = 60;
    //每页最大显示数
    private int mMaxNum = 5;

    //控件的宽高
    private int mWidth, mHeight;

    //滑动相关参数
    private int mLastX, mMove;
    private int mMinVelocity;
    private Scroller mScroller;
    private VelocityTracker mVelocityTracker;

    //回调
    private OnValueChangeListener mListener;
    //是滞带背景
    private boolean isHasBg = false;
    //显示的标签
    private List<String> mLabels;

    @SuppressWarnings("deprecation")
    public NewWheelView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mScroller = new Scroller(getContext());
        mDensity = getContext().getResources().getDisplayMetrics().density;

        mMinVelocity = ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity();

        if (isHasBg) {
            setBackgroundDrawable(createBackground());
        }
    }

    /**
     * 默认显示的界面的元素个数
     * @param num
     */
    public void setMaxShow(int num){
        mMaxNum = num;
    }

    /**
     *
     * @param labels 标尺显示项的内容
     * @param index 默认选中的内容的索引
     */
    public void setLabels(List<String> labels, int index){
        mLabels = labels;
        mMaxValue = mLabels.size()-1;
        mValue = index;
    }
    public void setFontSize(int fontsize){
        mTextSize = fontsize;
    }

    //创建背景
    private GradientDrawable createBackground() {
        float strokeWidth = 4 * mDensity; // 边框宽度
        float roundRadius = 6 * mDensity; // 圆角半径
        int strokeColor = Color.parseColor("#FF666666");// 边框颜色

        setPadding((int)strokeWidth, (int)strokeWidth, (int)strokeWidth, 0);

        int colors[] = { 0xFF999999, 0xFFFFFFFF, 0xFF999999 };// 分别为开始颜色,中间夜色,结束颜色
        GradientDrawable bgDrawable = new GradientDrawable(GradientDrawable.Orientation.LEFT_RIGHT, colors);// 创建drawable
        bgDrawable.setCornerRadius(roundRadius);
        bgDrawable.setStroke((int)strokeWidth, strokeColor);
        return bgDrawable;
    }

    /**
     * 设置用于接收结果的监听器
     *
     * @param listener
     */
    public void setValueChangeListener(OnValueChangeListener listener) {
        mListener = listener;
    }

    /**
     * 获取当前刻度值
     *
     * @return
     */
    public float getValue() {
        return mValue;
    }
    //载入时设置默认值
    public void setValue(int val){
        mValue = val;
        postInvalidate();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        mWidth = getWidth();
        mHeight = getHeight();
        super.onLayout(changed, left, top, right, bottom);
        mLineDivider = (int) ((mWidth/mMaxNum)/mDensity);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        drawScaleLine(canvas);
        drawMiddleLine(canvas);
    }

    /**
     * 从中间往两边开始画刻度线
     *
     * @param canvas
     */
    private void drawScaleLine(Canvas canvas) {
        canvas.save();
        Paint linePaint = new Paint();
        linePaint.setStrokeWidth(2);
        linePaint.setColor(Color.BLACK);
        LogUtil.d("jiaABC", "drawScaleLine2+++++++++++++++++++++++++++");
        TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextSize(mTextSize * mDensity);

        int width = mWidth;
        int drawCount = 0;
        float xPosition, textHeight;
        float maxtextWidth = measureTextHeight(textPaint);
        for (int i = 0; drawCount <= 4 * width; i++) {
            LogUtil.d("jiaABC", "drawScaleLine2 drawCount="+drawCount);
            LogUtil.d("jiaABC", "drawScaleLine2 mValue="+mValue);

            xPosition = (width / 2 - mMove) + i * mLineDivider * mDensity;
            //离中心的每一个单位字体大小下降2
            textPaint.setTextSize((mTextSize-2*i) * mDensity);
            textHeight = measureTextHeight(textPaint);
            if (xPosition + getPaddingRight() < mWidth) {
                if (mValue + i <= mMaxValue) {
                    if (mLabels != null && mLabels.size()>0) {
                        canvas.drawText(mLabels.get(mValue + i), xPosition - textPaint.measureText(mLabels.get(mValue + i),0,mLabels.get(mValue + i).length())/2, textHeight + 10, textPaint);
                    }else{
                        canvas.drawText(String.valueOf(mValue + i), xPosition - textPaint.measureText(String.valueOf(mValue + i),0,String.valueOf(mValue + i).length())/2, textHeight + 10, textPaint);
                    }
                }
            }

            xPosition = (width / 2 - mMove) - i * mLineDivider * mDensity;
            if (xPosition > getPaddingLeft()) {
                if (mValue - i >= 0) {
                    if (mLabels != null && mLabels.size()>0) {
                        canvas.drawText(mLabels.get(mValue - i), xPosition - textPaint.measureText(mLabels.get(mValue - i),0, mLabels.get(mValue - i).length())/2, textHeight + 10, textPaint);
                    }else {
                        canvas.drawText(String.valueOf(mValue - i), xPosition - textPaint.measureText(String.valueOf(mValue - i),0,String.valueOf(mValue - i).length())/2, textHeight + 10, textPaint);
                    }
                }
            }

            drawCount += 2 * mLineDivider * mDensity;
        }

        canvas.restore();
    }
    /**
     * 测量文字的高度
     * --经测试后发现,采用另一种带Rect的方式,获得的数据并不准确。
     * 特别是在一些对文字有一些倾斜处理的时候
     * @param paint
     * @return
     */
    public static float measureTextHeight(Paint paint){
        float height = 0f;
        if(null == paint){
            return height;
        }
        Paint.FontMetrics fontMetrics = paint.getFontMetrics();
        height = fontMetrics.descent - fontMetrics.ascent;
        return height;
    }
    /**
     * 计算没有数字显示位置的辅助方法
     *
     * @param value
     * @param xPosition
     * @param textWidth
     * @return
     */
    private float countLeftStart(int value, float xPosition, float textWidth) {
        float xp = 0f;
        if (mLabels != null && mLabels.size()>0) {
            int len = mLabels.get(value).length();
            xp = xPosition - len/2;
        }else {
            if (value < 10) {
                xp = xPosition - (textWidth * 1 / 2);
            } else if (value < 100){
                xp = xPosition - (textWidth * 2 / 2);
            } else if (value < 1000){
                xp = xPosition - (textWidth * 3 / 2);
            } else {
                xp = xPosition - (textWidth * 4 / 2);
            }
        }
        return xp;
    }
    /**
     * 画中间的红色指示线、阴影等。指示线两端简单的用了两个矩形代替
     *
     * @param canvas
     */
    private void drawMiddleLine(Canvas canvas) {
        int color = Color.YELLOW;
        int height = 30;
        int lens = 40;
        int pos_y = 10;

        canvas.save();
        Paint paint = new Paint();
        paint.setColor(color);
        //设置实心
        paint.setStyle(Paint.Style.FILL);
        paint.setStrokeWidth(1);
        // 设置画笔的锯齿效果
        paint.setAntiAlias(true);

        Path path = new Path();

        path.moveTo(mWidth / 2, mHeight-height-pos_y);
        //从起始位置划线到(200, 200)坐标
        path.lineTo((mWidth / 2) - (lens/2), mHeight - pos_y);
        path.lineTo((mWidth / 2) + (lens/2), mHeight - pos_y);
        //将mpath封闭,也可以写 mpath.lineTo(100, 100);代替
        path.close();
        //绘制path路径
        canvas.drawPath(path, paint);

        canvas.restore();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int action = event.getAction();
        int xPosition = (int) event.getX();

        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);

        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mScroller.forceFinished(true);
                mLastX = xPosition;
                mMove = 0;
                break;
            case MotionEvent.ACTION_MOVE:
                mMove += (mLastX - xPosition);
                changeMoveAndValue();
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                countMoveEnd();
                countVelocityTracker(event);
                return false;
            // break;
            default:
                break;
        }

        mLastX = xPosition;
        return true;
    }

    private void countVelocityTracker(MotionEvent event) {
        mVelocityTracker.computeCurrentVelocity(1000);
        float xVelocity = mVelocityTracker.getXVelocity();
        if (Math.abs(xVelocity) > mMinVelocity) {
            mScroller.fling(0, 0, (int) xVelocity, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
        }
    }

    private void changeMoveAndValue() {
        int tValue = (int) (mMove / (mLineDivider * mDensity));
        if (Math.abs(tValue) > 0) {
            mValue += tValue;
            mMove -= tValue * mLineDivider * mDensity;
            if (mValue <= 0 || mValue > mMaxValue) {
                mValue = mValue <= 0 ? 0 : mMaxValue;
                mMove = 0;
                mScroller.forceFinished(true);
            }
            notifyValueChange();
        }
        postInvalidate();
    }

    private void countMoveEnd() {
        int roundMove = Math.round(mMove / (mLineDivider * mDensity));
        mValue = mValue + roundMove;
        mValue = mValue <= 0 ? 0 : mValue;
        mValue = mValue > mMaxValue ? mMaxValue : mValue;

        mLastX = 0;
        mMove = 0;

        notifyValueChange();
        postInvalidate();
    }

    private void notifyValueChange() {
        if (null != mListener) {
            mListener.onValueChange(mValue);
        }
        LogUtil.d("jiaABC", "notifyValueChange mValue="+mValue);
    }

    @Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()) {
            if (mScroller.getCurrX() == mScroller.getFinalX()) { // over
                countMoveEnd();
            } else {
                int xPosition = mScroller.getCurrX();
                mMove += (mLastX - xPosition);
                changeMoveAndValue();
                mLastX = xPosition;
            }
        }
    }
}

参考:

https://blog.csdn.net/ttdevs/article/details/38944799

猜你喜欢

转载自blog.csdn.net/blogercn/article/details/106178976
今日推荐