本文主要是介绍Android定制组件的三种方式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原文地址: http://www.cnblogs.com/baihai/archive/2012/08/20/2647533.html
方式一、继承原有的组件
实例:带图像的TextView
1、IconTextView.java
package net.blogjava.mobile.widget;import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Rect; import android.util.AttributeSet; import android.widget.TextView;public class IconTextView extends TextView {// 命名空间的值private final String namespace = "http://net.blogjava.mobile";// 图像资源IDprivate int resourceId = 0;private Bitmap bitmap;//构造函数public IconTextView(Context context, AttributeSet attrs){//继承TextView的构造函数public TextView(Context context, AttributeSet attrs)super(context, attrs);resourceId = attrs.getAttributeResourceValue(namespace, "iconSrc", 0);if (resourceId > 0)bitmap = BitmapFactory.decodeResource(getResources(), resourceId);}@Overrideprotected void onDraw(Canvas canvas){if (bitmap != null){ // 从原图上截取图像的区域,在本例中为整个图像Rect src = new Rect();// 将截取的图像复制到bitmap上的目标区域,在本例中与复制区域相同Rect target = new Rect();src.left = 0;src.top = 0;src.right = bitmap.getWidth();src.bottom = bitmap.getHeight();int textHeight = (int) getTextSize();target.left = 0;// 计算图像复制到目录区域的纵坐标。由于TextView中文本内容并不是从最顶端开始绘制的,因此,需要重新计算绘制图像的纵坐标target.top = (int) ((getMeasuredHeight() - getTextSize()) / 2) + 1;target.bottom = target.top + textHeight;// 为了保证图像不变形,需要根据图像高度重新计算图像的宽度target.right = (int) (textHeight * (bitmap.getWidth() / (float) bitmap.getHeight()));// 开始绘制图像 canvas.drawBitmap(bitmap, src, target, getPaint());// 将TextView中的文本向右移动一定的距离(在本例中移动了图像宽度加2个象素点的位置) canvas.translate(target.right + 2, 0);}super.onDraw(canvas);// 必须最后调用} }
2、main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:mobile="http://net.blogjava.mobile" android:orientation="vertical"android:layout_width="fill_parent" android:layout_height="fill_parent"><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第一个笑脸" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第二个笑脸" android:textSize="24dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第三个笑脸" android:textSize="36dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第四个笑脸" android:textSize="48dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第五个笑脸" android:textSize="36dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第六个笑脸" android:textSize="24dp" mobile:iconSrc="@drawable/small" /><net.blogjava.mobile.widget.IconTextViewandroid:layout_width="fill_parent" android:layout_height="wrap_content"android:text="第七个笑脸" mobile:iconSrc="@drawable/small" /></LinearLayout>
3、效果
方式二、组合原有的组件
实例:带文本标签的EditText
1、LabelEditText.java
package net.blogjava.mobile.widget;import net.blogjava.mobile.R; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.widget.LinearLayout; import android.widget.TextView;public class LabelEditText extends LinearLayout {private TextView textView;private String labelText;private int labelFontSize;private String labelPosition;public LabelEditText(Context context, AttributeSet attrs) {super(context, attrs);// 读取labelText属性的资源IDint resourceId = attrs.getAttributeResourceValue(null, "labelText", 0);// 未获得资源ID,继续读取属性值if (resourceId == 0)labelText = attrs.getAttributeValue(null, "labelText");// 从资源文件中获得labelText属性的值elselabelText = getResources().getString(resourceId);// 如果按两种方式都未获得labelTex属性的值,表示未设置该属性,抛出异常if (labelText == null) {throw new RuntimeException("必须设置labelText属性.");}// 获得labelFontSize属性的资源IDresourceId = attrs.getAttributeResourceValue(null, "labelFontSize", 0);// 继续读取labelFontSize属性的值,如果未设置该属性,将属性值设为14if (resourceId == 0)labelFontSize = attrs.getAttributeIntValue(null, "labelFontSize", 14);// 从资源文件中获得labelFontSize属性的值elselabelFontSize = getResources().getInteger(resourceId);// 获得labelPosition属性的资源IDresourceId = attrs.getAttributeResourceValue(null, "labelPosition", 0);// 继续读取labelPosition属性的值if (resourceId == 0)labelPosition = attrs.getAttributeValue(null, "labelPosition");// 从资源文件中获得labelPosition属性的值elselabelPosition = getResources().getString(resourceId);// 如果未设置labelPosition属性值,将该属性值设为leftif (labelPosition == null)labelPosition = "left";String infService = Context.LAYOUT_INFLATER_SERVICE;LayoutInflater li;// 获得LAYOUT_INFLATER_SERVICE服务li = (LayoutInflater) context.getSystemService(infService);LinearLayout linearLayout = null;// 根据labelPosition属性的值装载不同的布局文件if ("left".equals(labelPosition))linearLayout = (LinearLayout) li.inflate(R.layout.labeledittext_horizontal, this);else if ("top".equals(labelPosition))linearLayout = (LinearLayout) li.inflate(R.layout.labeledittext_vertical, this);elsethrow new RuntimeException("labelPosition属性的值只能是left或top.");// 下面的代码从相应的布局文件中获得了TextView对象,并根据LabelTextView的属性值设置TextView的属性textView = (TextView) findViewById(R.id.textview);textView.setTextSize((float) labelFontSize);textView.setText(labelText);}}
2、main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="fill_parent"android:layout_height="fill_parent"android:orientation="vertical" ><TextViewandroid:id="@+id/textView"/><net.blogjava.mobile.widget.LabelEditTextandroid:id="@+id/first"android:layout_width="fill_parent"android:layout_height="wrap_content"labelFontSize="16"labelPosition="left"labelText="姓名:" /><net.blogjava.mobile.widget.LabelEditTextandroid:id="@+id/second"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_marginTop="20dp"labelFontSize="26"labelPosition="top"labelText="兴趣爱好" /></LinearLayout>
3、labeledittext_horizontal.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal" android:layout_width="fill_parent"android:layout_height="fill_parent"><TextView android:id="@+id/textview" android:layout_width="wrap_content"android:layout_height="wrap_content" /><EditText android:id="@+id/edittext" android:layout_width="fill_parent"android:layout_height="wrap_content" /> </LinearLayout>
4、labeledittext_vertical.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="fill_parent"android:layout_height="fill_parent"><TextView android:id="@+id/textview" android:layout_width="wrap_content"android:layout_height="wrap_content" /><EditText android:id="@+id/edittext" android:layout_width="fill_parent"android:layout_height="wrap_content" /> </LinearLayout>
5、效果
方式三、完全重写组件
实例:更换变盘指针后的时钟
1、HandClocl.java
package net.blogjava.mobile.widget;import java.util.Calendar; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.os.Handler; import android.util.AttributeSet; import android.view.View;public class HandClock extends View implements Runnable {private int clockImageResourceId;private Bitmap bitmap;private float scale;private float handCenterWidthScale;private float handCenterHeightScale;private int minuteHandSize;private int hourHandSize;private Handler handler = new Handler();public void run() {// 重新绘制View invalidate();// 重新设置定时器,在60秒后调用run方法handler.postDelayed(this, 60 * 1000);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);// 根据图像的实际大小等比例设置View的大小setMeasuredDimension((int) (bitmap.getWidth() * scale), (int) (bitmap.getHeight() * scale));}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Paint paint = new Paint();paint.setAntiAlias(true);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 * handCenterWidthScale;float centerY = bitmap.getHeight() * scale * handCenterHeightScale;// 表表盘中心点画一个半径为5的实心圆圈canvas.drawCircle(centerX, centerY, 5, paint);// 设置分针为3个象素粗paint.setStrokeWidth(3);Calendar calendar = Calendar.getInstance();int currentMinute = calendar.get(Calendar.MINUTE);int currentHour = calendar.get(Calendar.HOUR);// 计算分针和时间的角度double minuteRadian = Math.toRadians((360 - ((currentMinute * 6) - 90)) % 360);double hourRadian = Math.toRadians((360 - ((currentHour * 30) - 90)) % 360 - (30 * currentMinute / 60));// 在表盘上画分针canvas.drawLine(centerX, centerY, (int) (centerX + minuteHandSize * Math.cos(minuteRadian)), (int) (centerY - minuteHandSize * Math.sin(minuteRadian)), paint);// 设置实针为4个象素粗paint.setStrokeWidth(4);// 在表盘上画分针canvas.drawLine(centerX, centerY, (int) (centerX + hourHandSize * Math.cos(hourRadian)), (int) (centerY - hourHandSize * Math.sin(hourRadian)), paint);}public HandClock(Context context, AttributeSet attrs) {super(context, attrs);// 读取相应的属性值clockImageResourceId = attrs.getAttributeResourceValue(null, "clockImageSrc", 0);if (clockImageResourceId > 0)bitmap = BitmapFactory.decodeResource(getResources(), clockImageResourceId);scale = attrs.getAttributeFloatValue(null, "scale", 1);handCenterWidthScale = attrs.getAttributeFloatValue(null, "handCenterWidthScale", bitmap.getWidth() / 2);handCenterHeightScale = attrs.getAttributeFloatValue(null, "handCenterHeightScale", bitmap.getHeight() / 2);// 在读取分针和时针长度后,将其值按图像的缩放比例进行缩放minuteHandSize = (int) (attrs.getAttributeIntValue(null, "minuteHandSize", 0) * scale);hourHandSize = (int) (attrs.getAttributeIntValue(null, "hourHandSize", 0) * scale);int currentSecond = Calendar.getInstance().get(Calendar.SECOND);// 将定时器设在0分时执行run方法handler.postDelayed(this, (60 - currentSecond) * 1000);}@Overrideprotected void onDetachedFromWindow() {super.onDetachedFromWindow();// 删除回调类handler.removeCallbacks(this);}}
完整代码:http://pan.baidu.com/share/link?shareid=22336&uk=1829692564
这篇关于Android定制组件的三种方式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!