通过继承View类,我们可以自定义自己需求的复杂控件。本例实现了一个自定义的时钟。
效果如下:
代码如下:
package com.example.test; import java.util.Calendar; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.os.Handler; import android.util.AttributeSet; import android.view.View; public class Clock extends View implements Runnable { //表盘图像资源ID private int clockImageResourceID; //表盘图像缩放比例 private float scale; private Bitmap bitmap; //原始图像中表盘中心点横坐标相当于图像宽度的比例 private float centerWidthScale; //原始图像中表盘中心点纵坐标相当于图像高度的比例 private float centerHeightScale; //在原始表盘中分针的长度 private int minuteSize; //在原始表盘中时针的长度 private int hourSize; private Handler handler=new Handler(); public Clock(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub //本例未使用命名空间 null clockImageResourceID=attrs.getAttributeResourceValue(null,"clockImageSrc",0); if(clockImageResourceID>0){ bitmap=BitmapFactory.decodeResource(getResources(), clockImageResourceID); } scale=attrs.getAttributeFloatValue(null, "scale", 1); centerWidthScale=attrs.getAttributeFloatValue(null, "centerWidthScale" ,bitmap.getHeight()/2); centerHeightScale=attrs.getAttributeFloatValue(null, "centerHeightScale" ,bitmap.getWidth()/2); //将时针分针的长度缩放 minuteSize=(int)(attrs.getAttributeIntValue(null, "minuteSize", 0)*scale); hourSize=(int)(attrs.getAttributeIntValue(null, "hourSize", 0)*scale); int currentSecond=Calendar.getInstance().get(Calendar.SECOND); //当秒钟在12点方向时 执行run方法 handler.postDelayed(this, (60-currentSecond)*1000); } //view分离时调用 @Override protected void onDetachedFromWindow() { // TODO Auto-generated method stub super.onDetachedFromWindow(); handler.removeCallbacks(this); } public void run() { // TODO Auto-generated method stub //重绘 invalidate(); //重新设定定时器60s后启用 handler.postDelayed(this, 60*1000); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); //根据图像的实际大小等比例设置view的大小 setMeasuredDimension((int)(bitmap.getWidth()*scale), (int)(bitmap.getHeight()*scale)); } @Override protected void onDraw(Canvas canvas) { // TODO Auto-generated method stub super.onDraw(canvas); Paint paint=new Paint(); Rect src=new Rect(); Rect target=new Rect(); src.left=0; src.top=0; src.right=bitmap.getWidth(); src.bottom=bitmap.getHeight(); target.left=0; target.top=0; target.bottom=(int)(src.bottom*scale); target.right=(int)(src.right*scale); //画表盘 canvas.drawBitmap(bitmap, src, target,paint); //计算表盘中心点的横坐标 float centerX=bitmap.getWidth()*scale*centerWidthScale; //计算表盘中心点的纵坐标 float centerY=bitmap.getHeight()*scale*centerHeightScale; canvas.drawCircle(centerX, centerY, 5, paint); paint.setStrokeWidth(3); Calendar calendar=Calendar.getInstance(); int currentMinute=calendar.get(Calendar.MINUTE); int currentHour=calendar.get(Calendar.HOUR); //计算分针和时针的角度 double minuteRadin=Math.toRadians((360-((currentMinute*6)-90))%360); double hourRadin=Math.toRadians((360-((currentHour*30)-90))%360-(30*currentMinute/60)); //在表盘上画分针 canvas.drawLine(centerX, centerY, (int)(centerX+minuteSize*Math.cos(minuteRadin)), (int)(centerY-hourSize*Math.sin(minuteRadin)), paint); paint.setStrokeWidth(4); paint.setColor(Color.RED); //画时针 canvas.drawLine(centerX, centerY, (int)(centerX+hourSize*Math.cos(hourRadin)), (int)(centerY-hourSize*Math.sin(hourRadin)), paint); } }
布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <com.example.test.Clock android:layout_width="match_parent" android:layout_height="match_parent" clockImageSrc="@drawable/ic_launcher" scale="1.5" centerWidthScale="0.5" centerHeightScale="0.5" minuteSize="100" hourSize="30" /> </RelativeLayout>在Activity中引用该布局文件即可显示自定义的时钟控件。