自定义刻度盘,用于显示一些界面效果,可实现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");
            }
        });
    }
				
时间: 2024-10-05 14:48:54

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

用于显示上个月和下个月_PHP

/** * 用于显示上个月和下个月 * @param int $sign 1:表示上个月 0:表示下个月 * @return string */ function GetMonth($sign="1"){ //得到系统的年月 $tmp_date=date("Ym"); //切割出年份 $tmp_year=substr($tmp_date,0,4); //切割出月份 $tmp_mon =substr($tmp_date,4,2); $tmp_nextmonth=mkt

登录界面、AutoUtils 屏幕适配、自定义Edittext(显示密码可见和一键清空)和 TextInputLayout的使用。

登录界面: AutoUtils自动屏幕适配: AutoUtils屏幕适配使用的方法 : 1.将AutoUtils类复制到要适配的项目中: 2.在程序的入口(清单文件filter):super.onCreate(savedInstanceState);//屏幕适配,这里是以720*1280分辨率为基准的适配AutoUtils.setSize(this, false, 720, 1280); * 这里我们UI是以1920*1280分辨率做图的,并且是横屏显示:AutoUtils.setSize(th

[ jquery 效果 show([speed,[easing],[fn]]) hide([speed,[easing],[fn]]) ] 此方法用于显示隐藏的被选元素:show() 适用于通过 jQuery 方法和 CSS 中 display:none type=&#39;hidden&#39; 隐藏的元素(不适用于通过 visibility:hidden 隐藏的元素)

show()显示隐藏的被选元素:show() 适用于通过 jQuery 方法和 CSS 中 display:none type='hidden' 隐藏的元素(不适用于通过 visibility:hidden 隐藏的元素): hide() 方法隐藏被选元素: 参数 描述 speed 可选.规定显示效果的速度. 可能的值: 毫秒 "slow" "fast" easing 可选.规定在动画的不同点上元素的速度.默认值为 "swing". 可能的值: &

JavaScript之jQuery-5 jQuery 动画效果(隐藏和显示、自定义动画、并发与排列效果)

一.jQuery 隐藏和显示 基本显示.隐藏效果 - show() / hide() - 作用: 通过同时改变元素的宽度和高度来实现显示或隐藏 - 用法: $obj.show(执行时间,回调函数); 执行时间:slow,normal,fast或毫秒数 回调函数:动画执行完毕之后要执行的函数 滑动式动画效果 - slideDown() / slideUp() - 作用: 通过改变高度来实现显示或者隐藏的效果 - 用法同 show() / hidden() 淡入淡出式动画效果 - fadeIn()

Windows界面编程第十二篇 位图显示特效 飞入效果与伸展效果

分享一下我老师大神的人工智能教程吧.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!http://www.captainbed.net 转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/8696726 欢迎关注微博:http://weibo.com/MoreWindows Windows界面编程之位图显示特效系列目录: 1. <Windows界面编程第九篇位图显示特效交错效果> http:/

Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果

首先我们先看第一个界面吧,使用将手机中的图片扫描出来,然后根据图片的所在的文件夹将其分类出来,并显示所在文件夹里面的一张图片和文件夹中图片个数,我们根据界面元素(文件夹名, 文件夹图片个数,文件夹中的一张图片)使用一个实体对象ImageBean来封装这三个属性 package com.example.imagescan; /** * GridView的每个item的数据对象 * * @author len * */ public class ImageBean{ /** * 文件夹的第一张图片路

通过自定义样式优化博客界面

园子里的模板非常丰富,但距自己的期望,总是差一点点.加上我使用的是Windows Live Writer 2009写博客(2011的某些功能我无法接受,退回到习惯的旧版),所以写博客快则快矣,界面就有点不忍直视了.如前两天写的一篇博文: 无论是标题,还是各级子标题.代码.例子,布局,感觉都是乱糟糟的,打开页面,实在没有阅读下去的兴趣. 于是研究了一下究竟怎样来优化博客界面,对以下方面进行了修改: 每个段落加上首行缩进 标题.子标题样式修改 代码样式修改 增加阅读目录 增加回到顶部 最后的结果好多

Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果

大家好!过完年回来到现在差不多一个月没写文章了,一是觉得不知道写哪些方面的文章,没有好的题材来写,二是因为自己的一些私事给耽误了,所以过完年的第一篇文章到现在才发表出来,2014年我还是会继续在CSDN上面更新我的博客,欢迎大家关注一下,今天这篇文章主要的是介绍下开源库StickyGridHeaders的使用,StickyGridHeaders是一个自定义GridView带sections和headers的Android库,sections就是GridView item之间的分隔,headers

App启动界面效果设计

转载请标明出处:http://blog.csdn.net/u012637501/article/details/45746617 每个Android应用启动之后都会出现一个Splash启动界面,大多数的Splash界面都是会等待一定时间,然后切换到下一个界面.但如果app启动时间过长,可使用启动界面让用户耐心等待这段枯燥的时间.Splash界面一般用于显示产品的LOGO.产品名称.版本信息等,也可以完成对系统状况的检测,如网络是否连通.电源是否充足.检测新版本等,也可以预先加载相关数据.启动界面