Android自定义View之滑动取值条

Android自定义View之滑动取值条

1 : 需求
可自定义更改滑动条的样式(本功能实现两种样式)
联动方式 : 滑块上更新的值通过回调给Edittext; 在Edittext上输入值,更新滑动条的游标的位置和值
高度复合性: 可根据需求,自初始化值,及返回值的调整,显示精度的可调整性
,超过滑动范围的可调整性
滑动取值条的取值方式: 可滑动,可点击
当值过大时,取值条上的值根据像素比例进行相应的缩放,使其显示完全

2: 实现

public CustomTakeValueArticle(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public CustomTakeValueArticle(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

上面的代码这里只构造了两个方法

初始化init(Context context)的实现如下:

  /**
     * 初始化
     *
     * @param context
     */
    private void init(Context context) {
        mTrunkBmp = BitmapFactory.decodeResource(getResources(), R.drawable.cursor_line_red);
        mTrunkBmpDeep = BitmapFactory.decodeResource(getResources(), R.drawable.cursor_line_red_deep);
        mCursorBmp = BitmapFactory.decodeResource(getResources(), R.drawable.red_cursor);
        matrix = new Matrix();
        matrixDeep = new Matrix();
        mTrunkHight = mTrunkBmp.getHeight();
        mCursorWidth = mCursorBmp.getWidth();
        mCursorHight = mCursorBmp.getHeight();
        mTrunkMarginTop = dip2px(context, TRUNKMARGINTOP);
        mTextCursorSpace = dip2px(context, TEXT_CURSOR_SPACE);
        mCursorTextSize = sp2px(context, TEXTSIZE);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mClickTimeout = ViewConfiguration.getPressedStateDuration() + ViewConfiguration.getTapTimeout();
        mLineWidth = dip2px(context, LINEWIDTH);
        mPaint = new Paint();
        mPaint.setColor(Color.RED);// 设置红色
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(mCursorTextSize);
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        mTextHight = (int) (fontMetrics.descent - fontMetrics.ascent + 0.5f);
    }

这里对刻度杆滑动,未滑动,游标图的bitmap进行初始化,相关矩阵,画笔等初始化

重写onDraw方法

    /**
     * 重写onDraw方法
     *
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mScaling = (getWidth() - getPaddingRight() - getPaddingLeft() - mCursorWidth)
                / (getXAxisEnd() - getXAxisStart());
        if (ISCENTERVERTICALTRUNK) {
            mTrunkMarginTop = (getHeight() - mTrunkHight) / 2.0f;
        }
        if (dstbmp != null)
            dstbmp.recycle();
        dstbmp = null;
        drawTrunk(canvas, mTrunkMarginTop);
        drawCursor(canvas);
    }

这里在重写onDraw方法时取实际坐标转换为像素坐标的比例 mScaling
,刻度杆的上边界像素坐标mTrunkMarginTop,再进行重写drawTrunk(刻度杆),drawCursor(游标)的方法.

drawTrunk(刻度杆)的方法如下:

   /**
     * 绘制刻度条主干
     *
     * @param canvas
     */
    private void drawTrunk(Canvas canvas, float mTrunkMarginTop) {
        int leftbmp = getPaddingLeft();
        int topBoundary = (int) (mTrunkMarginTop + 0.5f);
        int widthbmp = getWidth() - getPaddingLeft() - getPaddingRight();
        float scaw = widthbmp * 1.0f / (mTrunkBmp.getWidth());
        matrix.setScale(scaw, 1.0f);

        /**
         * 绘制未选中的值刻度线
         */
        if (dstbmp == null)
            dstbmp = Bitmap.createBitmap(mTrunkBmp, 0, 0, mTrunkBmp.getWidth(), mTrunkBmp.getHeight(), matrix, true);
        canvas.drawBitmap(dstbmp, leftbmp, topBoundary, null);


        /**
         * 绘制选中的值刻度线
         */
        if (x - mXAxisStart >= 0 && mXAxisEnd - x >= 0) {
            scaw = (float) (getWidthForXValue() * 1.0f / mTrunkBmpDeep.getWidth());
        } else if (mXAxisEnd - x < 0) {
            scaw = (float) (getWidthForXValue() * 1.0f / mTrunkBmpDeep.getWidth());
        } else {
            scaw = mCursorWidth / 2.0f / mTrunkBmpDeep.getWidth();
        }
        float scaH = mTrunkBmp.getHeight() * 1.0f / mTrunkBmpDeep.getHeight();
        matrixDeep.setScale(scaw, scaH);
        Bitmap dstbmpdeep = Bitmap.createBitmap(mTrunkBmpDeep, 0, 0, mTrunkBmpDeep.getWidth(),
                mTrunkBmpDeep.getHeight(), matrixDeep, true);
        canvas.drawBitmap(dstbmpdeep, leftbmp, topBoundary, null);


        /**
         * 绘制起始值和结束值(isInteger保留整数,否则精度)
         */

        double tempX = getXForXvalue(mXAxisEnd);
        mPaint.setColor(getTrunkTextColor());
        String mEnd;
        if (isInteger) {//保持整形
            mEnd = String.valueOf((int) mXAxisEnd);
        } else {
            BigDecimal bd = new BigDecimal(mXAxisEnd);
            bd = bd.setScale(precision, BigDecimal.ROUND_HALF_DOWN);
            mEnd = String.valueOf(bd.doubleValue());
        }
        refitText(mEnd, computeMaxStringWidth(mEnd));
        canvas.drawText(mEnd, (float) tempX,
                mTrunkHight / 2.0f + mCursorHight + mTextHight + mTextHight / 2.0f,
                mPaint);


        String mStart;
        if (isInteger) {//保持整形
            mStart = String.valueOf((int) mXAxisStart);
        } else {
            BigDecimal bd = new BigDecimal(mXAxisStart);
            bd = bd.setScale(precision, BigDecimal.ROUND_HALF_UP);
            mStart = String.valueOf(bd.doubleValue());
        }
        double tempSX = getXForXvalue(mXAxisStart);
        mPaint.setColor(getTrunkTextColor());
        refitText(mStart, computeMaxStringWidth(mStart));
        canvas.drawText(mStart, (float) tempSX,
                mTrunkHight / 2.0f + mCursorHight + mTextHight + mTextHight / 2.0f,
                mPaint);

        /**
         * 绘制标记(起始位置和结束位置)
         */
        float lineW = (mLineWidth + 0.5f);
        float tempLSX = (float) getXForXvalue(mXAxisStart);
        mPaint.setColor(getTrunkTextColor());
        canvas.drawRect(tempLSX, mTrunkMarginTop, tempLSX + lineW, mTrunkMarginTop + mTrunkHight, mPaint);
        float tempLEX = (float) getXForXvalue(mXAxisEnd);
        mPaint.setColor(getTrunkTextColor());
        canvas.drawRect(tempLEX, mTrunkMarginTop, tempLEX + lineW, mTrunkMarginTop + mTrunkHight, mPaint);
    }

绘制刻度杆主干只要绘制未选中的值刻度线,选中的值刻度线,以及绘制起始值和结束值,根据isInteger来设置是否保持整形还是精度,精度值根据precision参数来设置

绘制游标drawCursor方法如下:

/**
     * 绘制游标
     *
     * @param canvas
     */
    private void drawCursor(Canvas canvas) {

        /**
         * 绘制游标图片
         */
        canvas.drawBitmap(mCursorBmp, (int) (getXLocation() - mCursorWidth / 2.0f + 0.5f),
                (int) (mTrunkMarginTop + mTrunkHight / 2.0f - mCursorHight / 2.0f + 0.5f), null);

        /**
         * 绘制游标文字
         */

        if (isInteger) {//点差策略
            scrollValue = String.valueOf(((int) value));
        } else {
            BigDecimal bd = new BigDecimal(scrollValue);
            bd = bd.setScale(precision, BigDecimal.ROUND_HALF_UP);
            scrollValue = String.valueOf(bd.doubleValue());
        }
        mPaint.setColor(getCursorTextColor());
        refitText(scrollValue, computeMaxStringWidth(scrollValue));
        canvas.drawText(scrollValue, (int) (getXLocation() + 0.5f),
                (int) (mTrunkMarginTop - mCursorHight / 2.0f + mTrunkHight / 2.0f + 0.5f - mTextCursorSpace),
                mPaint);

    }

该方法里主要是绘制游标图片和绘制游标文字

完整的View代码如下:

package com.example.administrator.myapplication;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.text.Layout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.TextView;

import java.math.BigDecimal;

/**
 * Created by Linhailin on 2017/2/13.
 */

public class CustomTakeValueArticle extends View {
    /**
     * 红色(游标和范围)颜色值
     */
    private final int COLOR_PROFIT_LINE = getResources().getColor(R.color.scroll_bar_line_red);
    private final int COLOR_PROFIT_TEXT = getResources().getColor(R.color.scroll_bar_text_red_label);

    /**
     * 绿色(游标和范围)颜色值
     */
    private final int COLOR_LOSS_LINE = getResources().getColor(R.color.scroll_bar_line_bule);
    private final int COLOR_LOSS_TEXT = getResources().getColor(R.color.scroll_bar_text_bule_label);

    /**
     * 滑动游标图片
     */
    private Bitmap mCursorBmp;

    /**
     * 主干相关
     */
    private Bitmap mTrunkBmp;
    private Matrix matrix;
    private Bitmap dstbmp;
    private Matrix matrixDeep;
    private Bitmap mTrunkBmpDeep;

    /**
     * 画笔
     */
    private Paint mPaint;

    /**
     * 文字大小(PX)
     */
    private float mCursorTextSize = 0;

    /**
     * 刻度杆的上边界像素坐标
     */
    private float mTrunkMarginTop = 20;

    /**
     * 横坐标开始点坐标
     */
    private double mXAxisStart;

    /**
     * 横坐标结束点坐标
     */
    private double mXAxisEnd;

    /**
     * 实际坐标转换为像素坐标的比例
     */
    private double mScaling;

    /**
     * 游标的宽度
     */
    private float mCursorWidth = 0;

    /**
     * 游标的高度
     */
    private int mCursorHight = 0;


    /**
     * 刻度杆的高度
     */
    private int mTrunkHight = 0;

    /**
     * 刻度杆的上边界(DP)
     */
    private float TRUNKMARGINTOP = 15;

    /**
     * 刻度杆是否居中
     */
    private boolean ISCENTERVERTICALTRUNK = true;

    private double x = 0;

    /**
     * 游标与文字之间的间隔
     */
    private int mTextCursorSpace = 0;

    /**
     * 游标与文字之间的间隔(DP)
     */
    private final float TEXT_CURSOR_SPACE = 0.5f;

    /**
     * 文字大小(SP)
     */
    private int TEXTSIZE = 10;

    /**
     * 文字的高度
     */
    private float mTextHight;

    /**
     * 是止盈
     */
    private boolean isProfit = true;

    private OnScrollListener onScrollListener;
    private OnClickListener onClickListener;
    private boolean noSetX = true;
    /**
     * 刻度线的粗细
     */
    private float mLineWidth = 0;
    /**
     * 刻度线的粗细(DP)
     */
    private final int LINEWIDTH = 1;
    /**
     * 当前游标上的数值
     */
    private double value;

    /**
     * 当前游标上的文字
     */
    private String scrollValue = "0";

    /**
     * 触摸滑动计数,超过,这认为不是点击事件
     */
    private int mTouchSlop = 0;

    /**
     * 触摸时间,超过,则认为不是点击事件
     */
    private int mClickTimeout = 0;

    /**
     * 值的精度
     */
    private int precision;

    /**
     * 设置类型(是否需要保持精度还是整形)
     */
    private Boolean isInteger;


    public CustomTakeValueArticle(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    public CustomTakeValueArticle(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    /**
     * 初始化
     *
     * @param context
     */
    private void init(Context context) {
        mTrunkBmp = BitmapFactory.decodeResource(getResources(), R.mipmap.cursor_line_red);
        mTrunkBmpDeep = BitmapFactory.decodeResource(getResources(), R.mipmap.cursor_line_red_deep);
        mCursorBmp = BitmapFactory.decodeResource(getResources(), R.mipmap.red_cursor);
        matrix = new Matrix();
        matrixDeep = new Matrix();
        mTrunkHight = mTrunkBmp.getHeight();
        mCursorWidth = mCursorBmp.getWidth();
        mCursorHight = mCursorBmp.getHeight();
        mTrunkMarginTop = dip2px(context, TRUNKMARGINTOP);
        mTextCursorSpace = dip2px(context, TEXT_CURSOR_SPACE);
        mCursorTextSize = sp2px(context, TEXTSIZE);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mClickTimeout = ViewConfiguration.getPressedStateDuration() + ViewConfiguration.getTapTimeout();
        mLineWidth = dip2px(context, LINEWIDTH);
        mPaint = new Paint();
        mPaint.setColor(Color.RED);// 设置红色
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(mCursorTextSize);
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        mTextHight = (int) (fontMetrics.descent - fontMetrics.ascent + 0.5f);
    }

    /**
     * 重写onDraw方法
     *
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mScaling = (getWidth() - getPaddingRight() - getPaddingLeft() - mCursorWidth)
                / (getXAxisEnd() - getXAxisStart());
        if (ISCENTERVERTICALTRUNK) {
            mTrunkMarginTop = (getHeight() - mTrunkHight) / 2.0f;
        }
        if (dstbmp != null)
            dstbmp.recycle();
        dstbmp = null;
        drawTrunk(canvas, mTrunkMarginTop);
        drawCursor(canvas);
    }


    /**
     * 绘制刻度条主干
     *
     * @param canvas
     */
    private void drawTrunk(Canvas canvas, float mTrunkMarginTop) {
        int leftbmp = getPaddingLeft();
        int topBoundary = (int) (mTrunkMarginTop + 0.5f);
        int widthbmp = getWidth() - getPaddingLeft() - getPaddingRight();
        float scaw = widthbmp * 1.0f / (mTrunkBmp.getWidth());
        matrix.setScale(scaw, 1.0f);

        /**
         * 绘制未选中的值刻度线
         */
        if (dstbmp == null)
            dstbmp = Bitmap.createBitmap(mTrunkBmp, 0, 0, mTrunkBmp.getWidth(), mTrunkBmp.getHeight(), matrix, true);
        canvas.drawBitmap(dstbmp, leftbmp, topBoundary, null);


        /**
         * 绘制选中的值刻度线
         */
        if (x - mXAxisStart >= 0 && mXAxisEnd - x >= 0) {
            scaw = (float) (getWidthForXValue() * 1.0f / mTrunkBmpDeep.getWidth());
        } else if (mXAxisEnd - x < 0) {
            scaw = (float) (getWidthForXValue() * 1.0f / mTrunkBmpDeep.getWidth());
        } else {
            scaw = mCursorWidth / 2.0f / mTrunkBmpDeep.getWidth();
        }
        float scaH = mTrunkBmp.getHeight() * 1.0f / mTrunkBmpDeep.getHeight();
        matrixDeep.setScale(scaw, scaH);
        Bitmap dstbmpdeep = Bitmap.createBitmap(mTrunkBmpDeep, 0, 0, mTrunkBmpDeep.getWidth(),
                mTrunkBmpDeep.getHeight(), matrixDeep, true);
        canvas.drawBitmap(dstbmpdeep, leftbmp, topBoundary, null);


        /**
         * 绘制起始值和结束值(isInteger保留整数,否则精度)
         */

        double tempX = getXForXvalue(mXAxisEnd);
        mPaint.setColor(getTrunkTextColor());
        String mEnd;
        if (isInteger) {//保持整形
            mEnd = String.valueOf((int) mXAxisEnd);
        } else {
            BigDecimal bd = new BigDecimal(mXAxisEnd);
            bd = bd.setScale(precision, BigDecimal.ROUND_HALF_DOWN);
            mEnd = String.valueOf(bd.doubleValue());
        }
        refitText(mEnd, computeMaxStringWidth(mEnd));
        canvas.drawText(mEnd, (float) tempX,
                mTrunkHight / 2.0f + mCursorHight + mTextHight + mTextHight / 2.0f,
                mPaint);


        String mStart;
        if (isInteger) {//保持整形
            mStart = String.valueOf((int) mXAxisStart);
        } else {
            BigDecimal bd = new BigDecimal(mXAxisStart);
            bd = bd.setScale(precision, BigDecimal.ROUND_HALF_UP);
            mStart = String.valueOf(bd.doubleValue());
        }
        double tempSX = getXForXvalue(mXAxisStart);
        mPaint.setColor(getTrunkTextColor());
        refitText(mStart, computeMaxStringWidth(mStart));
        canvas.drawText(mStart, (float) tempSX,
                mTrunkHight / 2.0f + mCursorHight + mTextHight + mTextHight / 2.0f,
                mPaint);

        /**
         * 绘制标记(起始位置和结束位置)
         */
        float lineW = (mLineWidth + 0.5f);
        float tempLSX = (float) getXForXvalue(mXAxisStart);
        mPaint.setColor(getTrunkTextColor());
        canvas.drawRect(tempLSX, mTrunkMarginTop, tempLSX + lineW, mTrunkMarginTop + mTrunkHight, mPaint);
        float tempLEX = (float) getXForXvalue(mXAxisEnd);
        mPaint.setColor(getTrunkTextColor());
        canvas.drawRect(tempLEX, mTrunkMarginTop, tempLEX + lineW, mTrunkMarginTop + mTrunkHight, mPaint);
    }

    /**
     * 绘制游标
     *
     * @param canvas
     */
    private void drawCursor(Canvas canvas) {

        /**
         * 绘制游标图片
         */
        canvas.drawBitmap(mCursorBmp, (int) (getXLocation() - mCursorWidth / 2.0f + 0.5f),
                (int) (mTrunkMarginTop + mTrunkHight / 2.0f - mCursorHight / 2.0f + 0.5f), null);

        /**
         * 绘制游标文字
         */

        if (isInteger) {//点差策略
            scrollValue = String.valueOf(((int) value));
        } else {
            BigDecimal bd = new BigDecimal(scrollValue);
            bd = bd.setScale(precision, BigDecimal.ROUND_HALF_UP);
            scrollValue = String.valueOf(bd.doubleValue());
        }
        mPaint.setColor(getCursorTextColor());
        refitText(scrollValue, computeMaxStringWidth(scrollValue));
        canvas.drawText(scrollValue, (int) (getXLocation() + 0.5f),
                (int) (mTrunkMarginTop - mCursorHight / 2.0f + mTrunkHight / 2.0f + 0.5f - mTextCursorSpace),
                mPaint);

    }


    /**
     * 设置游标图片
     */
    public void setCursorBmp(Bitmap mCursorBitmap) {
        this.mCursorBmp = mCursorBitmap;

    }

    /**
     * 设置刻度未选中图片
     */
    public void setTrunkBmp(Bitmap mTrunkBitmap) {
        this.mTrunkBmp = mTrunkBitmap;
    }


    /**
     * 设置刻度选中图片
     */
    public void setTrunkBmpDeep(Bitmap mTrunkBitmapDeep) {
        this.mTrunkBmpDeep = mTrunkBitmapDeep;
    }


    /**
     * isProfit=true(是止盈)
     */
    public void setIsProfit(boolean isProfit) {
        this.isProfit = isProfit;
    }


    /**
     * 根据止盈止损类型设置游标上的颜色值
     */
    public int getCursorTextColor() {
        return isProfit ? COLOR_PROFIT_TEXT : COLOR_LOSS_TEXT;
    }

    /**
     * 根据止盈止损类型设置刻度干上的颜色值
     */
    public int getTrunkTextColor() {
        return isProfit ? COLOR_PROFIT_LINE : COLOR_LOSS_LINE;
    }

    /**
     * X轴坐标终点
     *
     * @return
     */
    public double getXAxisEnd() {
        return mXAxisEnd;
    }

    /**
     * X轴坐标起点
     *
     * @return
     */
    public double getXAxisStart() {
        return mXAxisStart;
    }

    /**
     * 设置范围(最大值和最小值)
     *
     * @param mXAxisStart
     * @param mXAxisEnd
     */
    public void setValueScale(double mXAxisStart, double mXAxisEnd) {
        this.mXAxisStart = mXAxisStart;
        this.mXAxisEnd = mXAxisEnd;
    }


    /**
     * 设置游标位置(在屏幕位置).在初始化时调用
     *
     * @param x
     */
    public void setXValue(double x) {
        if (mXAxisStart != 0 || mXAxisEnd != 1)
            noSetX = false;
        this.x = x;
        this.scrollValue = String.valueOf(x);
        this.value = x;
    }

    public void setOnScrollListener(OnScrollListener onScrollListener) {
        this.onScrollListener = onScrollListener;
    }


    /**
     * 根据x在屏幕的像素点坐标计算实际x值
     *
     * @return
     */
    private double getXValueForPx(double xpx) {
        double d = (xpx - getPaddingLeft() - mCursorWidth / 2.0f) / mScaling + mXAxisStart;
        return d;
    }

    private double getXForXvalue(double xvalue) {
        int x = getPaddingLeft() + (int) ((xvalue - mXAxisStart) * mScaling + mCursorWidth / 2.0f + 0.5f);
        return x;
    }

    /**
     * 根据手机的分辨率从 dip 的单位 转成为 px(像素)
     */
    private int dip2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 将sp值转换为px值,保证文字大小不变
     *
     * @param spValue
     * @return
     */
    private int sp2px(Context context, float spValue) {
        final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }

    /**
     * 获取像素位置
     *
     * @return
     */
    public double getXLocation() {
        Paint.Align align = Paint.Align.LEFT;
        double px = getXForXvalue(x);
        if (noSetX) {
            px = align == Paint.Align.LEFT ? 0 : getWidth();
        }
        if (px <= getPaddingLeft() + mCursorWidth / 2.0f)
            px = getPaddingLeft() + mCursorWidth / 2.0f;
        if (px >= getWidth() - getPaddingRight() - mCursorWidth / 2.0f)
            px = getWidth() - getPaddingRight() - mCursorWidth / 2.0f;
        return px;
    }

    /**
     * 设置像素位置
     *
     * @param x
     */
    public void setXLocation(double x) {
        setXValue(getXValueForPx(x));
    }

    public float getTextSize() {
        return mCursorTextSize;
    }


    /**
     * 滑动接口
     */
    public interface OnScrollListener {
        /**
         * 返回游标上的字
         *
         * @param x
         * @return
         */

        String onScroll(double x);


    }

    public void setOnClickListener(OnClickListener onClickListener) {
        this.onClickListener = onClickListener;
    }

    public interface OnClickListener {
        String onClick(double x);
    }

    private double getWidthForXValue() {
        double strat = getXForXvalue(x);
        return strat != 0 && strat > 0 ? strat : 1;
    }

    float startX = 0;
    float startY = 0;
    boolean isClick = true;

    @SuppressLint("ClickableViewAccessibility")
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                getParent().requestDisallowInterceptTouchEvent(true);
                if ((Math.abs(event.getX() - x) <= mCursorWidth) && (getXValueForPx(event.getX()) <= mXAxisEnd &&
                        getXValueForPx(event.getX()) >= mXAxisStart)) {
                    setXLocation(event.getX());
                }
                startX = event.getRawX();
                startY = event.getRawY();
                isClick = true;
                break;
            case MotionEvent.ACTION_MOVE:
                float dx = event.getRawX() - startX;
                float dy = event.getRawY() - startY;
                if (onScrollListener != null) {
                    setXLocation(event.getX());
                    this.scrollValue = onScrollListener.onScroll(getXValueForPx(getXLocation()));
                    this.value = getXValueForPx(getXLocation());
                } else if (Math.abs(dx) > mTouchSlop || Math.abs(dy) > mTouchSlop) {
                    isClick = false;
                }
                break;
            case MotionEvent.ACTION_UP:
                double tempX = getXForXvalue(getXLocation());
                if (Math.abs(getXLocation() - tempX) <= mCursorWidth && (getXValueForPx(event.getX()) <= mXAxisEnd &&
                        getXValueForPx(event.getX()) >= mXAxisStart)) {
                    setXLocation(tempX);
                } else if (isClick && event.getEventTime() - event.getDownTime() < mClickTimeout) {
                    //作为点击事件操作
                    if (onClickListener != null) {
                        setXLocation(event.getX());
                        this.scrollValue = onClickListener.onClick(getXValueForPx(getXLocation()));
                        this.value = getXValueForPx(getXLocation());
                    }
                }
                break;
        }
        invalidate();
        return true;
    }


    /**
     * 当前游标所在位置
     *
     * @return
     */
    public double getValue() {
        return this.value;
    }


    /**
     * 当前刻度干的最大值
     *
     * @return
     */
    public double getMaxValue() {
        return this.mXAxisEnd;
    }


    /**
     * 当前刻度干的最小值
     *
     * @return
     */
    public double getMinValue() {
        return this.mXAxisStart;
    }

    /**
     * 增加参数(根据传入的策略类型,来设置精度)(百分比2个精度,点差不需要,价格根据instrument中的精度值设置)
     */
    public void setPrecision(int precision) {
        this.precision = (int) (Math.log(precision) / Math.log(10));
    }

    /**
     * 增加参数(设置类型)
     */
    public void setType(Boolean isInteger) {
        this.isInteger = isInteger;
    }


    /**
     * 获取当前字符的宽度(设置位置)
     */
    private int computeMaxStringWidth(String strings) {
        TextView textView = new TextView(getContext());
        textView.setText(strings);
        TextPaint paint = textView.getPaint();
        int widthText = (int) Layout.getDesiredWidth(strings, 0,
                strings.length(), paint);
        return widthText;
    }

    /**
     * 根据文字的宽度重新设置字体的大小(超过三个字符就缩小)
     *
     * @param text
     * @param textWidth
     */
    private void refitText(String text, int textWidth) {
        if (textWidth > 0) {
            float[] widths = new float[text.length()];
            Rect rect = new Rect();
            mPaint.getTextBounds(text, 0, text.length(), rect);
            int textWidths = rect.width();
            mCursorTextSize = this.getTextSize();
            while (textWidths > 48) {
                mCursorTextSize = mCursorTextSize - 1;
                mPaint.setTextSize(mCursorTextSize);
                textWidths = mPaint.getTextWidths(text, widths);
            }
            mPaint.setTextSize(mCursorTextSize);
        }
        invalidate();
    }
}

使用示例:

package com.example.administrator.myapplication;

import android.graphics.BitmapFactory;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.EditText;
import android.widget.TextView;

import java.text.NumberFormat;

public class MainActivity extends AppCompatActivity {
    private EditText content;
    private EditText content1;
    private CustomTakeValueArticle profitLimitScrollbar;
    private CustomTakeValueArticle lossLimitScrollbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView() {
        content = (EditText) findViewById(R.id.content);
        content1 = (EditText) findViewById(R.id.content1);
        profitLimitScrollbar = (CustomTakeValueArticle) findViewById(R.id.profit_limit_scrollbar);
        lossLimitScrollbar = (CustomTakeValueArticle) findViewById(R.id.loss_limit_scrollbar);
        initScrollbar();
        setScrollBarValue();
    }

    /**
     * 初始化Scrollbar相关配置参数
     */
    private void initScrollbar() {
        profitLimitScrollbar.setCursorBmp(BitmapFactory.decodeResource(getResources(), R.mipmap.red_cursor));
        profitLimitScrollbar.setTrunkBmp(BitmapFactory.decodeResource(getResources(), R.mipmap.cursor_line_red));
        profitLimitScrollbar.setTrunkBmpDeep(BitmapFactory.decodeResource(getResources(), R.mipmap.cursor_line_red_deep));
        profitLimitScrollbar.setIsProfit(true);
        profitLimitScrollbar.setOnScrollListener(new CustomTakeValueArticle.OnScrollListener() {
            @Override
            public String onScroll(double x) {
                changeScrollBarValue(x, content);
                return String.valueOf(x);
            }
        });
        profitLimitScrollbar.setOnClickListener(new CustomTakeValueArticle.OnClickListener() {
            @Override
            public String onClick(double x) {
                changeScrollBarValue(x, content);
                return String.valueOf(x);
            }
        });

        lossLimitScrollbar.setCursorBmp(BitmapFactory.decodeResource(getResources(), R.mipmap.blue_cursor));
        lossLimitScrollbar.setTrunkBmp(BitmapFactory.decodeResource(getResources(), R.mipmap.cursor_line_blue));
        lossLimitScrollbar.setTrunkBmpDeep(BitmapFactory.decodeResource(getResources(), R.mipmap.cursor_line_blue_deep));
        lossLimitScrollbar.setIsProfit(false);
        lossLimitScrollbar.setOnScrollListener(new CustomTakeValueArticle.OnScrollListener() {
            @Override
            public String onScroll(double x) {
                changeScrollBarValue(x, content1);
                return String.valueOf(x);

            }
        });
        lossLimitScrollbar.setOnClickListener(new CustomTakeValueArticle.OnClickListener() {
            @Override
            public String onClick(double x) {
                changeScrollBarValue(x, content1);
                return String.valueOf(x);
            }
        });
    }


    /**
     * 点击和滑动更新实时值
     *
     * @param x
     * @param limitValue
     */
    private void changeScrollBarValue(double x, TextView limitValue) {
        NumberFormat capitalNumberFormat;
        capitalNumberFormat = NumberFormat.getInstance();
        capitalNumberFormat.setMaximumFractionDigits(2);
        capitalNumberFormat.setMinimumFractionDigits(2);
        capitalNumberFormat.setGroupingUsed(false);
        NumberFormat mNumberFormat;
        mNumberFormat = NumberFormat.getInstance();
        mNumberFormat.setMaximumFractionDigits(0);
        mNumberFormat.setMinimumFractionDigits(0);
        mNumberFormat.setGroupingUsed(false);
        if (limitValue == content) {
            limitValue.setText(capitalNumberFormat.format(x));
        } else {
            limitValue.setText(mNumberFormat.format(x));
        }
    }

    /**
     * 设置ScrollBar相关数据参数
     */

    private void setScrollBarValue() {
        profitLimitScrollbar.invalidate();
        lossLimitScrollbar.invalidate();
        profitLimitScrollbar.setType(false);
        lossLimitScrollbar.setType(true);
        profitLimitScrollbar.setPrecision(2);
        profitLimitScrollbar.setXValue(50.02);
        content.setText("50.02");
        lossLimitScrollbar.setXValue(40);
        content1.setText("40");
        profitLimitScrollbar.setValueScale(0,
                120);
        lossLimitScrollbar.setValueScale(0,
                100);
    }
}

相关实现参数可根据需求在代码中修改!

效果图:
Android自定义View之滑动取值条_第1张图片

源码下载

你可能感兴趣的:(Android开发技术)