主要是为了学习自定义控件,如何添加属性以及修改方法等等。
为模拟时钟添加了秒针走动。
效果如附件。
package com.able.widget;
import java.util.TimeZone;
import com.able.test.R;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.text.format.Time;
import android.util.AttributeSet;
import android.view.View;
public class AbleAnalogClock extends View
{
private Time mCalendar;
private Drawable mHourHand;//时针
private Drawable mMinuteHand;//分针
private Drawable mDial;//表盘
private Drawable mSecondHand;//秒针
private int mDialWidth;//表盘宽度
private int mDialHeight;//表盘高度
private boolean mAttached;
private final Handler mHandler = new Handler();
private float mMinutes;
private float mHour;
private float mSecond;
private boolean mChanged;
private final int UPDATEBYMIN=111;
public AbleAnalogClock(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public AbleAnalogClock(Context context, AttributeSet attrs) {
super(context, attrs);
try
{
Resources r=context.getResources();//
TypedArray a=context.obtainStyledAttributes(attrs,R.styleable.AbleAnalogClock);
this.mSecondHand=a.getDrawable(R.styleable.AbleAnalogClock_second);//属性栏的值
if(mSecondHand==null)
{
mSecondHand=r.getDrawable(R.drawable.clock_hand_second);//无用户输入时的默认值
}
mDial = a.getDrawable(R.styleable.AbleAnalogClock_face);
if (mDial == null) {
mDial = r.getDrawable(R.drawable.clock_dial);
}
mHourHand = a.getDrawable(R.styleable.AbleAnalogClock_hour);
if (mHourHand == null) {
mHourHand = r.getDrawable(R.drawable.clock_hand_hour);
}
mMinuteHand = a.getDrawable(R.styleable.AbleAnalogClock_minute);
if (mMinuteHand == null) {
mMinuteHand = r.getDrawable(R.drawable.clock_hand_minute);
}
mCalendar = new Time();
mDialWidth = mDial.getIntrinsicWidth();
mDialHeight = mDial.getIntrinsicHeight();
a.recycle();
}
catch(Exception e)
{
e.printStackTrace();
}
handler.sendEmptyMessage(UPDATEBYMIN);
}
public AbleAnalogClock(Context context) {
this(context,null);
// TODO Auto-generated constructor stub
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mAttached) {
mAttached = true;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);//send every min
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
// in the main thread, therefore the receiver can't run before this method returns.
// The time zone may have changed while the receiver wasn't registered, so update the Time
mCalendar = new Time();
// Make sure we update to the current time
onTimeChanged();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAttached) {
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
handler.removeMessages(UPDATEBYMIN);
}
}
@Override
protected 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;
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));
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mChanged = true;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
boolean changed = mChanged;
if (changed) {
mChanged = false;
}
int availableWidth = mDial.getIntrinsicWidth();
int availableHeight = mDial.getIntrinsicHeight();
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();
canvas.save();
canvas.rotate(mSecond*6.0f, x, y);
final Drawable secondHand = mSecondHand;
if (changed) {
w = secondHand.getIntrinsicWidth();
h = secondHand.getIntrinsicHeight();
secondHand.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
}
secondHand.draw(canvas);
canvas.restore();
if (scaled) {
canvas.restore();
}
}
private Context getApplicationContext() {
return null;
}
private void onTimeChanged() {
mCalendar.setToNow();
int hour = mCalendar.hour;
int minute = mCalendar.minute;
int second = mCalendar.second;
mSecond=second;
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
mChanged = true;
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
String tz = intent.getStringExtra("time-zone");
mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
}
onTimeChanged();
invalidate();
}
};
Handler handler=new Handler()
{
@Override
public void handleMessage(Message msg) {
switch(msg.what)
{
case UPDATEBYMIN:
onTimeChanged();
invalidate();
sendEmptyMessageDelayed(UPDATEBYMIN,1000);
break;
}
super.handleMessage(msg);
}
};
}
- 大小: 66.3 KB
分享到:
相关推荐
在Android开发中,自定义控件是一项非常重要的技能,它能帮助开发者实现独特且具有个性化的...通过实践这个自定义时钟控件项目,初学者可以深入了解Android UI开发,并为后续更复杂的自定义控件开发打下坚实的基础。
时钟的显示方式可以多样化,如模拟时钟、数字时钟或滚动时钟。为了实时更新,可以使用`Handler`或`CountDownTimer`。同时,考虑到电源效率,时钟控件需要在后台运行时适当地暂停或休眠。 5. **动画效果**: 自定义...
本示例主要介绍如何创建一个自定义控件——"ClockLib",这是一个模拟时钟的控件,并探讨如何在应用程序中正确调用和使用它。 首先,创建自定义控件的过程通常包括以下步骤: 1. **创建新类**:在项目中创建一个新...
在Android开发中,自定义控件是提升应用独特性和用户体验的重要手段。本教程将深入探讨如何使用Android的Canvas API来创建一个自定义的表盘控件。表盘控件常见于各种应用程序,如时钟、计步器或者模拟仪表,因此掌握...
自定义控件通常继承自View或者ViewGroup,并重写必要的方法来绘制和响应用户交互。 在"android自定义时钟控件"的案例中,我们的目标是创建一个能够动态显示小时、分钟和秒针的时钟。为此,我们可以创建一个新的类,...
在Android开发中,自定义控件是提升应用独特性和用户体验的重要手段。本篇文章将深入探讨如何在Android中创建一个自定义的时钟控件,基于提供的"android 自定义时钟控件"标题和描述,我们将重点讲解以下几个核心知识...
本文将深入探讨如何创建一个圆形自定义控件,使其能够作为仪表盘或时钟使用,从而实现功能强大的、灵活且实用的UI元素。 首先,我们需要了解自定义控件的基础。在Android中,我们可以继承`View`或`ViewGroup`类来...
这个控件可能被应用于各种场景,如模拟时钟、选择器或者游戏界面等。 首先,我们要理解自定义控件的基本概念。在Android中,自定义控件通常通过继承已有的View或ViewGroup类,并重写其onDraw()方法来实现。在这个...
在Android开发中,自定义控件是一项常见的任务,它能够帮助开发者实现个性化的设计和功能,以满足特定的应用需求。在本案例中,我们关注的是一个自定义时钟控件,其核心是通过图像资源来展示时间。下面我们将深入...
在安卓开发中,自定义控件是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何在Android平台上实现一个自定义的钟表视图。首先,我们从标题和描述中可以得知,这是一个关于使用Android SDK创建自定义View...
在Android开发中,自定义控件是提升应用用户体验和界面设计独特性的重要手段。`TClock`就是一个很好的例子,它模拟了时钟的功能,并且具备事件监听能力。在这个项目`HoldMyOwn-TClock-6b86259`中,我们可以深入学习...
在本文中,我们将深入探讨如何使用Qt框架来创建一个功能丰富的时钟应用,包括模拟时钟、数字时钟以及万年历。Qt是一个跨平台的C++图形用户界面应用程序开发框架,广泛应用于桌面、移动和嵌入式系统。它提供了一系列...
自定义控件通常是在Android的`View`或`ViewGroup`基础上进行扩展,创建一个新类,并重写其必要的方法,如`onDraw()`用于绘制控件内容,`onMeasure()`用于确定控件大小,以及`onLayout()`用于布局定位。在这个例子中...
虽然这两个文件与自定义时钟控件直接相关性不大,但它们可能代表了在实际应用中,自定义控件可以与其他功能(如音频播放)结合,以提供更加一体化的用户体验。 在开发自定义控件时,理解`View`类的工作原理至关重要...
2. **自定义控件**: `ClockContrl`展示了如何创建自定义控件,包括重写`OnPaint`事件以实现自定义绘制。 3. **图形绘制**: 使用`Graphics`类和`Pen`类进行图形绘制,这是在`OnPaint`事件中更新时钟外观的关键。 4. *...
在本文中,我们将深入探讨如何使用Microsoft Foundation Class (MFC) 库来创建一个“美丽的模拟时钟”程序。MFC 是微软为Windows应用程序开发提供的一组C++类库,它封装了Windows API,使开发者能更高效地构建用户...
在MFC中,我们可以利用CWnd派生类来创建自定义控件,表示时钟的各个部分。我们可能需要定义一个名为CMFCClock的类,继承自CWnd,并重写OnPaint()方法来绘制时钟的背景、刻度、数字和指针。在这个方法中,可以使用CDC...
本示例中的"Qt自绘控件-旋转的时钟"是一个典型的自定义控件案例,它模拟了一个旋转的时钟显示,这涉及到Qt的图形系统、事件处理以及时间更新机制。 1. **自定义控件的创建** 在Qt中创建自定义控件需要继承自一个...
总的来说,创建一个C#的仿真时钟控件并实现可调表盘颜色涉及了图形绘制、时间处理、用户交互以及自定义控件设计等多个知识点。这样的控件不仅可以用于教育或演示目的,也可以在各种桌面应用中提供美观的时间显示功能...