android 带刻度的滑动条_Android自定义控件尺子 滚动刻度尺
自定义控件是件很有乐趣的事,慢慢的会爱上它,哈哈哈。废话不多说先上设计图
接下来我们我们要先分析一下页面中需要到哪些东西
1.一条无限长的底线;
2.一根在屏幕中间的红色标记线,代表当前位置;
3.一个半透明的蓝色背景,改背景超过部分才会被展现;
4.刻度 整数高一点刻度 非整第一点的刻度
5.一个大刻度上都会标的数值
6.滚动
接下来进入正题,让我们开始绘制:
首先我们先给控件定义它的属性,根据刚才的分析我给他定义了一下的属性
接下来在控件的构造方法中获取这些值,里面还涉及到一些需要初始化的值都有备注
public RulerView(Context context, AttributeSet attrs) {
super(context, attrs);
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(dm);
screenWidth = dm.widthPixels;
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RulerView);
maxValue = typedArray.getDimensionPixelOffset(R.styleable.RulerView_max_value, 200000);
minValue = typedArray.getDimensionPixelOffset(R.styleable.RulerView_min_value, 0);
scaleTextSize = typedArray.getDimensionPixelOffset(R.styleable.RulerView_scale_text_size, 24);
scaleTextColor = typedArray.getColor(R.styleable.RulerView_scale_text_color, Color.parseColor("#d8d8d8"));
scaleSelectColor = typedArray.getColor(R.styleable.RulerView_scale_select_color, Color.parseColor("#76e4ff"));
scaleSelectBackgroundColor = typedArray.getColor(R.styleable.RulerView_scale_select_background_color, Color.parseColor("#6676e4ff"));
scaleUnSelectColor = typedArray.getColor(R.styleable.RulerView_scale_unselect_color, Color.parseColor("#d8d8d8"));
cursorColor = typedArray.getColor(R.styleable.RulerView_tag_color, Color.parseColor("#ff5555"));
if (currLocation == 0) {
currLocation = typedArray.getDimensionPixelOffset(R.styleable.RulerView_start_location, 0);
}
showItemSize = typedArray.getInteger(R.styleable.RulerView_show_item_size, 5);
oneItemValue = typedArray.getInteger(R.styleable.RulerView_show_item_size, 1000);
typedArray.recycle();
//一个刻度的宽度
scaleWidth = (screenWidth / (showItemSize * 10));
//尺子长度总的个数*一个的宽度
viewWidth = maxValue / oneItemValue * scaleWidth;
//滚动计算器
scroller = new Scroller(context);
//手势解析器
gestureDetector = new GestureDetector(context, gestureListener);
gestureDetector.setIsLongpressEnabled(false);
}
我们先从简单的开始画一条在底部的线,那问题来了这个View底部坐标在哪里呢?不用担心View有个onMeasure方法,在里面我们可以直接获取到View的高度
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
viewHeight = MeasureSpec.getSize(heightMeasureSpec);
}
private void drawBottomLine(Canvas canvas) {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(3);
paint.setColor(scaleUnSelectColor);
canvas.drawLine(0, viewHeight, viewWidth, viewHeight, paint);
}
绘制刻度以及刻度值,以及超过时的颜色
private void drawScale(Canvas canvas) {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(2);
//计算游标开始绘制的位置
float startLocation = (screenWidth / 2) - ((scaleWidth * (currLocation / oneItemValue)));
for (int i = 0; i < maxValue / oneItemValue; i++) {
//判断当前刻度是否小于当前刻度
if (i * oneItemValue <= currLocation) {
paint.setColor(scaleSelectColor);
} else {
paint.setColor(scaleUnSelectColor);
}
float location = startLocation + i * scaleWidth;
if (i % 10 == 0) {
canvas.drawLine(location, viewHeight - scaleHeight, location, viewHeight, paint);
paintText = new Paint(Paint.ANTI_ALIAS_FLAG);
paintText.setTextSize(scaleTextSize);
if (i * oneItemValue <= currLocation) {
paintText.setColor(scaleSelectColor);
} else {
paintText.setColor(scaleTextColor);
}
String drawStr = oneItemValue * i + "";
Rect bounds = new Rect();
paintText.getTextBounds(drawStr, 0, drawStr.length(), bounds);
canvas.drawText(drawStr, location - bounds.width() / 2, viewHeight - (scaleHeight + 5), paintText);
} else {
canvas.drawLine(location, viewHeight - scaleHeight / 2, location, viewHeight, paint);
}
//绘制选中的背景
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(scaleSelectBackgroundColor);
canvas.drawRect(startLocation, viewHeight - scaleHeight / 3, startLocation + currLocation / oneItemValue * scaleWidth, viewHeight, paint);
}
}
最后绘制一条中线
private void drawCursor(Canvas canvas) {
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeWidth(3);
paint.setColor(cursorColor);
canvas.drawLine(screenWidth / 2, viewHeight / 5, screenWidth / 2, viewHeight, paint);
}
上面的方法都要在View的onDraw方法中调用一遍,这样刻度尺就绘制完成了。最后我们的工作就是让刻度尺跟着我们的手指动起来,直接重写onTouchEvent方法将所有事件交给手势处理器来处理然后重写onScroll(滚动),onFling(抛事件)方法
@Override
public boolean onTouchEvent(MotionEvent event) {
gestureDetector.onTouchEvent(event);
return true;
}
private GestureDetector.SimpleOnGestureListener gestureListener = new GestureDetector.SimpleOnGestureListener() {
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
if (!isScrollingPerformed) {
isScrollingPerformed = true;
}
doScroll((int) -distanceX);
invalidate();
return true;
}
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
lastScrollX = getCurrentItem() * getItemWidth() + scrollingOffset;
int maxX = getItemsCount()
* getItemWidth();
int minX = 0;
scroller.fling(lastScrollX, 0, (int) (-velocityX / 1.5), 0, minX, maxX, 0, 0);
setNextMessage(MESSAGE_SCROLL);
return true;
}
};
private void doScroll(int delta) {
//偏移量叠加
scrollingOffset += delta;
//总共滚动了多少个Item
int count = scrollingOffset / getItemWidth();
//当前位置
int pos = getCurrentItem() - count;
//限制滚到范围
if (isScrollingPerformed) {
if (pos < 0) {
count = getCurrentItem();
pos = 0;
} else if (pos >= getItemsCount()) {
count = getCurrentItem() - getItemsCount() + 1;
pos = getItemsCount() - 1;
}
}
int offset = scrollingOffset;
//移动了一个Item的距离,就更新页面
if (pos != getCurrentItem()) {
setCurrentItem(pos);
}
// 重新更新一下偏移量
scrollingOffset = offset - count * getItemWidth();
}
public int getItemWidth() {
return scaleWidth;
}
public int getCurrentItem() {
return currLocation / oneItemValue;
}
public int getItemsCount() {
return maxValue / oneItemValue;
}
public void setCurrentItem(int index) {
scrollingOffset = 0;
currLocation = index * oneItemValue;
invalidate();
if (onRulerChangeListener != null) {
onRulerChangeListener.onChanged(currLocation);
}
}
private void setNextMessage(int message) {
animationHandler.removeMessages(MESSAGE_SCROLL);
animationHandler.sendEmptyMessage(message);
}
// 动画处理
private Handler animationHandler = new Handler() {
public void handleMessage(Message msg) {
scroller.computeScrollOffset();
int currX = scroller.getCurrX();
int delta = lastScrollX - currX;
lastScrollX = currX;
if (delta != 0) {
doScroll(delta);
}
// 滚动还没有完成,到最后,完成手动
if (Math.abs(currX - scroller.getFinalX()) < MIN_DELTA_FOR_SCROLLING) {
scroller.forceFinished(true);
}
if (!scroller.isFinished()) {
animationHandler.sendEmptyMessage(msg.what);
} else {
finishScrolling();
}
}
};
private void finishScrolling() {
if (isScrollingPerformed) {
isScrollingPerformed = false;
}
invalidate();
}
最后上一张效果图
源码地址:http://download.csdn.net/detail/fengzhongdeyang/9638371
android 带刻度的滑动条_Android自定义控件尺子 滚动刻度尺相关推荐
- android 带刻度的滑动条_Android实现滑动刻度尺效果
最近群里的开发人员咨询怎样实现刻度尺的滑动效果去选择身高体重等信息.给个横着的效果,自己试着去改编或者修改一下,看看通过自己的能力能不能做出竖着的效果来,过两天我再把竖着的那个滑动选择效果分享出来.废 ...
- android 带刻度的滑动条_android 滚轮刻度尺的实现
遇到一个需求需要实现如下图的效果: 卷尺,通过左右滑动来选择不同的刻度值.这方面的东西以前没弄过,以目前你的能力,想了几种思路都死在了半路上.比如上面的刻度线如何弄,滑动的时候又该如何弄:下面的数字又 ...
- lvgl如何用单向直线触摸滑动条模拟编码器的滚动操作,请注意,单向触摸滑动条是一个输入外设,是一个硬件,而并非lvgl内置的滑条控件...
LVGL可以通过监听单向触摸滑动条的输入事件,并在触摸滑动条的值变化时进行相应的操作,从而模拟编码器的滚动操作.具体的实现方法如下: 初始化单向触摸滑动条:在初始化时,要确保单向触摸滑动条处于正常工作 ...
- android自定义滚轴选择器_Android自定义控件实战—滚动选择器PickerView
手机里设置闹钟需要选择时间,那个选择时间的控件就是滚动选择器,前几天用手机刷了MIUI,发现自带的那个时间选择器效果挺好看的,于是就自己仿写了一个,权当练手.先来看效果: 效果还行吧?实现思路就是自定 ...
- Android 带文字的进度条,文字颜色随进度条的增加而渐变的效果
Android自带的ProgressBar是不带文字的,加文字的话可以参考这篇博客:http://blog.csdn.net/lixiaodaoaaa/article/details/9852327 ...
- android开发歌词滑动效果_Android 歌词同步滚动效果
歌词是播放器类App必不可少的组件,而一般的歌词组件都需要做到歌词的显示与播放进度同步.我们知道,歌词是如下所示的文件: lrc [ti:原来爱情这么伤] [ar:梁咏琪] [al:给自己的情歌] [ ...
- Android ScrollView去掉右侧滑动条
<ScrollView ......android:scrollbars="none"><!--添加代码-->
- 疯狂JAVA讲义---第十二章:Swing编程(五)进度条和滑动条
http://blog.csdn.net/terryzero/article/details/3797782 疯狂JAVA讲义---第十二章:Swing编程(五)进度条和滑动条 标签: swing编程 ...
- wdatepicker设置初始时间_滑动条的滑块的初始位置应该放在哪儿?
滑动条(slider question)是网络调查中独有的一种题型,它由一个有刻度的轴和一个可在轴上来回拖动的滑块组成.受访者在PC或手机屏幕上,通过鼠标或者手指将滑块移动至轴上相应的位置,来完成答题 ...
最新文章
- python的numpy(array)
- Unity C#单例模式的实现
- PHP Warning: date(): It is not safe to rely on the system's timezone settings
- 吴恩达 coursera ML 第十课总结+作业答案
- commit分拆多个 git_这才是真正的Git——Git内部原理
- tornado基本使用一
- 浅谈 js 数字格式类型
- 『力荐汇总』这些 VS Code 快捷键太好用,忍不住录了这34张gif动图
- 8.程序员的自我修养---动态链接
- win7+nfs文件服务器,win7如何挂载nfs服务器
- 微信小程序实现图片懒加载
- 蓝牙耳机哪个音质好?推荐几款音质好的蓝牙耳机
- 海信电视 android,海信聚好看app下载 海信聚好看(电视微助手) for Android V5.7.0.9 安卓手机版 下载-脚本之家...
- 网传固态硬盘因为TRIM指令一经删除无法恢复是以讹传讹
- IoT黑板报0209:工信部明确增加物联网网号
- python selenium爬虫自动登录实例
- Vin码查询车辆详细信息
- 单向链表和双向链表的优缺点及使用场景
- 联想笔记本电脑开机黑屏可能是什么原因
- CoreData基础
热门文章
- Digilent Basys2开发板驱动安装失败
- 一个菜鸟的Linux起步 课程第一节:linux基础与命令介绍
- vue表单验证自定义验证规则
- Fusion360学习记录:螺丝螺帽
- python修改列表元素_python 3 基础之列表和列表添加元素、修改元素、查找元素、删除元素、排序、嵌套、取最值...
- Python我的世界小游戏源代码
- css制作3D立体旋转效果
- 制作Wi-Fi Ducky远程HID攻击设备
- Go游戏服务器开发的一些思考(三十):排行榜服务器设计思路
- Windows10为什么无法将文件命名为aux,com1,com2,prn,con,nul等?