Android零碎知识
1、显示当前时间和日期:
1 case R.id.btnShowDate: 2 { 3 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 4 // 显示当前日期 5 showDialog("当前日期", sdf.format(new Date())); 6 break; 7 } 8 case R.id.btnShowTime: 9 { 10 SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); 11 // 显示当前时间 12 showDialog("当前时间", sdf.format(new Date())); 13 break; 14 }
2、定制组件——带图像的TextView
1 package net.blogjava.mobile.widget; 2 3 import android.content.Context; 4 import android.graphics.Bitmap; 5 import android.graphics.BitmapFactory; 6 import android.graphics.Canvas; 7 import android.graphics.Rect; 8 import android.util.AttributeSet; 9 import android.widget.TextView; 10 11 public class IconTextView extends TextView 12 { 13 // 命名空间的值 14 private final String namespace = "http://net.blogjava.mobile"; 15 // 图像资源ID 16 private int resourceId = 0; 17 private Bitmap bitmap; 18 19 public IconTextView(Context context, AttributeSet attrs) 20 { 21 super(context, attrs); 22 resourceId = attrs.getAttributeResourceValue(namespace, "iconSrc", 0); 23 if (resourceId > 0) 24 bitmap = BitmapFactory.decodeResource(getResources(), resourceId); 25 } 26 27 @Override 28 protected void onDraw(Canvas canvas) 29 { 30 if (bitmap != null) 31 { 32 33 // 从原图上截取图像的区域,在本例中为整个图像 34 Rect src = new Rect(); 35 // 将截取的图像复制到bitmap上的目标区域,在本例中与复制区域相同 36 Rect target = new Rect(); 37 src.left = 0; 38 src.top = 0; 39 src.right = bitmap.getWidth(); 40 src.bottom = bitmap.getHeight(); 41 42 int textHeight = (int) getTextSize(); 43 target.left = 0; 44 // 计算图像复制到目录区域的纵坐标。由于TextView中文本内容并不是从最顶端开始绘制的,因此,需要重新计算绘制图像的纵坐标 45 target.top = (int) ((getMeasuredHeight() - getTextSize()) / 2) + 1; 46 target.bottom = target.top + textHeight; 47 // 为了保证图像不变形,需要根据图像高度重新计算图像的宽度 48 target.right = (int) (textHeight * (bitmap.getWidth() / (float) bitmap 49 .getHeight())); 50 // 开始绘制图像 51 canvas.drawBitmap(bitmap, src, target, getPaint()); 52 // 将TextView中的文本向右移动一定的距离(在本例中移动了图像宽度加2个象素点的位置) 53 54 canvas.translate(target.right + 2, 0); 55 } 56 super.onDraw(canvas); 57 58 } 59 60 }
从xml文件中来看,实际上也只是为控件添加了iconSrc属性:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:mobile="http://net.blogjava.mobile" android:orientation="vertical" 4 android:layout_width="fill_parent" android:layout_height="fill_parent"> 5 <net.blogjava.mobile.widget.IconTextView 6 android:layout_width="fill_parent" android:layout_height="wrap_content" 7 android:text="第一个笑脸" mobile:iconSrc="@drawable/small" /> 8 <net.blogjava.mobile.widget.IconTextView 9 android:layout_width="fill_parent" android:layout_height="wrap_content" 10 android:text="第二个笑脸" android:textSize="24dp" mobile:iconSrc="@drawable/small" /> 11 <net.blogjava.mobile.widget.IconTextView 12 android:layout_width="fill_parent" android:layout_height="wrap_content" 13 android:text="第三个笑脸" android:textSize="36dp" mobile:iconSrc="@drawable/small" /> 14 <net.blogjava.mobile.widget.IconTextView 15 android:layout_width="fill_parent" android:layout_height="wrap_content" 16 android:text="第四个笑脸" android:textSize="48dp" mobile:iconSrc="@drawable/small" /> 17 <net.blogjava.mobile.widget.IconTextView 18 android:layout_width="fill_parent" android:layout_height="wrap_content" 19 android:text="第五个笑脸" android:textSize="36dp" mobile:iconSrc="@drawable/small" /> 20 <net.blogjava.mobile.widget.IconTextView 21 android:layout_width="fill_parent" android:layout_height="wrap_content" 22 android:text="第六个笑脸" android:textSize="24dp" mobile:iconSrc="@drawable/small" /> 23 <net.blogjava.mobile.widget.IconTextView 24 android:layout_width="fill_parent" android:layout_height="wrap_content" 25 android:text="第七个笑脸" mobile:iconSrc="@drawable/small" /> 26 27 </LinearLayout>
textSize默认是14dp;getTextSize()输出也为14dp,简单理解为文字的高度;getMeasuredHeight()输出该视图的原始测量高度(API:The raw measured height of this view)相应值为19dp,简单理解为TextView控件的高度,差值简单认为是padding的值。
target.top = (int) ((getMeasuredHeight() - getTextSize())/2 ) + 1;式子加好前面的部分可以理解为padding的值,实际上不加1更好理解,效果也更好
3、定制组件——完全重写组件
通过这种方式定制的组件类需要从android:view:View继承,并通过组合、画布等方式对View进行拓展。
1 package net.blogjava.mobile.widget; 2 3 import java.util.Calendar; 4 import android.content.Context; 5 import android.graphics.Bitmap; 6 import android.graphics.BitmapFactory; 7 import android.graphics.Canvas; 8 import android.graphics.Paint; 9 import android.graphics.Rect; 10 import android.os.Handler; 11 import android.util.AttributeSet; 12 import android.view.View; 13 14 public class HandClock extends View implements Runnable 15 { 16 private int clockImageResourceId; 17 private Bitmap bitmap; 18 private float scale; 19 private float handCenterWidthScale; 20 private float handCenterHeightScale; 21 private int minuteHandSize; 22 private int hourHandSize; 23 private Handler handler = new Handler(); 24 25 @Override 26 public void run() 27 { 28 // 重新绘制View 29 invalidate(); 30 // 重新设置定时器,在60秒后调用run方法 31 handler.postDelayed(this, 60 * 1000); 32 } 33 34 @Override 35 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 36 { 37 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 38 // 根据图像的实际大小等比例设置View的大小 39 setMeasuredDimension((int) (bitmap.getWidth() * scale), (int) (bitmap 40 .getHeight() * scale)); 41 } 42 43 @Override 44 protected void onDraw(Canvas canvas) 45 { 46 super.onDraw(canvas); 47 Paint paint = new Paint(); 48 Rect src = new Rect(); 49 Rect target = new Rect(); 50 src.left = 0; 51 src.top = 0; 52 src.right = bitmap.getWidth(); 53 src.bottom = bitmap.getHeight(); 54 55 target.left = 0; 56 target.top = 0; 57 target.bottom = (int) (src.bottom * scale); 58 target.right = (int) (src.right * scale); 59 // 画表盘图像 60 canvas.drawBitmap(bitmap, src, target, paint); 61 // 计算表盘中心点的横纵坐标 62 float centerX = bitmap.getWidth() * scale * handCenterWidthScale; 63 float centerY = bitmap.getHeight() * scale * handCenterHeightScale; 64 // 表表盘中心点画一个半径为5的实心圆圈 65 canvas.drawCircle(centerX, centerY, 5, paint); 66 // 设置分针为3个象素粗 67 paint.setStrokeWidth(3); 68 Calendar calendar = Calendar.getInstance(); 69 int currentMinute = calendar.get(Calendar.MINUTE); 70 int currentHour = calendar.get(Calendar.HOUR); 71 // 计算分针和时间的角度 72 double minuteRadian = Math 73 .toRadians((360 - ((currentMinute * 6) - 90)) % 360); 74 double hourRadian = Math.toRadians((360 - ((currentHour * 30) - 90)) 75 % 360 - (30 * currentMinute / 60)); 76 // 在表盘上画分针 77 canvas.drawLine(centerX, centerY, (int) (centerX + minuteHandSize 78 * Math.cos(minuteRadian)), (int) (centerY - minuteHandSize 79 * Math.sin(minuteRadian)), paint); 80 // 设置实针为4个象素粗 81 paint.setStrokeWidth(4); 82 // 在表盘上画分针 83 canvas.drawLine(centerX, centerY, (int) (centerX + hourHandSize 84 * Math.cos(hourRadian)), (int) (centerY - hourHandSize 85 * Math.sin(hourRadian)), paint); 86 } 87 88 public HandClock(Context context, AttributeSet attrs) 89 { 90 super(context, attrs); 91 // 读取相应的属性值 92 clockImageResourceId = attrs.getAttributeResourceValue(null, 93 "clockImageSrc", 0); 94 if (clockImageResourceId > 0) 95 bitmap = BitmapFactory.decodeResource(getResources(), 96 clockImageResourceId); 97 scale = attrs.getAttributeFloatValue(null, "scale", 1); 98 handCenterWidthScale = attrs.getAttributeFloatValue(null, 99 "handCenterWidthScale", bitmap.getWidth() / 2); 100 handCenterHeightScale = attrs.getAttributeFloatValue(null, 101 "handCenterHeightScale", bitmap.getHeight() / 2); 102 // 在读取分针和时针长度后,将其值按图像的缩放比例进行缩放 103 minuteHandSize = (int) (attrs.getAttributeIntValue(null, 104 "minuteHandSize", 0) * scale); 105 hourHandSize = (int) (attrs.getAttributeIntValue(null, "hourHandSize", 106 0) * scale); 107 int currentSecond = Calendar.getInstance().get(Calendar.SECOND); 108 // 将定时器设在0分时执行run方法 109 handler.postDelayed(this, (60 - currentSecond) * 1000); 110 } 111 112 @Override 113 protected void onDetachedFromWindow() 114 { 115 super.onDetachedFromWindow(); 116 // 删除回调类 117 handler.removeCallbacks(this); 118 } 119 120 }
组件共定义了六个属性:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" android:layout_width="fill_parent" 4 android:layout_height="fill_parent" android:background="#FFF" 5 android:gravity="center_horizontal"> 6 <net.blogjava.mobile.widget.HandClock 7 android:layout_width="wrap_content" android:layout_height="wrap_content" 8 android:layout_marginTop="10dp" clockImageSrc="@drawable/clock2" 9 scale="0.3" handCenterWidthScale="0.5" handCenterHeightScale="0.5" 10 minuteHandSize="154" hourHandSize="100" /> 11 <net.blogjava.mobile.widget.HandClock 12 android:layout_width="wrap_content" android:layout_height="wrap_content" 13 android:layout_marginTop="10dp" clockImageSrc="@drawable/clock3" 14 scale="0.3" handCenterWidthScale="0.5" handCenterHeightScale="0.5" 15 minuteHandSize="154" hourHandSize="100" /> 16 </LinearLayout> 17