自定义刻度盘,用于显示一些界面效果,可实现1加减和0.5加减

主要代码如下,处女作,写得不好,多多体谅,基本功能都实现了,只是0.1加减的没有去弄,大家可以参考一下:
自定义刻度盘文件TuneWheel.java
/**
 * 类说明:自定义刻度盘
 * Author: gaobaiq
 * Date: 2016/8/8 10:39
 */
public class TuneWheel extends View {

    public static final int MOD_TYPE_HALF = 2;  // 0.5加减
    public static final int MOD_TYPE_ONE = 10;  // 1加减

    private static final int ITEM_HALF_DIVIDER = 20;    // 0.5加减刻度间隔
    private static final int ITEM_ONE_DIVIDER = 10;     // 1加减速刻度间隔

    private static final int ITEM_MAX_HEIGHT = 25;      // 满10刻度高度
    private static final int ITEM_MIN_HEIGHT = 15;      // 每一刻度高度
    private static final int ITEM_MIDDLE_HEIGHT = 30;   // 选中刻度高度

    private static final int TEXT_SIZE = 16;            // 文字大小

    private static final int INDEX_WIDTH = 1;           // 刻度宽度

    private float mDensity;
    private int mValue = 50;        // 选中值
    private int mMaxValue = 100;    // 最大值
    private int mModType = MOD_TYPE_HALF;
    private int mLineDivider = ITEM_HALF_DIVIDER;


    private int mLastX, mMove;
    private int mWidth, mHeight;

    private int mMinVelocity;
    private Scroller mScroller;
    private VelocityTracker mVelocityTracker;

    private OnValueChangeListener mListener;


    public TuneWheel(Context context) {
        this(context, null);
    }


    public TuneWheel(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }


    public TuneWheel(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

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

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

        setBackgroundDrawable(createBackground());
    }


    @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);
    }


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

        drawScaleLine(canvas);
        drawMiddleLine(canvas);
    }


    private GradientDrawable createBackground() {
        float strokeWidth = INDEX_WIDTH * mDensity; // 边框宽度
        float roundRadius = 0 * mDensity; // 圆角半径
        int strokeColor = Color.parseColor("#a3a3a3");// 边框颜色

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

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

        return bgDrawable;
    }

    /**
     * @param defaultValue    初始值
     * @param maxValue 最大值
     * @param model    刻度盘精度:<br>
     */
    public void initViewParam(int defaultValue, int maxValue, int model) {
        switch (model) {
            case MOD_TYPE_HALF:
                mModType = MOD_TYPE_HALF;
                mLineDivider = ITEM_HALF_DIVIDER;
                mValue = defaultValue * 2;
                mMaxValue = maxValue * 2;
                break;
            case MOD_TYPE_ONE:
                mModType = MOD_TYPE_ONE;
                mLineDivider = ITEM_ONE_DIVIDER;
                mValue = defaultValue;
                mMaxValue = maxValue;
                break;

            default:
                break;
        }
        invalidate();

        mLastX = 0;
        mMove = 0;
        notifyValueChange();
    }


    /**
     * 从中间往两边开始画刻度线
     *
     * @param canvas
     */
    private void drawScaleLine(Canvas canvas) {
        canvas.save();

        Paint linePaint = new Paint();
        linePaint.setStrokeWidth(INDEX_WIDTH);
        linePaint.setColor(Color.parseColor("#a3a3a3"));

        TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(Color.parseColor("#a3a3a3"));
        textPaint.setTextSize(TEXT_SIZE * mDensity);

        int width = mWidth, drawCount = 0;
        float xPosition = 0, textWidth = Layout.getDesiredWidth("0", textPaint);

        for (int i = 0; drawCount <= 4 * width; i++) {
            int numSize = String.valueOf(mValue + i).length();

            // 画右边
            xPosition = (width / 2 - mMove) + i * mLineDivider * mDensity;
            if (xPosition + getPaddingRight() < mWidth) {
                if ((mValue + i) % mModType == 0) {
                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint);

                    if (mValue + i <= mMaxValue) {
                        switch (mModType) {
                            case MOD_TYPE_HALF:
                                canvas.drawText(String.valueOf((mValue + i) / 2), countLeftStart(mValue + i, xPosition, textWidth), getHeight() - textWidth, textPaint);
                                break;
                            case MOD_TYPE_ONE:
                                canvas.drawText(String.valueOf(mValue + i), xPosition - (textWidth * numSize / 2), getHeight() - textWidth, textPaint);
                                break;

                            default:
                                break;
                        }
                    }
                } else {
                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint);
                }
            }

            // 画左边
            xPosition = (width / 2 - mMove) - i * mLineDivider * mDensity;
            if (xPosition > getPaddingLeft()) {
                if ((mValue - i) % mModType == 0) {
                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MAX_HEIGHT, linePaint);

                    if (mValue - i >= 0) {
                        switch (mModType) {
                            case MOD_TYPE_HALF:
                                canvas.drawText(String.valueOf((mValue - i) / 2), countLeftStart(mValue - i, xPosition, textWidth), getHeight() - textWidth, textPaint);
                                break;
                            case MOD_TYPE_ONE:
                                canvas.drawText(String.valueOf(mValue - i), xPosition - (textWidth * numSize / 2), getHeight() - textWidth, textPaint);
                                break;

                            default:
                                break;
                        }
                    }
                } else {
                    canvas.drawLine(xPosition, getPaddingTop(), xPosition, mDensity * ITEM_MIN_HEIGHT, linePaint);
                }
            }

            drawCount += 2 * mLineDivider * mDensity;
        }

        canvas.restore();
    }

    /**
     * 计算没有数字显示位置的辅助方法
     *
     * @param value
     * @param xPosition
     * @param textWidth
     * @return
     */
    private float countLeftStart(int value, float xPosition, float textWidth) {
        float xp = 0f;
        if (value < 20) {
            xp = xPosition - (textWidth * 1 / 2);
        } else {
            xp = xPosition - (textWidth * 2 / 2);
        }
        return xp;
    }

    /**
     * 画中间的红色指示线、阴影等。指示线两端简单的用了两个矩形代替
     *
     * @param canvas
     */
    private void drawMiddleLine(Canvas canvas) {

        canvas.save();

        Paint redPaint = new Paint();
        redPaint.setStrokeWidth(INDEX_WIDTH);
        redPaint.setColor(Color.RED);
        canvas.drawLine(mWidth / 2, 0, mWidth / 2, mDensity * ITEM_MIDDLE_HEIGHT,
                redPaint);

        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));
        Log.w("Wheel", tValue + "");
        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) {
            if (mModType == MOD_TYPE_ONE) {
                mListener.onValueChange(mValue);
            }
            if (mModType == MOD_TYPE_HALF) {
                mListener.onValueChange(mValue / 2f);
            }
        }
    }


    @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;
            }
        }
    }


    public void changeValue(int step) {
        int roundMove = Math.round(mMove / (mLineDivider * mDensity));
        mValue = mValue + step + roundMove;
        mValue = mValue <= 0 ? 0 : mValue;
        mValue = mValue > mMaxValue ? mMaxValue : mValue;
        mLastX = 0;
        mMove = 0;
        notifyValueChange();
        postInvalidate();
    }


    /**
     * 获取当前刻度值
     *
     * @return
     */
    public int getValue() {
        return mValue;
    }


    /**
     * 接收结果事件
     * */
    public interface OnValueChangeListener {
        void onValueChange(float value);
    }


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

<!-- 布局文件 activity_bmi_main.xml-->
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:toolbar="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorBackground"
    android:orientation="vertical"
    tools:context=".ui.customised.widget.BMIMainActivity">

    <com.qicloud.dashenlin.widget.toolbar.BaseBar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="@dimen/toolbar_height"
        toolbar:is_left="true"
        toolbar:left_icon="@drawable/icon_left"/>
    

    <ScrollView android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <View android:layout_width="match_parent"
                android:layout_height="@dimen/line_height"
                android:background="@color/colorSubTitle"/>

            <LinearLayout android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:background="@color/white"
                android:gravity="center_horizontal"
                android:layout_marginTop="@dimen/view_padding">

                <TextView android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/text_padding"
                    android:textColor="@color/colorTitle"
                    android:textSize="@dimen/micro_text_size"
                    android:text="身高:"/>


                <TextView
                    android:id="@+id/tv_height"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/text_padding"
                    android:textColor="@color/green_25ab38"
                    android:textSize="@dimen/large_text_size"
                    android:text="174CM"/>


                <com.qicloud.dashenlin.widget.customview.TuneWheel
                    android:id="@+id/wheel_height"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/scale_height"
                    android:layout_marginTop="@dimen/text_padding"
                    android:layout_marginBottom="@dimen/layout_margin"
                    android:layout_marginLeft="@dimen/text_padding"
                    android:layout_marginRight="@dimen/text_padding"/>

            </LinearLayout>


            <View android:layout_width="match_parent"
                android:layout_height="@dimen/line_height"
                android:background="@color/colorSubTitle"/>

            <View android:layout_width="match_parent"
                android:layout_height="@dimen/line_height"
                android:layout_marginTop="@dimen/layout_margin"
                android:background="@color/colorSubTitle"/>

            <LinearLayout android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:background="@color/white"
                android:gravity="center_horizontal">

                <TextView android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/text_padding"
                    android:textColor="@color/colorTitle"
                    android:textSize="@dimen/micro_text_size"
                    android:text="体重:"/>


                <TextView
                    android:id="@+id/tv_weight"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="@dimen/text_padding"
                    android:textColor="@color/green_25ab38"
                    android:textSize="@dimen/large_text_size"
                    android:text="62.5KG"/>


                <com.qicloud.dashenlin.widget.customview.TuneWheel
                    android:id="@+id/wheel_weight"
                    android:layout_width="match_parent"
                    android:layout_height="@dimen/scale_height"
                    android:layout_marginTop="@dimen/text_padding"
                    android:layout_marginBottom="@dimen/layout_margin"
                    android:layout_marginLeft="@dimen/text_padding"
                    android:layout_marginRight="@dimen/text_padding"/>

            </LinearLayout>


            <View android:layout_width="match_parent"
                android:layout_height="@dimen/line_height"
                android:background="@color/colorSubTitle"/>

            <TextView android:layout_width="match_parent"
                android:layout_height="@dimen/large_btn_height"
                android:background="@drawable/btn_green_selector"
                android:layout_margin="@dimen/layout_margin"
                android:gravity="center"
                android:textSize="@dimen/small_text_size"
                android:textColor="@color/white"
                android:text="马上计算"/>


            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/text_padding"
                android:layout_marginRight="@dimen/text_padding"
                android:textColor="@color/colorTitle"
                android:textSize="@dimen/medium_text_size"
                android:text="BMI科普:"/>


            <TextView
                android:id="@+id/tv_bmi_intro"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="@dimen/text_padding"
                android:layout_marginRight="@dimen/text_padding"
                android:layout_marginTop="@dimen/text_padding"
                android:lineSpacingExtra="@dimen/text_padding"
                android:textColor="@color/colorTitle"
                android:textSize="@dimen/micro_text_size"
                android:text="@string/customised_bmi_intro"/>


        </LinearLayout>

    </ScrollView>


</LinearLayout>

 

调用方法

/**
 * 类说明:BMI计算首页
 * Author: gaobaiq
 * Date: 2016/8/8 10:30
 */
public class BMIMainActivity extends BaseActivity {

    @Bind(R.id.tv_height)
    TextView mTvHeight;
    @Bind(R.id.wheel_height)
    TuneWheel mWheelHeight;
    @Bind(R.id.tv_weight)
    TextView mTvWeight;
    @Bind(R.id.wheel_weight)
    TuneWheel mWheelWeight;
    @Bind(R.id.tv_bmi_intro)
    TextView mTvBmiIntro;

    private int heightValue = 175;  // 身高
    private int weightValue = 62;   // 体重


    @Override protected int initLayout() {
        return R.layout.activity_bmi_main;
    }


    @Override protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initViewAndData();
    }


    @Override protected BasePresenter initPresenter() {
        return null;
    }


    public static void openActivity(Context context) {
        context.startActivity(new Intent(context, BMIMainActivity.class));
    }


    private void initViewAndData() {
        mWheelHeight.initViewParam(50, 240, TuneWheel.MOD_TYPE_ONE);
        mWheelHeight.setValueChangeListener(new TuneWheel.OnValueChangeListener() {
            @Override
            public void onValueChange(float value) {
                heightValue = (int) value;
                mTvHeight.setText(String.valueOf(value) + "CM");
            }
        });


        mWheelWeight.initViewParam(60, 240, TuneWheel.MOD_TYPE_HALF);
        mWheelWeight.setValueChangeListener(new TuneWheel.OnValueChangeListener() {
            @Override
            public void onValueChange(float value) {
                weightValue = (int) value;
                mTvWeight.setText(String.valueOf(value) + "KG");
            }
        });
    }
 

转载于:https://www.cnblogs.com/gaobaiq/p/5750049.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值