谷歌已经为我们提供了非常丰富的控件,一般任务均可完成,但是有时候一些特别任务还是需要我们自定义控件来完成。

本文尝试完成一个自定义钟表控件。

</pre><pre name="code" class="java">package com.shusheng007.customviews;import com.shusheng007.mp3plaryer.R;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.text.format.Time;
import android.util.AttributeSet;
import android.view.View;public class CustomClockView extends View
{private Time mCalendar;// 表盘上的各指针图private Drawable mHourHand;private Drawable mMinuteHand;//表盘图片private Drawable mDial;// 定义表盘的宽和高private int mDialWidth;private int mDialHeight;private boolean mAttached;private final Handler mHandler = new Handler();private float mMinutes;private float mHour;//用于判断,view是否需要重新绘制private boolean mChanged;public CustomClockView(Context context){this(context,null);}public CustomClockView(Context context, AttributeSet attrs){this(context, attrs,0);}public CustomClockView(Context context, AttributeSet attrs, int defStyleAttr){super(context, attrs, defStyleAttr);Resources r = context.getResources();/** 通过资源加载各图片,用于绘制时钟*/mDial = r.getDrawable(R.drawable.clock_dial);mHourHand = r.getDrawable(R.drawable.clock_hour);mMinuteHand = r.getDrawable(R.drawable.clock_minute);mCalendar = new Time();mDialWidth = mDial.getIntrinsicWidth();mDialHeight = mDial.getIntrinsicHeight();}/** 要计算该组件的宽和高时调用该方法*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){//获得模式和尺寸int widthMode = MeasureSpec.getMode(widthMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);float hScale = 1.0f;float vScale = 1.0f;//判断尺寸模式是否为Unspecified,如果不是就需要判断表盘大小是否超出容器尺寸if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {hScale = (float) widthSize / (float) mDialWidth;}if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {vScale = (float) heightSize / (float) mDialHeight;}//如果表盘图像尺寸超出其组件的尺寸,则需要缩放float scale = Math.min(hScale, vScale);//此函数必须调用,用于设置空间尺寸setMeasuredDimension(resolveSize((int) (mDialWidth * scale), widthMeasureSpec),resolveSize((int) (mDialHeight * scale), heightMeasureSpec));}@Overrideprotected void onDraw(Canvas canvas){// TODO Auto-generated method stubsuper.onDraw(canvas);// 用一个标识来判断是否要重新绘boolean changed = mChanged;if (changed) {mChanged = false;}// 获取在其父容器中的的位置信final int mRight = getRight();final int mLeft = getLeft();final int mTop = getTop();final int mBottom = getBottom();// 计算实际的宽和高int availableWidth = mRight - mLeft;int availableHeight = mBottom - mTop;// 计算时钟的原点int x = availableWidth / 2;int y = availableHeight / 2;// 表盘的宽和高final Drawable dial = mDial;int w = dial.getIntrinsicWidth();int h = dial.getIntrinsicHeight();boolean scaled = false;// 利用实际宽高和表盘的宽高,判断是否需要缩放画布if (availableWidth < w || availableHeight < h) {scaled = true;float scale = Math.min((float) availableWidth / (float) w,(float) availableHeight / (float) h);canvas.save();canvas.scale(scale, scale, x, y);}if (changed) {dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));}dial.draw(canvas);canvas.save();canvas.rotate(mHour / 12.0f * 360.0f, x, y);final Drawable hourHand = mHourHand;if (changed) {w = hourHand.getIntrinsicWidth();h = hourHand.getIntrinsicHeight();hourHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y+ (h / 2));}hourHand.draw(canvas);canvas.restore();canvas.save();canvas.rotate(mMinutes / 60.0f * 360.0f, x, y);final Drawable minuteHand = mMinuteHand;if (changed) {w = minuteHand.getIntrinsicWidth();h = minuteHand.getIntrinsicHeight();minuteHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y+ (h / 2));}minuteHand.draw(canvas);canvas.restore();if (scaled) {canvas.restore();}Matrix matrix = new Matrix();matrix.setRotate(45, 50, 50);matrix.setScale(1.5f, 1.5f);canvas.concat(matrix);}/** (non-Javadoc)* * @see android.view.View#onAttachedToWindow()* 在组件绘制到window之前调用,这时组件的相关资源已经读取完毕。一般在该方法中进行逻辑上的初始化操作�1�?�?�?* * 在该实例中,进行了IntentReceiver注册的操作�1�?�?�?*/@Overrideprotected void onAttachedToWindow() {super.onAttachedToWindow();onTimeChanged();if (!mAttached) {mAttached = true;IntentFilter filter = new IntentFilter();// 注册时间改变的Intent,当时间变动时改变时钟时�?�?filter.addAction(Intent.ACTION_TIME_TICK);filter.addAction(Intent.ACTION_TIME_CHANGED);getContext().registerReceiver(mIntentReceiver, filter, null,mHandler);}}/** @see android.view.View#onDetachedFromWindow()* 当该组件不再window上显示时调用。一般进行一些IntentReceiver的销毁工作*/@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();if (mAttached) {getContext().unregisterReceiver(mIntentReceiver);mAttached = false;}}private void onTimeChanged() {long time = System.currentTimeMillis();mCalendar.set(time);int hour = mCalendar.hour;int minute = mCalendar.minute;int second = mCalendar.second;mMinutes = minute + second / 60.0f;mHour = hour + mMinutes / 60.0f;mChanged = true;}private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {onTimeChanged();//使view显示内容无效,然后View,执行ondraw重绘invalidate();}};
}

自定义控件学习之钟表制作相关推荐

  1. 刚開始学习的人制作VMOS场效应管小功放

    VMOS场效应管既有电子管的长处又有晶体管的长处,用它制作的功率放大器声音醇厚.甜美,动态范围大.频率响应好.因此近年来在音响设备中得到了广泛应用. 大功率的场效应管功率放大器.电.路比較复杂.制作和 ...

  2. 全景丨0基础学习VR全景制作,平台篇第13章:热点功能-总览介绍

    全景丨0基础学习VR全景制作,平台篇第13章:热点功能-总览介绍 大家好,欢迎观看蛙色VR官方--后台使用系列课程! 一.热点功能概览 热点,指在全景作品中添加各种类型图标的按钮,引导用户通过按钮产生 ...

  3. Polyworks脚本开发学习笔记(十七)-制作宏脚本自定义工具条

    Polyworks脚本开发学习笔记(十七)-制作宏脚本自定义工具条 做好的宏脚本程序,每次打开脚本加载程序太多麻烦,为了方便的调用脚本做各种操作,可以使用系统的自定义工具条功能将脚本加载到工具条上. ...

  4. ps基础入门知识课程教程学习文字设计制作小白

    ps基础入门知识课程教程学习文字设计制作小白

  5. 学习个人网页制作全过程

    如何制作个人网页全过程,送给刚学做网页的朋友们 第一讲 网页的基本知识和FrontPage入门 一.网页的基本知识 1.网站与网页 我们在因特网上浏览时,看到的每一个页面,称为网页,很多网页组成一个网 ...

  6. html制作网站边框,HTML学习笔记☆边框制作

    HTML学习笔记☆边框制作 代码: 填入内容 填入内容 填入内容 填入内容 填入内容 填入内容 填入内容 填入内容 填入内容 以上代码确切地说是表格代码,把括号内文字改成数字或去掉,变成以下代码形式: ...

  7. Caffe学习笔记3——制作并训练自己的数据集

    Caffe学习笔记3 本文为原创作品,未经本人同意,禁止转载,禁止用于商业用途!本人对博客使用拥有最终解释权 欢迎关注我的博客:http://blog.csdn.net/hit2015spring和h ...

  8. 用HTML制作表单表格能学到什么,Html学习之十七(表格与表单学习--排行版制作)...

    表格与表单01 table{ width: 300px; height: 40px; margin: 100px auto; border-collapse: collapse; } .th2{ fl ...

  9. Android自定义控件学习(三)----- 自定义视图组件

    自定义视图组件 说明 Android提供了用于构建UI的基础上,基本布局类一个复杂和强大的组件化模式:View和 ViewGroup.首先,该平台包含各种预构建的View和ViewGroup子类 - ...

最新文章

  1. java中对Excel的创建、样式修改
  2. Resharper 检测所有NullReferenceExceptions(空指针)
  3. 导出对象_从代数几何到导出代数几何:形变与逼近
  4. 使用的是html5的canvas将文字转换成图片
  5. 蓝桥杯java第八届第三题--承压计算
  6. java中的神奇this
  7. Centos普通用户权限报错:** is not in the sudoers file. This incident will be reported.
  8. 程序员的进阶课-架构师之路(14)-B+树、B*树
  9. .net找List1和List2的差集
  10. Visual Studio 2013中因Browser Link引起的Javascript错误
  11. Response JSON数据返回
  12. 一个IE动画图标的小例子
  13. (转)Android 如何建立你的菜单
  14. 《企业IT架构转型之道》读后感(一)
  15. 数据分析sql面试必会6题经典_面试准备:数据库常见面试题汇总
  16. 禁止搜狗拼音输入法自动更新
  17. 鱼塘钓鱼(贪心算法)--算法设计
  18. ip自签名ssl证书
  19. 基于Java的企业内部通信系统的设计与实现
  20. c语言中getc函数,C语言中getc怎么用?

热门文章

  1. 杨澜给二十几岁的女孩的告诫
  2. 《CCNA学习指南:Cisco网络设备互连(ICND2)(第4版)》——1.1节理解VLAN 和VLAN Trunk 及排除相关故障...
  3. windowsXP服务详解
  4. mysql isnum()_mysql 一些基础的语法和命令
  5. 7-1 统计正数和负数的个数然后计算这些数的平均值 (15 分)-java
  6. 为什么我不建议你去外包公司?
  7. 【一看就懂】tf.logical_and(),tf.logical_or(),tf.logical_not(),tf.logical_xor()
  8. Python 博客园快速备份脚本
  9. android开发——分秒计时器(可 开始/暂停/继续/停止)
  10. Neuron segmentation using 3D wavelet integratedencoder–decoder network