实现滑动标尺选择值,效果图

1.自定义属性attrs.xml

<declare-styleable name="RulerView"><attr name="textColor" format="color" /><attr name="textSize" format="dimension" /><attr name="lineColor" format="color" /><attr name="lineSpaceWidth" format="dimension" /><attr name="lineWidth" format="dimension" /><attr name="lineMaxHeight" format="dimension" /><attr name="lineMidHeight" format="dimension" /><attr name="lineMinHeight" format="dimension" /><attr name="textMarginTop" format="dimension" /><attr name="alphaEnable" format="boolean" /><attr name="minValue" format="float"/><attr name="maxValue" format="float"/><attr name="selectorValue" format="float"/><attr name="perValue" format="float"/></declare-styleable>

2.自定义RulerView

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.Scroller;public class RulerView extends View {private int mMinVelocity;private Scroller mScroller;  //Scroller是一个专门用于处理滚动效果的工具类   用mScroller记录/计算View滚动的位置,再重写View的computeScroll(),完成实际的滚动private VelocityTracker mVelocityTracker; //主要用跟踪触摸屏事件(flinging事件和其他gestures手势事件)的速率。private int mWidth;private int mHeight;private float mSelectorValue = 50.0f; // 未选择时 默认的值 滑动后表示当前中间指针正在指着的值private float mMaxValue = 200;        // 最大数值private float mMinValue = 100.0f;     //最小的数值private float mPerValue = 1;          //最小单位  如 1:表示 每2条刻度差为1.   0.1:表示 每2条刻度差为0.1// 在demo中 身高mPerValue为1  体重mPerValue 为0.1private float mLineSpaceWidth = 5;    //  尺子刻度2条线之间的距离private float mLineWidth = 4;         //  尺子刻度的宽度private float mLineMaxHeight = 420;   //  尺子刻度分为3中不同的高度。 mLineMaxHeight表示最长的那根(也就是 10的倍数时的高度)private float mLineMidHeight = 30;    //  mLineMidHeight  表示中间的高度(也就是 5  15 25 等时的高度)private float mLineMinHeight = 17;    //  mLineMinHeight  表示最短的那个高度(也就是 1 2 3 4 等时的高度)private float mTextMarginTop = 10;    //oprivate float mTextSize = 30;         //尺子刻度下方数字 textsizeprivate boolean mAlphaEnable = false;  // 尺子 最左边 最后边是否需要透明 (透明效果更好点)private float mTextHeight;            //尺子刻度下方数字  的高度private Paint mTextPaint;             // 尺子刻度下方数字( 也就是每隔10个出现的数值) paintprivate Paint mLinePaint;             //  尺子刻度  paintprivate int mTotalLine;               //共有多少条 刻度private int mMaxOffset;               //所有刻度 共有多长private float mOffset;                // 默认状态下,mSelectorValue所在的位置  位于尺子总刻度的位置private int mLastX, mMove;private OnValueChangeListener mListener;  // 滑动后数值回调private int mLineColor = Color.GRAY;   //刻度的颜色private int mTextColor = Color.BLACK;    //文字的颜色public RulerView(Context context) {this(context, null);}public RulerView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RulerView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}protected void init(Context context, AttributeSet attrs) {mScroller = new Scroller(context);this.mLineSpaceWidth = myfloat(25.0F);this.mLineWidth = myfloat(2.0F);this.mLineMaxHeight = myfloat(100.0F);this.mLineMidHeight = myfloat(60.0F);this.mLineMinHeight = myfloat(40.0F);this.mTextHeight = myfloat(40.0F);final TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.RulerView);mAlphaEnable = typedArray.getBoolean(R.styleable.RulerView_alphaEnable, mAlphaEnable);mLineSpaceWidth = typedArray.getDimension(R.styleable.RulerView_lineSpaceWidth, mLineSpaceWidth);mLineWidth = typedArray.getDimension(R.styleable.RulerView_lineWidth, mLineWidth);mLineMaxHeight = typedArray.getDimension(R.styleable.RulerView_lineMaxHeight, mLineMaxHeight);mLineMidHeight = typedArray.getDimension(R.styleable.RulerView_lineMidHeight, mLineMidHeight);mLineMinHeight = typedArray.getDimension(R.styleable.RulerView_lineMinHeight, mLineMinHeight);mLineColor = typedArray.getColor(R.styleable.RulerView_lineColor, mLineColor);mTextSize = typedArray.getDimension(R.styleable.RulerView_textSize, mTextSize);mTextColor = typedArray.getColor(R.styleable.RulerView_textColor, mTextColor);mTextMarginTop = typedArray.getDimension(R.styleable.RulerView_textMarginTop, mTextMarginTop);mSelectorValue = typedArray.getFloat(R.styleable.RulerView_selectorValue, 0.0f);mMinValue = typedArray.getFloat(R.styleable.RulerView_minValue, 0.0f);mMaxValue = typedArray.getFloat(R.styleable.RulerView_maxValue, 100.0f);mPerValue = typedArray.getFloat(R.styleable.RulerView_perValue, 0.1f);mMinVelocity = ViewConfiguration.get(getContext()).getScaledMinimumFlingVelocity();mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mTextPaint.setTextSize(mTextSize);mTextPaint.setColor(mTextColor);mTextHeight = getFontHeight(mTextPaint);mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);mLinePaint.setStrokeWidth(mLineWidth);mLinePaint.setColor(mLineColor);// setValue(1990, 1940, 2016, 1);}public static int myfloat(float paramFloat) {return (int) (0.5F + paramFloat * 1.0f);}private float getFontHeight(Paint paint) {Paint.FontMetrics fm = paint.getFontMetrics();return fm.descent - fm.ascent;}/*** @param selectorValue 未选择时 默认的值 滑动后表示当前中间指针正在指着的值* @param minValue      最大数值* @param maxValue      最小的数值* @param per           最小单位  如 1:表示 每2条刻度差为1.   0.1:表示 每2条刻度差为0.1 在demo中 身高mPerValue为1  体重mPerValue 为0.1*/public void setValue(float selectorValue, float minValue, float maxValue, float per) {this.mSelectorValue = selectorValue;this.mMaxValue = maxValue;this.mMinValue = minValue;this.mPerValue = (int) (per * 10.0f);this.mTotalLine = ((int) ((mMaxValue * 10 - mMinValue * 10) / mPerValue)) + 1;mMaxOffset = (int) (-(mTotalLine - 1) * mLineSpaceWidth);mOffset = (mMinValue - mSelectorValue) / mPerValue * mLineSpaceWidth * 10;invalidate();setVisibility(VISIBLE);}public void setOnValueChangeListener(OnValueChangeListener listener) {mListener = listener;}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);if (w > 0 && h > 0) {mWidth = w;mHeight = h;}}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);float left, height;String value;int alpha = 0;float scale;int srcPointX = mWidth / 2;for (int i = 0; i < mTotalLine; i++) {left = srcPointX + mOffset + i * mLineSpaceWidth;if (left < 0 || left > mWidth) {continue;  //  先画默认值在正中间,左右各一半的view。  多余部分暂时不画(也就是从默认值在中间,画旁边左右的刻度线)}/*文字*/if (i % 10 == 0) {value = String.valueOf((int) (mMinValue + i * mPerValue / 10));if (mAlphaEnable) {mTextPaint.setAlpha(alpha);}canvas.drawText(value, left - mTextPaint.measureText(value) / 2,mTextHeight, mTextPaint);    // 在为整数时,画 数值}/*线条*/if (i % 10 == 0) {height = mLineMinHeight;} else if (i % 5 == 0) {height = mLineMidHeight;} else {height = mLineMaxHeight;}if (mAlphaEnable) {scale = 1 - Math.abs(left - srcPointX) / srcPointX;alpha = (int) (255 * scale * scale);mLinePaint.setAlpha(alpha);}canvas.drawLine(left, mLineMaxHeight + mTextMarginTop + mTextHeight, left, height, mLinePaint);}}@Overridepublic 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();return false;default:break;}mLastX = xPosition;return true;}private void countVelocityTracker() {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);}}/*** 滑动结束后,若是指针在2条刻度之间时,改变mOffset 让指针正好在刻度上。*/private void countMoveEnd() {mOffset -= mMove;if (mOffset <= mMaxOffset) {mOffset = mMaxOffset;} else if (mOffset >= 0) {mOffset = 0;}mLastX = 0;mMove = 0;mSelectorValue = mMinValue + Math.round(Math.abs(mOffset) * 1.0f / mLineSpaceWidth) * mPerValue / 10.0f;mOffset = (mMinValue - mSelectorValue) * 10.0f / mPerValue * mLineSpaceWidth;notifyValueChange();postInvalidate();}/*** 滑动后的操作*/private void changeMoveAndValue() {mOffset -= mMove;if (mOffset <= mMaxOffset) {mOffset = mMaxOffset;mMove = 0;mScroller.forceFinished(true);} else if (mOffset >= 0) {mOffset = 0;mMove = 0;mScroller.forceFinished(true);}mSelectorValue = mMinValue + Math.round(Math.abs(mOffset) * 1.0f / mLineSpaceWidth) * mPerValue / 10.0f;notifyValueChange();postInvalidate();}private void notifyValueChange() {if (null != mListener) {mListener.onValueChange(mSelectorValue);}}/*** 滑动后的回调*/public interface OnValueChangeListener {void onValueChange(float value);}@Overridepublic void computeScroll() {super.computeScroll();if (mScroller.computeScrollOffset()) {     //mScroller.computeScrollOffset()返回 true表示滑动还没有结束if (mScroller.getCurrX() == mScroller.getFinalX()) {countMoveEnd();} else {int xPosition = mScroller.getCurrX();mMove = (mLastX - xPosition);changeMoveAndValue();mLastX = xPosition;}}}
}

3.xml中使用activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="fill_parent"android:gravity="center_horizontal"android:orientation="vertical"android:visibility="visible"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:includeFontPadding="false"android:maxHeight="17.0sp"android:text="身高(cm)"android:textColor="#cc222222"android:textSize="15.0sp" /><TextViewandroid:id="@+id/tv_info_height_value"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="11.0dip"android:includeFontPadding="false"android:maxHeight="24.0sp"android:textColor="#cc222222"android:textSize="24.0sp" /><RelativeLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"><com.demo.ruleview.RulerViewandroid:id="@+id/ruler_height"android:layout_width="fill_parent"android:layout_height="68.0dip"android:layout_marginTop="24.0dip"app:alphaEnable="true"app:lineColor="@color/gray"app:lineMaxHeight="40dp"app:lineMidHeight="30dp"app:lineMinHeight="20dp"app:lineSpaceWidth="10dp"app:lineWidth="2dip"app:maxValue="250.0"app:minValue="80.0"app:perValue="1"app:textColor="@color/black" /><ImageViewandroid:layout_width="14.0dip"android:layout_height="46.0dip"android:layout_centerHorizontal="true"android:layout_marginTop="40.0dip"android:scaleType="fitXY"android:src="@drawable/info_ruler" /></RelativeLayout><Buttonandroid:id="@+id/click"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="点击改变" /></LinearLayout>
</LinearLayout>

4.Activity中使用MainActivity

public class MainActivity extends AppCompatActivity {private int maxValue = 250;private int minValue = 80;private RulerView rulerHeight;private TextView tvHeightValue;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);rulerHeight = (RulerView) findViewById(R.id.ruler_height);tvHeightValue = (TextView) findViewById(R.id.tv_info_height_value);showNumInt();findViewById(R.id.click).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {showNumInt();}});rulerHeight.setOnValueChangeListener(new RulerView.OnValueChangeListener() {@Overridepublic void onValueChange(float value) {tvHeightValue.setText(String.valueOf(value));}});}private void showNumInt() {Random rand = new Random();int value = rand.nextInt(maxValue - minValue + 1) + minValue;rulerHeight.setValue(value, minValue, maxValue, 1);tvHeightValue.setText(String.valueOf(Integer.valueOf(value)));}
}

PS:可自行根据需要绘制线条和文字,上下选择文字位置

Android 自定义标尺滑动选择值相关推荐

  1. android自定义标尺,Android自定义标尺滑动选择值效果

    Android自定义标尺滑动选择值效果 发布时间:2020-10-16 07:40:15 来源:脚本之家 阅读:130 作者:676598624 本文实例为大家分享了Android实现滑动标尺选择值, ...

  2. 精通Android自定义View(五)自定义属性值使用详情

    1 可查看Android自定义View的基本使用 1 精通Android自定义View(一)自定义控的基本使用 2 精通Android自定义View(二)自定义属性使用详解 2 string 字符串 ...

  3. Android按钮滚动条,Android自定义Seekbar滑动条,Pop提示跟随滑动按钮一起滑动

    由于项目需要做出此效果,自定义写了一个. 效果图 思路: 原始的seekbar只有滑动条并没有下方的提示文字,所以我们必须要继承Seekbar重写这个控件. 代码: 在values文件夹下新建attr ...

  4. android身高控件_RuleView Android 自定义标尺控件(选择身高、体重等) @codeKK Android开源站...

    尺子刻度 -- 自定义 view 自定义 view 学习(第一章) 1.自定义刻度尺控件 在我们想要获取用户的身高体重等信息时,直接让他们输入显然不够友好偶然看到一款 App 用了类似刻度尺的界面让用 ...

  5. Android自定义日期区间选择,类似12306酒店入住的日期选择

    时间过的好快,一转眼2019年马上就结束了,在年末最后一天,写一篇与时间有关的文章吧,今天做一个日期区间的选择功能,效果类似一些酒店入住的日期选择,我写的这个类似12306上面的酒店入住日期选择效果, ...

  6. Android 自定义View 滑动解锁

    自定义view来绘制一个类似滑动解锁的button,注释都在,效果如下 代码在下面,替换一下资源,可以直接使用,如果需要画的是圆角的话,需要把下面两行注释的DrawLine的注释打开,然后把两行dra ...

  7. Android 自定义日期段选择控件,开始日期-结束日期。

    开发中碰到个需求,需要在一个控件中选择完成开始和结束日期.实现的过程走的是程序员开发的老路子,找到轮子后自己改吧改吧就成了.去年做的找不到参考的文章连接了,请原博主见谅. 当时做的时候有几个需求:1. ...

  8. Android自定义日期区间选择日期范围选则的日历,实现类似美团携程选择酒店入住日期和离店日期的日历效果

    前言 有时候我们会有需要在日历上选择一个日期范围的这种需求,先选一个开始日期,然后再选结束日期,如酒店入住日期和离店日期选择,美团携程这种预定酒店的app都有这种操作.那么这种需求该如何实现呢?先看一 ...

  9. android自定义标尺,Android 自定义 View 刻度尺

    项目地址: 简介:

  10. 精通Android自定义View(十四)绘制水平向右加载的进度条

    1引言 1 精通Android自定义View(一)View的绘制流程简述 2 精通Android自定义View(二)View绘制三部曲 3 精通Android自定义View(三)View绘制三部曲综合 ...

最新文章

  1. ipsec ***野蛮模式应用
  2. Android.mk 文件语法详解
  3. 开发笔记:掉落系统模块设计思路
  4. php异步传输,php 异步处理-上传文件
  5. 将5350 i2c clk设置为gpio 中断模式的方法
  6. SpringBoot项目@Email不起作用
  7. c语言宏定义_C语言宏定义
  8. spring案列——annotation配置
  9. 修炼!!!——超越项目经理
  10. 【MiniSTM32_HAL库版本_V1.0】实验1跑马灯代码解释(超详细,适合初识STM32的朋友)
  11. Axure使用教程(二)、动态面板
  12. HDU 6319 Problem A. Ascending Rating (单调队列)
  13. 《自控力》——[美]Kelly McGonigal
  14. 你是否希望大前端做服务器合租代管服务?
  15. 同仁堂-十大王牌、十大名药
  16. 本土英雄的退场和归来:Micromax教给了在印中国手机厂商哪些事?
  17. Apollo使用方法
  18. 免费小程序开发平台有哪些功能对零售超市行业有利?
  19. C++ map遍历删除的正确写法
  20. 电脑系统重装篇4:Windows 10 专业版安装步骤(UltraISO)

热门文章

  1. 数据库中常见mdf 、ndf 、ldf 、文件
  2. 极路由3C【C103B】刷breed再刷老毛子教程
  3. 申请ios证书并发布uniapp软件
  4. 关于protel 99se 汉化后某些菜单消失的解决方法
  5. 模拟信号的数字处理方法
  6. 关于CWMP基础(二)----TR069通信流程
  7. linux能解锁小米手机吗,【BL锁】还在为小米手机如何解锁及解锁后如何加锁而烦恼吗?...
  8. 印象笔记如何分享链接_【记录】试用印象笔记最新的笔记分享出页面的功能
  9. java xmpp即时通讯_Android基于Xmpp的即时通讯
  10. java web 和js区别_jsp和javascript之间有什么区别?