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.LabelEditText
15         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属性的资源ID
19         int resourceId = attrs.getAttributeResourceValue(null, "labelText", 0);
20         // 未获得资源ID,继续读取属性值
21         if (resourceId == 0)
22             labelText = attrs.getAttributeValue(null, "labelText");
23         // 从资源文件中获得labelText属性的值
24         else
25             labelText = getResources().getString(resourceId);
26         // 如果按两种方式都未获得labelTex属性的值,表示未设置该属性,抛出异常
27         if (labelText == null) {
28             throw new RuntimeException("必须设置labelText属性.");
29         }
30         // 获得labelFontSize属性的资源ID
31         resourceId = attrs.getAttributeResourceValue(null, "labelFontSize", 0);
32         // 继续读取labelFontSize属性的值,如果未设置该属性,将属性值设为14
33         if (resourceId == 0)
34             labelFontSize = attrs.getAttributeIntValue(null, "labelFontSize",
35                     14);
36         // 从资源文件中获得labelFontSize属性的值
37         else
38             labelFontSize = getResources().getInteger(resourceId);
39         // 获得labelPosition属性的资源ID
40         resourceId = attrs.getAttributeResourceValue(null, "labelPosition", 0);
41         // 继续读取labelPosition属性的值
42         if (resourceId == 0)
43             labelPosition = attrs.getAttributeValue(null, "labelPosition");
44         // 从资源文件中获得labelPosition属性的值
45         else
46             labelPosition = getResources().getString(resourceId);
47         // 如果未设置labelPosition属性值,将该属性值设为left
48         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         else
64             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.IconTextView
12         android:layout_width="fill_parent" android:layout_height="wrap_content"
13         android:text="第三个图标" android:textSize="36dp" mobile:iconSrc="@drawable/android" />
14     <cn.eoe.widget.IconTextView
15         android:layout_width="fill_parent" android:layout_height="wrap_content"
16         android:text="第四个图标" android:textSize="48dp" mobile:iconSrc="@drawable/android" />
17     <cn.eoe.widget.IconTextView
18         android:layout_width="fill_parent" android:layout_height="wrap_content"
19         android:text="第五个图标" android:textSize="36dp" mobile:iconSrc="@drawable/android" />
20     <cn.eoe.widget.IconTextView
21         android:layout_width="fill_parent" android:layout_height="wrap_content"
22         android:text="第六个图标" android:textSize="24dp" mobile:iconSrc="@drawable/android" />
23     <cn.eoe.widget.IconTextView
24         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     // 图像资源ID
15     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     @Override
27     protected void onDraw(Canvas canvas) {
28         if (bitmap != null) {
29
30             // 从原图上截取图像的区域,在本例中为整个图像
31             Rect src = 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) bitmap
46                     .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.IconTextView
13         android:layout_width="fill_parent" android:layout_height="wrap_content"
14         android:text="第三个图标" android:textSize="36sp" app:iconSrc="@drawable/android" />
15     <cn.eoe.widget.IconTextView
16         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.IconTextView
20         android:layout_width="fill_parent" android:layout_height="wrap_content"
21         android:text="第五个图标" android:textSize="36sp" app:iconSrc="@drawable/android" />
22     <cn.eoe.widget.IconTextView
23         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.IconTextView
27         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     // 图像资源ID
15     private int resourceId = 0;
16     // icon位置 0:left 1:right
17     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     @Override
35     protected void onDraw(Canvas canvas) {
36         if (bitmap != null) {
37
38             // 从原图上截取图像的区域,在本例中为整个图像
39             Rect src = 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 = left
58                     + (int) (textHeight * (bitmap.getWidth() / (float) bitmap
59                             .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 }

时间: 2024-12-29 21:43:57

3、用继承和组合方式定制控件的相关文章

用继承和组合方式定制控件

1. 定制控件的方式 2. 带标签的文本编辑框(不带命名空间) 3. 带图标的文本框(带命名空间) 4. 控件属性验证 1. 定制控件的方式 <1>继承其他控件类 Ctrl + 左键 --->EditText <2>组合方式. 当前控件类从容器类继承, 并将若干个控件添加到当前容器中 <3>绘制控件. 也就是控件类从View继承, 并在onDraw方法中从零开始绘制控件, 例如TextView 2. 带标签的文本编辑框(不带命名空间)

2、继承和组合,绘制方式定制控件

定制控件的方式 1.继承其他控件类. 例如,EditText,是继承TextView. 例子:带图标的文本框 public IconTextView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.IconTextView); resourceId = typedArray.

WorldWind源码剖析系列:窗口定制控件类WorldWindow

在WorldWindow定制控件是从Control类派生出来的,需要自己操纵GDI+绘制所需要的界面效果,比较耗费精力(区别于用户控件UserControl,也叫组合控件,大多是对.NET工具箱提供的默认基础控件进行的组合和轻量级的改变,实现起来比较简单).为了明确定制控件Control和用户控件UserControl之间的体系关系,此处给出了Control类继承层次结构(源自MSDN): 在WorldWindow中星球球体的渲染和经纬网格的渲染时分别绘制的,星球由类World表示,经纬网格.

VC/MFC 工具栏上动态添加组合框等控件的方法

引言 工具条作为大多数标准的Windows应用程序的一个重要组成部分,使其成为促进人机界面友好的一个重要工具.通过工具条极大方便了用户对程序的操作,但是在由Microsoft Visual C++开发环境所创建的应用程序框架中的工具条只是一个简单的按钮的集合,在功能上也仅仅是起到了菜单快捷方式的作用,而没有做到象VC.Word等软件的工具条那样,提供多种不同类型的标准控件如组合框.编辑框等.尤其是组合框在添加到工具条上后,可将原本需要在弹出对话框中完成的交互操作在工具条上就可以进行,从而在很大程

Android定制控件-带图像的TextView

最近在学习Android,边看书边敲代码,看到是李宁的Android开发完全讲义,因为是对着书本敲的, 所以代码跟原书的代码基本上是一致的 看到第四章,定制控件,觉得需要记录下些东西,所有把代码写到博客作为自己以后查阅的资料. 先上效果图 在src新建net.blogjava.mobile.widget/IconTextView.java 代码如下: package net.blogjava.mobile.widget; import android.content.Context; impor

定制控件背景颜色与背景位图

本文讲述如何定制控件的背景颜色和背景位图的技巧. 首先要说一下控件的绘制过程:当控件的某个区域需要重绘时,都会触发WM_ERASEBKGND和WM_PAINT消息.比如控件的某个区域被另一个程序的窗口挡住了,而后那个窗口又被移走了,这时控件被挡住的内容就需要重新绘制了. 第一步:系统向控件发送WM_ERASEBKGND消息以实现背景的擦除工作(有时不发送,比如用户可能调用InvalidateRect(),其参数却指定不擦除背景,这样就没有这个消息): 第二步:系统向控件的窗口过程发送WM_PAI

未能加载视图状态。正在向其中加载视图状态的控件树必须与前一请求期间用于保存视图状态的控件树相匹配。例如,当以动态方式添加控件时,在回发期间添加的控件必须与在初始请求期间添加的控件的类型和位置相匹配

信息: 未能加载视图状态.正在向其中加载视图状态的控件树必须与前一请求期间用于保存视图状态的控件树相匹配.例如,当以动态方式添加控件时,在回发期间添加的控件必须与在初始请求期间添加的控件的类型和位置相匹配. 数据源: System.Web 堆栈信息: 在 System.Web.UI.Control.LoadViewStateRecursive(Object savedState) 在 System.Web.UI.Control.LoadChildViewStateByIndex(ArrayLis

android自定义View之(七)------自定义控件组合仿actionbar控件

我们前面写了6个自定义view的样例,这都是全新自已画的控件.在这个样例中,我们来用几个现有的控件来组合成一个新的控件. 效果图: 我们用二个Button和一个TextView组合来成为一个actionbar,下面先来一个效果图: 关键代码: (1)res/layout/custom_action_bar.xml----组合控件布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android&quo

使用appearance proxy定制控件的默认外观(详解)

控件的外观,受到tint color,background image, background color等属性的共同影响,通常要修改某个控件对象的外观,就去调用上面属性的相关setter方法(或者其他可以修改它们的方法)就可以了.但是,如果希望整个app中的控件都保持一致的风格,比如所有button的风格(指的是大小,背景图,形状等)都一样,那么一个一个去重复设置每个button的风格,就显得太麻烦了.如果可以给Button类设定一个默认外观,就方便多了.appearance proxy就可以