主要代码如下,处女作,写得不好,多多体谅,基本功能都实现了,只是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"); } }); }
时间: 2024-10-05 14:48:54