首页 > 代码库 > 3、用继承和组合方式定制控件
3、用继承和组合方式定制控件
定制控件的方式
? 继承其它控件类(EditText、Button)
? 组合方式。当前控件类从容器类继承,并将若干个控件添加到当前的容器中。
? 绘制控件,也就是控件类从View继承,并在onDraw方法中从零绘制控件。例如,TextView。
带标签的文本编辑框(不带命名空间)
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android:layout_height="fill_parent" 5 android:orientation="vertical" > 6 7 <cn.eoe.widget.LabelEditText 8 android:layout_width="fill_parent" 9 android:layout_height="wrap_content"10 labelFontSize="16"11 labelPosition="left"12 labelText="姓名:" />13 14 <cn.eoe.widget.LabelEditText15 android:layout_width="fill_parent"16 android:layout_height="wrap_content"17 android:layout_marginTop="20dp"18 labelFontSize="26"19 labelPosition="top"20 labelText="兴趣爱好" />21 22 </LinearLayout>
1 package cn.eoe.widget; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.view.LayoutInflater; 6 import android.widget.LinearLayout; 7 import android.widget.TextView; 8 import cn.eoe.label.edittext.R; 9 10 public class LabelEditText extends LinearLayout {11 private TextView textView;12 private String labelText;13 private int labelFontSize;14 private String labelPosition;15 16 public LabelEditText(Context context, AttributeSet attrs) {17 super(context, attrs);18 // 读取labelText属性的资源ID19 int resourceId = attrs.getAttributeResourceValue(null, "labelText", 0);20 // 未获得资源ID,继续读取属性值21 if (resourceId == 0)22 labelText = attrs.getAttributeValue(null, "labelText");23 // 从资源文件中获得labelText属性的值24 else25 labelText = getResources().getString(resourceId);26 // 如果按两种方式都未获得labelTex属性的值,表示未设置该属性,抛出异常27 if (labelText == null) {28 throw new RuntimeException("必须设置labelText属性.");29 }30 // 获得labelFontSize属性的资源ID31 resourceId = attrs.getAttributeResourceValue(null, "labelFontSize", 0);32 // 继续读取labelFontSize属性的值,如果未设置该属性,将属性值设为1433 if (resourceId == 0)34 labelFontSize = attrs.getAttributeIntValue(null, "labelFontSize",35 14);36 // 从资源文件中获得labelFontSize属性的值37 else38 labelFontSize = getResources().getInteger(resourceId);39 // 获得labelPosition属性的资源ID40 resourceId = attrs.getAttributeResourceValue(null, "labelPosition", 0);41 // 继续读取labelPosition属性的值42 if (resourceId == 0)43 labelPosition = attrs.getAttributeValue(null, "labelPosition");44 // 从资源文件中获得labelPosition属性的值45 else46 labelPosition = getResources().getString(resourceId);47 // 如果未设置labelPosition属性值,将该属性值设为left48 if (labelPosition == null)49 labelPosition = "left";50 51 String infService = Context.LAYOUT_INFLATER_SERVICE;52 LayoutInflater li;53 // 获得LAYOUT_INFLATER_SERVICE服务54 li = (LayoutInflater) context.getSystemService(infService);55 LinearLayout linearLayout = null;56 // 根据labelPosition属性的值装载不同的布局文件57 if ("left".equals(labelPosition))58 linearLayout = (LinearLayout) li.inflate(59 R.layout.labeledittext_horizontal, this);60 else if ("top".equals(labelPosition))61 linearLayout = (LinearLayout) li.inflate(62 R.layout.labeledittext_vertical, this);63 else64 throw new RuntimeException("labelPosition属性的值只能是left或top.");65 66 // 下面的代码从相应的布局文件中获得了TextView对象,并根据LabelTextView的属性值设置TextView的属性67 textView = (TextView) findViewById(R.id.textview);68 // textView.setTextSize((float)labelFontSize);69 textView.setTextSize(labelFontSize);70 textView.setText(labelText);71 72 }73 74 }
带图标的文本框(带命名空间)
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:mobile="http://cn.eoe.icon.textview" android:orientation="vertical" 4 android:layout_width="fill_parent" android:layout_height="fill_parent"> 5 <cn.eoe.widget.IconTextView 6 android:layout_width="fill_parent" android:layout_height="wrap_content" 7 android:text="第一个图标" mobile:iconSrc="@drawable/android" /> 8 <cn.eoe.widget.IconTextView 9 android:layout_width="fill_parent" android:layout_height="wrap_content"10 android:text="第二个图标" android:textSize="24dp" mobile:iconSrc="@drawable/android" />11 <cn.eoe.widget.IconTextView12 android:layout_width="fill_parent" android:layout_height="wrap_content"13 android:text="第三个图标" android:textSize="36dp" mobile:iconSrc="@drawable/android" />14 <cn.eoe.widget.IconTextView15 android:layout_width="fill_parent" android:layout_height="wrap_content"16 android:text="第四个图标" android:textSize="48dp" mobile:iconSrc="@drawable/android" />17 <cn.eoe.widget.IconTextView18 android:layout_width="fill_parent" android:layout_height="wrap_content"19 android:text="第五个图标" android:textSize="36dp" mobile:iconSrc="@drawable/android" />20 <cn.eoe.widget.IconTextView21 android:layout_width="fill_parent" android:layout_height="wrap_content"22 android:text="第六个图标" android:textSize="24dp" mobile:iconSrc="@drawable/android" />23 <cn.eoe.widget.IconTextView24 android:layout_width="fill_parent" android:layout_height="wrap_content"25 android:text="第七个图标" mobile:iconSrc="@drawable/android" />26 27 </LinearLayout> 28
1 package cn.eoe.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 private final String namespace = "http://cn.eoe.icon.textview";14 // 图像资源ID15 private int resourceId = 0;16 private Bitmap bitmap;17 18 public IconTextView(Context context, AttributeSet attrs) {19 super(context, attrs);20 21 resourceId = attrs.getAttributeResourceValue(namespace, "iconSrc", 0);22 if (resourceId > 0)23 bitmap = BitmapFactory.decodeResource(getResources(), resourceId);24 }25 26 @Override27 protected void onDraw(Canvas canvas) {28 if (bitmap != null) {29 30 // 从原图上截取图像的区域,在本例中为整个图像31 Rect src = http://www.mamicode.com/new Rect();32 // 将截取的图像复制到bitmap上的目标区域,在本例中与复制区域相同33 Rect target = new Rect();34 src.left = 0;35 src.top = 0;36 src.right = bitmap.getWidth();37 src.bottom = bitmap.getHeight();38 39 int textHeight = (int) getTextSize();40 target.left = 0;41 // 计算图像复制到目录区域的纵坐标。由于TextView中文本内容并不是从最顶端开始绘制的,因此,需要重新计算绘制图像的纵坐标42 target.top = (int) ((getMeasuredHeight() - getTextSize()) / 2) + 1;43 target.bottom = target.top + textHeight;44 // 为了保证图像不变形,需要根据图像高度重新计算图像的宽度45 target.right = (int) (textHeight * (bitmap.getWidth() / (float) bitmap46 .getHeight()));47 // 开始绘制图像48 canvas.drawBitmap(bitmap, src, target, getPaint());49 // 将TextView中的文本向右移动一定的距离(在本例中移动了图像宽度加2个象素点的位置)50 51 canvas.translate(target.right + 2, 0);52 }53 super.onDraw(canvas);54 55 }56 57 }
控件属性验证
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res/cn.eoe.icon.textview.ext" 3 android:orientation="vertical" android:layout_width="fill_parent" 4 android:layout_height="fill_parent"> 5 <cn.eoe.widget.IconTextView 6 android:layout_width="fill_parent" android:layout_height="wrap_content" 7 android:text="第一个图标" app:iconSrc="@drawable/android" app:iconPosition="left" /> 8 <cn.eoe.widget.IconTextView 9 android:layout_width="fill_parent" android:layout_height="wrap_content"10 android:text="第二个图标" android:textSize="24sp" app:iconSrc="@drawable/android"11 app:iconPosition="right" />12 <cn.eoe.widget.IconTextView13 android:layout_width="fill_parent" android:layout_height="wrap_content"14 android:text="第三个图标" android:textSize="36sp" app:iconSrc="@drawable/android" />15 <cn.eoe.widget.IconTextView16 android:layout_width="fill_parent" android:layout_height="wrap_content"17 android:text="第四个图标" android:textSize="48sp" app:iconSrc="@drawable/android"18 app:iconPosition="right" />19 <cn.eoe.widget.IconTextView20 android:layout_width="fill_parent" android:layout_height="wrap_content"21 android:text="第五个图标" android:textSize="36sp" app:iconSrc="@drawable/android" />22 <cn.eoe.widget.IconTextView23 android:layout_width="fill_parent" android:layout_height="wrap_content"24 android:text="第六个图标" android:textSize="24sp" app:iconSrc="@drawable/android"25 app:iconPosition="right" />26 <cn.eoe.widget.IconTextView27 android:layout_width="fill_parent" android:layout_height="wrap_content"28 android:text="第七个图标" app:iconSrc="@drawable/android" />29 30 </LinearLayout> 31
1 package cn.eoe.widget; 2 3 import android.content.Context; 4 import android.content.res.TypedArray; 5 import android.graphics.Bitmap; 6 import android.graphics.BitmapFactory; 7 import android.graphics.Canvas; 8 import android.graphics.Rect; 9 import android.util.AttributeSet;10 import android.widget.TextView;11 import cn.eoe.icon.textview.ext.R;12 13 public class IconTextView extends TextView {14 // 图像资源ID15 private int resourceId = 0;16 // icon位置 0:left 1:right17 private int iconPosition = 0;18 private Bitmap bitmap;19 20 public IconTextView(Context context, AttributeSet attrs) {21 super(context, attrs);22 23 TypedArray typedArray = context.obtainStyledAttributes(attrs,24 R.styleable.IconTextView);25 26 resourceId = typedArray.getResourceId(R.styleable.IconTextView_iconSrc,27 0);28 if (resourceId > 0)29 bitmap = BitmapFactory.decodeResource(getResources(), resourceId);30 iconPosition = typedArray.getInt(R.styleable.IconTextView_iconPosition,31 0);32 }33 34 @Override35 protected void onDraw(Canvas canvas) {36 if (bitmap != null) {37 38 // 从原图上截取图像的区域,在本例中为整个图像39 Rect src = http://www.mamicode.com/new Rect();40 // 将截取的图像复制到bitmap上的目标区域,在本例中与复制区域相同41 Rect target = new Rect();42 src.left = 0;43 src.top = 0;44 src.right = bitmap.getWidth();45 src.bottom = bitmap.getHeight();46 47 int textHeight = (int) getTextSize();48 int left = 0;49 if (iconPosition == 1) {50 left = (int) getPaint().measureText(getText().toString()) + 2;51 }52 target.left = left;53 // 计算图像复制到目录区域的纵坐标。由于TextView中文本内容并不是从最顶端开始绘制的,因此,需要重新计算绘制图像的纵坐标54 target.top = (int) ((getMeasuredHeight() - getTextSize()) / 2) + 1;55 target.bottom = target.top + textHeight;56 // 为了保证图像不变形,需要根据图像高度重新计算图像的宽度57 target.right = left58 + (int) (textHeight * (bitmap.getWidth() / (float) bitmap59 .getHeight()));60 // 开始绘制图像61 canvas.drawBitmap(bitmap, src, target, getPaint());62 // 将TextView中的文本向右移动一定的距离(在本例中移动了图像宽度加2个象素点的位置)63 if (iconPosition == 0)64 canvas.translate(target.right + 2, 0);65 }66 super.onDraw(canvas);67 68 }69 70 }
3、用继承和组合方式定制控件
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。