Android利用SurfaceView实现简单计时器

发布时间 - 2026-01-10 22:47:44    点击率:

自学了android有几个月了,跟着网上的节奏,应该早点写些博客来提高自己的水准的。但苦于技术水准始终不自信(也是不过关的结果吧),就一直只是将自己学习过程中的问题和重要的知识点写在自己的笔记文档中。

但,总感觉一个人写下来成就感还是欠缺了那么一些,而且有些问题及解答方法抛出来,是有可能得到更多好的反馈及解决方案的。于是,本着不作不会死的心态,一步一步在技术成长的道路前行——>这篇博客就是其中一步!

若博客中有些技术知识点有误或者有更优化的解答方案,还望各位小伙伴多多指出。

以下是正题了:

目标:利用SurfaceView实现一个简单的计时器

图示:

描述:1.利用SurfaceView来实现计时功能,同时不断将圆弧画满;2.点击按钮可以停止计时;

重点:

1.自定义SurfaceView中针对SurfaceHolder.CallBack的三个方法进行覆写;

2.通过surfaceHolder.lockCanvas()在新开的线程中得到canvas对象,从而进行图形和时间文字的绘制;

3.通过设置flag值,从而控制在线程run()方法中逻辑代码的执行;

重要部分代码:

public TestView(Context context) { 
  super(context); 
  surfaceHolder = getHolder(); 
  surfaceHolder.addCallback(this); 
  countThread = new CountThread(surfaceHolder); 
} 
 
public TestView(Context context, AttributeSet attributeSet) { 
  super(context, attributeSet); 
  surfaceHolder = getHolder(); 
  surfaceHolder.addCallback(this); 
  countThread = new CountThread(surfaceHolder); 
} 

以上为自定义的SurfaceView(TestView)的构造函数,做相应的初始化工作。(第二个构造方法在实现过程中没有覆写,导致如果是通过布局文件引入进Activity中时,则显示不出View——>也就是一般自定义View一定要覆写的构造方法)。
在构造方法中初始化了自定义的内部线程类CountThread,用来执行绘制工作。

以下为CountThread类的run()方法执行逻辑:

@Override 
    public void run() { 
      Canvas canvas = null; 
      int pivotX = getResources().getDisplayMetrics().widthPixels / 2; 
      RectF rectF = new RectF(pivotX - 300, pivotX - 300, pivotX + 300, pivotX + 300); 
      while (!isStop) { 
        try { 
          canvas = surfaceHolder.lockCanvas(); 
          canvas.drawColor(Color.WHITE);//设置画布背景为白色 
//          canvas.drawRoundRect(300, 300, 600, 600, 150, 150, paint);//直接使用该行代码来画圆是行不通的,因为这个方法要求版本21,我的手机运行android版本是19 
          canvas.drawArc(rectF, -90, endAngle++, false, paint);//-90在这里不等于270,所以要想从最上方开始画弧,就得用-90 
          canvas.drawText(countTime(endAngle), pivotX, pivotX, paintText);//显示计算的时间 
          Thread.sleep(1000); 
        } catch (Exception e) { 
          e.printStackTrace(); 
        } finally { 
          if (canvas != null) {//需要对canvas进行非空判断 
            surfaceHolder.unlockCanvasAndPost(canvas); 
          } 
        } 
      } 
    } 

主要就是通过Thread.sleep(1000)来停顿一秒,从而通过endAngle来计数。

至此,基本的程序逻辑已经实现。再讲该自定义View引入进Activity指定的layout布局文件中即可进行显示。

但,这其中也会涉及到相应的问题。譬如:

1.图示中的按钮无法显示出来,只能看到自定义的SurfaceView的视图;

我的做法是:将布局设定为FrameLayout即可。因为SurfaceView是浮在窗口的一层,那么就可以把它看做一个图层。

2.java.lang.IllegalThreadStateException:Thread already started

该错误表明,线程已经存在了。这种错误的操作重现是:按下home键或者menu键会导致该自定的SurfaceView销毁,但线程并没有被销毁,再次启动该自定义SurfaceView的时候又去重新启动该线程。解决的方法是:

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
  if (!countThread.isAlive()) {//如果线程不存在,则启动线程——>当应用挂起的时候Thread是存在的,如果不做这个判断,会报“Thread already started ”错误 
    countThread.start();//SurfaceView创建时开启线程 
  } 
} 

在surfaceCreated()方法中对该线程是否是在存活中进行判断。

当然,这里面还有最重要的一个问题:

当按下home键或者menu键时,程序是没有在计时的。那么这种情况下,我的一个解决方案是,通过开启一个service来接收程序停止( onStop() )时已经计时的数值,然后传递给service记下并计时,当应用程序界面重新回归屏幕时( onRestart() )则将数据取出并回传到自定义的SurfaceView的逻辑run()方法中继续计时。

整个小程序的代码可以通过以下链接下载:

点击进入下载页面:http://xiazai./201701/yuanma/AndroidSurfaceView().rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# Android  # SurfaceView  # 计时器  # android使用surfaceview+MediaPlayer播放视频  # Android使用SurfaceView实现飘赞动画  # Android Surfaceview的绘制与应用  # Android截屏SurfaceView黑屏问题的解决办法  # Android利用SurfaceView实现下雨的天气动画效果  # Android切换至SurfaceView时闪屏(黑屏闪一下)以及黑屏移动问题的解决方法  # Android SurfaceView基础用法详解  # 自定义  # 自己的  # 按下  # 会报  # 博客  # 过程中  # 是在  # 在这里  # 也会  # 是有  # 不出  # 多好  # 最重要  # 把它  # 可以通过  # 要想  # 第二个  # 不存在  # 有几个 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Python自然语言搜索引擎项目教程_倒排索引查询优化案例  Laravel的Blade指令怎么自定义_创建你自己的Laravel Blade Directives  SQL查询语句优化的实用方法总结  HTML5建模怎么导出为FBX格式_FBX格式兼容性及导出步骤【指南】  详解MySQL数据库的安装与密码配置  Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】  QQ浏览器网页版登录入口 个人中心在线进入  Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决  阿里云网站搭建费用解析:服务器价格与建站成本优化指南  标题:Vue + Vuex 项目中正确使用 JWT 进行身份认证的实践指南  Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践  如何在云主机上快速搭建多站点网站?  如何快速生成ASP一键建站模板并优化安全性?  香港服务器建站指南:免备案优势与SEO优化技巧全解析  如何自定义建站之星网站的导航菜单样式?  Laravel如何配置任务调度?(Cron Job示例)  如何在建站之星网店版论坛获取技术支持?  如何用花生壳三步快速搭建专属网站?  Linux系统命令中screen命令详解  网站设计制作书签怎么做,怎样将网页添加到书签/主页书签/桌面?  HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】  如何在七牛云存储上搭建网站并设置自定义域名?  Laravel怎么解决跨域问题_Laravel配置CORS跨域访问  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】  制作旅游网站html,怎样注册旅游网站?  独立制作一个网站多少钱,建立网站需要花多少钱?  大连 网站制作,大连天途有线官网?  Laravel如何使用Spatie Media Library_Laravel图片上传管理与缩略图生成【步骤】  创业网站制作流程,创业网站可靠吗?  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  php增删改查怎么学_零基础入门php数据库操作必知基础【教程】  微信小程序 HTTPS报错整理常见问题及解决方案  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  再谈Python中的字符串与字符编码(推荐)  微信小程序 闭包写法详细介绍  LinuxCD持续部署教程_自动发布与回滚机制  Laravel API资源类怎么用_Laravel API Resource数据转换  Laravel如何从数据库删除数据_Laravel destroy和delete方法区别  香港服务器租用费用高吗?如何避免常见误区?  js实现点击每个li节点,都弹出其文本值及修改  C语言设计一个闪闪的圣诞树  如何在Windows环境下新建FTP站点并设置权限?  Laravel数据库迁移怎么用_Laravel Migration管理数据库结构的正确姿势  如何在Windows 2008云服务器安全搭建网站?  如何在建站之星绑定自定义域名?  Laravel如何处理和验证JSON类型的数据库字段  为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】  JavaScript常见的五种数组去重的方式  微信小程序 配置文件详细介绍  详解Android中Activity的四大启动模式实验简述