Android利用SurfaceView实现简单计时器

自学了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.jb51.net/201701/yuanma/AndroidSurfaceView(jb51.net).rar

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

(0)

相关推荐

  • Android实现的秒表计时器示例

    本文实例讲述了Android实现的秒表计时器.分享给大家供大家参考,具体如下: package com.liu.time; import java.util.Timer; import java.util.TimerTask; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; imp

  • Android时分秒计时器的两种实现方法

    可能我们在开发中会时常用到计时器这玩意儿,比如在录像的时候,我们可能需要在右上角显示一个计时器.这个东西其实实现起来非常简单. 只需要用一个控件Chronometer,是的,就这么简单,我都不好意思讲述一下了. <Chronometer android:layout_width="wrap_content" android:layout_height="wrap_content" android:format="%s" android:id

  • Android中CountDownTimer倒计时器用法实例

    本文实例讲述了Android中CountDownTimer倒计时器用法.分享给大家供大家参考,具体如下: 在平时我们编程的时候,经常会用到倒计时这个功能,很多人不知道Android已经帮封装好了一个类,往往都自己写.现在发现了这个类,大家共享一下: 在一个TextView不断显示剩下的时间,代码如下: private TextView vertifyView; private CountDownTimer timer = new CountDownTimer(10000, 1000) { @Ov

  • Android编程之简单计时器实现方法

    本文实例讲述了Android编程之简单计时器实现方法.分享给大家供大家参考,具体如下: 这里利用ContextMenu(上下文菜单),Chronometer实现简单计数器. Main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android

  • android之计时器(Chronometer)的使用以及常用的方法

    在Android的SDK中,为我们提供了一个计时器,这个计时器称为Chronometer,我们可以成它为Android的一个组件,同时它也具备自己独有的方法.下面我们举例介绍下这个计时器的使用以及常用的方法. 跟其他UI组件一样,当我们要使用它的时候,在布局文件中对应的位置声明定义计时器的位置与属性. 复制代码 代码如下: <Chronometer android:id="@+id/chronometer" android:layout_width="wrap_cont

  • android开发教程之间隔执行程序(android计时器)

    下面是每隔一段时间就执行某个操作,直到关闭定时操作: 复制代码 代码如下: final Handler handler = new Handler();     Runnable runnable = new Runnable(){         @Override         public void run() {             // TODO Auto-generated method stub             // 在此处添加执行的代码             ha

  • Android 编程下的计时器代码

    同样,为了防止用户恶意的频繁发送激活码,应用中需要对用户发送激活码的时间间隔进行限制,这时就需要用到倒计时器了,大概流程是这样的:页面初始化的时候,按钮为可点击状态,用户在点击"发送激活码"后按钮变为不可点击状态,同时按钮上的文字变为倒计时状态,倒计时结束后,按钮变为可点击状态,文字变为"发送激活码".具体逻辑看下面的代码: 复制代码 代码如下: package cn.sunzn.countdown; import android.app.Activity;impo

  • 学习使用Android Chronometer计时器

    本文实例为大家分享了Android Chronometer计时器基本使用方法,供大家参考,具体内容如下 在默认情况下,Chronometer组件只输出MM:SS或H:MM:SS的时间格式.例如,当计时到1分20秒时,Chronometer组件会显示01:20.如果想改变显示的信息内容,可以使用Chronometer类的setFormat方法.该方法需要一个String变量,并使用"%s"表示计时信息.例如,使用setFormat("计时信息:%s")设置显示信息,C

  • android计时器,时间计算器的实现方法

    需求:默认为"00:00:00",点击开始按钮时清零后开始计时,出现如10:28:34.点击停止的时候停止计时.问题:使用Calendar DateFormat的方法,不设置时区获取到的小时是本地时区的(东八区的就是8),设置成GMT标准时区获取到的时间是12小时(12:00:00),设置24小时制无效.在开始时间加减各种小时都无效,而且计时只能到12小时就自动跳上去了,始终无法出现默认状态00:00:00开始计时的效果.尝试各种时间设置方法无效后只能自己写一个根据秒数转换时间格式字符

  • Android Wear计时器开发

    记得在2013年12月的时候,有系列文章是介绍怎么开发一个智能手表的App,让用户可以在足球比赛中记录停表时间.随着Android Wear的问世,在可穿戴设备中开发一款这样的App确实是个很不错的想法,但是按照目前对于Android Wear的架构了解来说,似乎有些困难.所以本系列文章我们就重写这个应用,带领大家进入Android Wear的世界. 本文不会长篇大论地讲解我们要开发的这款App的用途,因为我们在之前的系列文章已经深入了解过了.这么说吧,这是一个计时类应用,在比赛开始的时候开始执

随机推荐