2019独角兽企业重金招聘Python工程师标准>>>

首先来张截图:

控件的外观可能不是很美观,不过功能基本都有了,可以自己设置选中的时间片段,暂时没有支持自定义样式。。。

接下来介绍如何实现这个控件。

首先要先知道android' view的绘制过程,首先的view先计算Measure,然后在进行Layout,最后Draw。那view的坐标系为左上角(0,0),

图片网络的:

那么在view上面画一些简单的图形的时候,也是根据这个坐标来绘制,如果你的画的图形超过了屏幕,就需要的移动view才能看见。因为view的本身是没有边界的,Canvas对象本身也是没有边界的。view的本身有两个函数scrollTo和scrollBy函数,可以用来移动view到自定义的位置。自己新建一个按钮,点击事件调用这两个函数的时候,可以看到按钮上的字移动,因为函数本身是view的移动,对于view的内容来说就是,坐标改变了。那么也就是说要实现时间刻度的效果,就是在屏幕上绘制一条很长的时间刻度,然后根据手指的移动,调用scrollTo或者scrollBy来移动view,对于里面的内容就是看起来移动了。

对于直接调用scrollTo或者scrollBy来移动view显得有点生硬,没有平滑的效果,所以要引入Scroller类来辅助处理滑动,不过还有一个加速度的类可以实现移动带有弹性的效果,不过现在暂时没有用到。对于Scroller类可以上网查查资料,是一个辅助类,可以计算出view移动的距离,并且计算出移动距离的平滑的点。使用方法比较简单。

scroller = new Scroller(context);

介绍一下computeScroll,computeScroll()是View类的一个空函数,在view需要重新绘制的时候,会调用computeScroll函数,那么在computeScroll可以调用scrollTo或者scrollBy传入Scroller的坐标,再重新绘制view就可以实现view的滚动。

 @Overridepublic void computeScroll() {super.computeScroll();if (scroller.computeScrollOffset()) {scrollTo(scroller.getCurrX(), scroller.getCurrY());invalidate();}}

view的重新绘制可以调用invalidate和postInvalidate 函数来通知系统重新绘制该view,前者要在ui线程里调用,后者可以在非ui线程里面调用。

接下来要重新写触摸事件:

@Overridepublic boolean onTouchEvent(MotionEvent event) {float x = event.getX();switch (event.getAction()) {case MotionEvent.ACTION_DOWN:if (scroller != null && !scroller.isFinished()) {scroller.abortAnimation();}lastX = x;return true;case MotionEvent.ACTION_MOVE:float dataX = lastX - x;int finalx = scroller.getFinalX();//右边if (dataX < 0) {if (finalx < -viewWidth / 2) {return super.onTouchEvent(event);}}if (dataX > 0) {if (finalx > timeScale * 21) {return super.onTouchEvent(event);}}/**对于这里调用startScroll函数,就是从某个点移动一段距离,这里传入scroller.getFinalX(), scroller.getFinalY()的原因是,获取的点都是手指移动的点*/scroller.startScroll(scroller.getFinalX(), scroller.getFinalY(), (int) dataX, 0);lastX = x;postInvalidate();return true;case MotionEvent.ACTION_UP:int finalx1 = scroller.getFinalX();if (finalx1 < -viewWidth / 2) {scroller.setFinalX(-viewWidth / 2);}if (finalx1 > timeScale * 21) {scroller.setFinalX(timeScale * 21);}if (scrollListener != null) {int finalX = scroller.getFinalX();//表示每一个屏幕刻度的一半的总秒数,每一个屏幕有6格int sec = 3 * 3600;//滚动的秒数int temsec = (int) Math.rint((double) finalX / (double) timeScale * 3600);sec += temsec;//获取的时分秒int thour = sec / 3600;int tmin = (sec - thour * 3600) / 60;int tsec = sec - thour * 3600 - tmin * 60;scrollListener.onScrollFinish(thour, tmin, tsec);}postInvalidate();break;}return super.onTouchEvent(event);}

也就是在移动的时候的调用

scroller.startScroll(scroller.getFinalX(), scroller.getFinalY(), (int) dataX, 0);

不停的生成新的点然后不停的重新画.

边界的处理,对于边界的处理,我的处理是判断坐标。

int finalx1 = scroller.getFinalX();if (finalx1 < -viewWidth / 2) {scroller.setFinalX(-viewWidth / 2);}if (finalx1 > timeScale * 21) {scroller.setFinalX(timeScale * 21);}

控制坐标的左右最大值。这个可以自己定。

接下就是画图形,绘画就是在onDraw里面用Canvas来绘画。

画刻度:

public void drawLines(Canvas canvas) {//底部的线canvas.drawLine(0, (float) (viewHeight * 0.9), totalTime,(float) (viewHeight * 0.9), linePaint);for (int i = 0; i <= totalTime; i++) {if (i % timeScale == 0) {canvas.drawLine(i, (float) (viewHeight * 0.7), i,(float) (viewHeight * 0.9), linePaint);//画刻度值canvas.drawText(formatString(i / timeScale, 0, 0), i, (float) (viewHeight * 0.6), linePaint);}}}

画指针

public void drawMidLine(Canvas canvas) {//移动的距离整个view内容移动的距离int finalX = scroller.getFinalX();//表示每一个屏幕刻度的一半的总秒数,每一个屏幕有6格int sec = 3 * 3600;//滚动的秒数int temsec = (int) Math.rint((double) finalX / (double) timeScale * 3600);sec += temsec;//获取的时分秒int thour = sec / 3600;int tmin = (sec - thour * 3600) / 60;int tsec = sec - thour * 3600 - tmin * 60;//滚动时的监听if (scrollListener != null) {scrollListener.onScroll(thour, tmin, tsec);}//画指针canvas.drawLine(timeScale * 3 + finalX, 0,timeScale * 3 + finalX, viewHeight, midPaint);//画数字canvas.drawText(formatString(thour, tmin, tsec), timeScale * 3 + finalX,(float) (viewHeight * 0.3), textPaint);}

画背景

public void drawBg(Canvas canvas) {rect.set(-1, 0, timeScale * 24 + 1, viewHeight);canvas.drawRect(rect, bgPaint);}

画时间片段

public void drawTimeRect(Canvas canvas) {for (TimePart temp : data) {int seconds1 = temp.sHour * 3600 + temp.sMinute * 60 + temp.sSeconds;int seconds2 = temp.eHour * 3600 + temp.eMinute * 60 + temp.eSeconds;//如果是先除以3600小数点的数据会被舍去 位置就不准确了int x1 = seconds1 * timeScale / 3600;int x2 = seconds2 * timeScale / 3600;rect.set(x1, 0, x2, (int) (viewHeight * 0.9));canvas.drawRect(rect, timePaint);}}

定义一个时间片段的类:

//时间片段 用于标记选中的时间public static class TimePart {//开始的时间public int sHour, sMinute, sSeconds;//结束的时间public int eHour, eMinute, eSeconds;public TimePart(int sHour, int sMinute, int sSeconds, int eHour, int eMinute, int eSeconds) {this.sHour = sHour;this.sMinute = sMinute;this.sSeconds = sSeconds;this.eHour = eHour;this.eMinute = eMinute;this.eSeconds = eSeconds;}}

其它的好像也没有什么介绍,如果有在补充。

项目地址:https://github.com/absolve/TimeScale

转载于:https://my.oschina.net/u/2000932/blog/759232

自定义一个可滑动时间刻度尺相关推荐

  1. Android 自定义LinearLayout实现滑动下拉抽屉的功能

    先看效果图: 先来说说思路:我们把该页面分为两部分,分别是头部的抽屉布局(海洋色背景)和主内容布局(白色背景),这两部分的布局是呈线性关系,即抽屉在上,主页面在下,并且它们的父布局应该是一个可滑动的L ...

  2. 可以缩放平移的时间刻度尺,方便自定义UI需求。仿萤石云历史录像时间轴

    https://github.com/Liberations/TimeRuler TimeRuler [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ijjdgeFo-1 ...

  3. 自定义时间刻度尺,时间选择器,模仿萤石云

    最近写了个功能萤石云历史回放.其中有个时间刻度选择器,看如下效果 TimeRuler 可以缩放平移的时间刻度尺,方便自定义UI需求.仿萤石云历史录像时间轴 效果: Add it to your bui ...

  4. swift 自定义滑动视图_在Swift中创建一个向上滑动菜单视图(以编程方式)

    swift 自定义滑动视图 This is a quick tutorial on how to create a slide-up menu view in iOS 这是有关如何在iOS中创建向上滑 ...

  5. android自定义view,时间刻度尺,时间轴,视频轴

    TimeRuler 最新版见github地址(欢迎star):https://github.com/huangdali/TimeRuler 时间轴.时间刻度尺 继承至TextureView,效率更高 ...

  6. 自定义一个类型实现go时间类型的json和bson的序列化和反序列化

    自定义一个类型实现go时间类型的json和bson的序列化和反序列化 需求 实现 -自定义JSONTime类型 如何使用? 需求 go语言在时间 和 json 转换时使用 yyyy-MM-dd HH: ...

  7. Android自定义一个属于自己的时间钟表

    1.概述 本文主要讲解的是如何自定义一个时间钟表,通过简单的练习可以简单学习android当中自定义view的一些常用绘图技巧,优化android绘图操作.言归正传,首先看下我们需要实现的效果: 当我 ...

  8. Android开源中国客户端学习 (自定义View)左右滑动控件ScrollLayout

    左右滑动的控件我们使用的也是非常多了,但是基本上都是使用的viewpager 等 android基础的控件,那么我们有么有考虑过查看他的源码进行定制呢?当然,如果你自我感觉非常好的话可以自己定制一个, ...

  9. Android自定义一个播放器控件

    介绍 最近要使用播放器做一个简单的视频播放功能,开始学习VideoView,在横竖屏切换的时候碰到了点麻烦,不过在查阅资料后总算是解决了.在写VideoView播放视频时候定义控制的代码全写在Actv ...

最新文章

  1. linux shell cgi post,linux下shell处理cgi的方法--post get
  2. 少侠!如何写一手好 SQL ?
  3. 成功的自动化测试实施的5大支柱(译)
  4. (转)电脑程序员才能看懂的笑话
  5. Makefile 打印变量的值
  6. 如何解决IIS配置报错问题:存储空间不足?
  7. jdk8 Arrays.sort()实现分析
  8. 字符串流 ostrstream 和 istrstream
  9. Win32汇编学习(7):鼠标输入消息
  10. 做数据分析,一定会用到的12类实用图表
  11. 【图像处理】基于matlab自动报靶系统(重弹孔)
  12. 浅谈矩阵加速——以时间复杂度为O(log n)的算法实现裴波那契数列第n项及前n之和使用矩阵加速法的优化求法
  13. jfinal+poi导出excel
  14. 如何让百度、Google、Yahoo等搜索引擎巨头收录你的网站
  15. plc 滑台流程图_PLC控制直线模组滑台运动概述
  16. python如何导出数据库数据库_python导出数据库数据的方法
  17. 论项目管理中的目标管理
  18. Netty与SpringBoot整合
  19. 毕业设计答辩准备(双频介质谐振器天线)
  20. oracle一个表空间超出32g,Oracle表空间超出32G的解决方法

热门文章

  1. React学习的小总结(一)
  2. Unity 3D学习之雷霆战机(一)
  3. 安装包的原理与制作安装包的流程
  4. 计算机等级成绩科目代码65,北京计算机等级考试成绩评定标准是怎样的
  5. Python操作*.cfg配置文件
  6. Linux下使用aMsn详解(转)
  7. 小米iot业务_一文看懂小米2019上半年财报:IoT平台连接设备达1.96亿台
  8. 编写Makefile:编译当前文件夹以及子文件夹下所有的ccpp文件并生成可执行文件
  9. 成功解决 word2019设置背景色为护眼的绿色
  10. java百度地图逆地址解析_web前端通过百度地图API批量逆解析地址