通过手势实现对时钟的拨动旋转效果(附详细说明)

31
回复
140911
查看
  [复制链接]

251

主题

251

帖子

1290

安币

代码手工艺人

Rank: 4

发表于 2011-11-27 22:29:38 | 显示全部楼层 |阅读模式
废话不多说,上图先

实际应用中,若钟表绘制仅通过GDI绘图方式,则样式较为单一
所以采取贴图的方式显示钟表则更能给人以丰富的视觉冲击
而其中则用到了CANVAS的偏移旋转的相关知识

MyClockView  类::
  1. protected void onDraw(Canvas canvas) {
  2. // TODO Auto-generated method stub
  3. super.onDraw(canvas);


  4. canvas.drawColor(Color.WHITE);

  5. if (!bInitComplete){
  6. return ;
  7. }

  8. drawClock(canvas);

  9. drawHour(canvas);

  10. drawMinute(canvas);

  11. Paint paint = new Paint();
  12. paint.setColor(Color.RED);

  13. canvas.drawLine(0, clockCenterY, canvas.getWidth(), clockCenterY, paint);

  14. canvas.drawLine(clockCenterX, 0, clockCenterX, canvas.getHeight(), paint);
复制代码
首先用白色填充画布,以便大家直观地看到视图大小,然后分别绘制时钟底盘,时针,分针,至于最后的红十字线只是呈现本例的时钟旋转所对应的参考坐标系
以分针为例,绘制如下:
  1. public void drawMinute(Canvas canvas){
  2. if (mMinuteBitmap == null){
  3. return ;
  4. }

  5. canvas.save();

  6. canvas.translate(clockCenterX, clockCenterY);



  7. canvas.rotate(mCurTime.mMinuteDegree);

  8. Paint paint = new Paint();
  9. paint.setAntiAlias(true);
  10. canvas.drawBitmap(mMinuteBitmap, mMinutePosX, mMinutePosY, paint);

  11. canvas.restore();
  12. }
复制代码
在绘制前,偏移CANVAS坐标系至时钟中心点,然后根据分针偏移量旋转坐标系,最后绘图,所以mMinutePosX和 mMinutePosY的坐标都是相对于参考坐标系即时钟中心点的位置

绘图过程大致就是如此,所以通过手势滑动拨动分针时要确定的就是指针的偏移角度,且看onTouch方法:
  1. public boolean onTouch(View v, MotionEvent event) {
  2. // TODO Auto-generated method stub

  3. switch(event.getAction()){
  4. case MotionEvent.ACTION_DOWN:

  5. calcDegree((int)event.getX(), (int)event.getY(), false);
  6. postInvalidate();

  7. break;
  8. case MotionEvent.ACTION_MOVE:

  9. calcDegree((int)event.getX(), (int)event.getY(), false);
  10. postInvalidate();

  11. break;
  12. case MotionEvent.ACTION_UP:

  13. calcDegree((int)event.getX(), (int)event.getY(), true);
  14. postInvalidate();

  15. break;
  16. }

  17. return true;
  18. }
复制代码
  1. public void calcDegree(int x, int y, boolean flag){
  2. int rx = x - clockCenterX;
  3. int ry = - (y - clockCenterY);

  4. Point point = new Point(rx, ry);

  5. mCurTime.mMinuteDegree = MyDegreeAdapter.GetRadianByPos(point);
  6. mCurTime.calcTime(flag);
  7. }
复制代码
int rx = x - clockCenterX;
int ry = - (y - clockCenterY);
Point point = new Point(rx, ry);
这三行代码作用就是将坐标点转化为时钟坐标系上的点(X轴向右,Y轴向上,这与画布坐标系的Y轴方向正好相反)


mCurTime.mMinuteDegree = MyDegreeAdapter.GetRadianByPos(point);
根据坐标计算分针偏移角度

mCurTime.calcTime(flag);
根据得到的分针角度进一步确定要表示的时间(时针角度依赖当前小时数和分针角度,以及当分针划过12点钟位置后小时数的变化)

MyDegreeAdapter 类一个主要方法:
  1. public static int GetRadianByPos(Point point){
  2.   double dAngle = GetRadianByPosEx(point);
  3.   
  4.   return (int) (dAngle * (360 / (2 * PI)));
  5. }
复制代码

根据坐标获得偏移角度,这里返回的是度数

综上所述,根据手势滑动时坐标点以及滑动方向便是计算指针偏移角度的核心
由于本例旨在介绍如何通过手势拨动时钟,故时钟并不随系统时间而走动
有兴趣的童鞋可以在此基础上扩展一下让时钟动起来(做成UI控件更不错哦)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

2

主题

187

帖子

17

安币

初级码农

IT男

Rank: 1

QQ达人

QQ
发表于 2011-11-30 09:38:58 | 显示全部楼层
下来看看呀!
努力!!!

2

主题

125

帖子

243

安币

攻城狮

Rank: 3Rank: 3

最佳新人

发表于 2012-2-22 08:57:57 | 显示全部楼层
有用到类似的东西

4

主题

60

帖子

194

安币

程序猿

Rank: 2

发表于 2012-3-23 16:34:59 | 显示全部楼层
{:soso_e129:},收藏

0

主题

47

帖子

16

安币

初级码农

Rank: 1

发表于 2012-3-26 20:55:19 | 显示全部楼层
收藏了   谢谢楼主

1

主题

95

帖子

549

安币

程序猿

Rank: 2

QQ达人

发表于 2012-3-27 21:48:36 | 显示全部楼层
谢谢楼主

7

主题

68

帖子

207

安币

程序猿

Rank: 2

发表于 2012-11-12 11:48:12 | 显示全部楼层
效果真的不错!顶

3

主题

495

帖子

755

安币

代码手工艺人

Rank: 4

发表于 2012-11-12 14:18:55 | 显示全部楼层
谢谢分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:1294855032@qq.com

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )