Android 用户界面---定制组件(Custom Components)
基于布局类View和ViewGroup的基本功能,Android为创建自己的UI界面提供了先进和强大的定制化模式。首先,平台包含了各种预置的View和ViewGroup子类---Widget和layout,可以使用它们来构造自己的UI界面。
部分的可以利用的widget包括:Button、TextView、EditText、ListView、CheckBox、RadioButton、Gallery、Spinner、以及比较特殊用途的AutoCompleteTextView、ImageSwitcher和TextSwitcher。
其中可利用的布局是:LinearLayout、FrameLayout、RelativeLayout以及其他的布局。更多的例子请看“共通布局对象”。http://developer.android.com/guide/topics/ui/layout-objects.html
如果遇到了没有预置的widget或layout的需求,可以创建自己的View子类。如果只需要对既存的widget或layout进行小的调整,那么只需简单的继承widget或layout,并且重写它们的方法。
创建自己的View子类,以便能够精准的控制屏幕元素的外观和功能。以下是用定制View对象来实现这种控制想法的一些例子:
1. 创建一个完全的定制化渲染的View类型,如用类似模拟电子控制的2D图形来渲染的音量控制按钮。
2. 把一组View组件组合成一个新的单一组件,制作一些像ComboBox(一个下拉列表和文本输入域的组合)、双面板选择器(左右两个列表面板,右边的列表面板中的项目与左边列表面板中的一个项目相关联)等组件。
3. 重写一个EditText组件在屏幕上的渲染的方法。
4. 捕获一些像按键一样的事件,并在某些定制的方法中处理它们(如游戏)。
基本方法
以下是创建自定义View组件需要要了解基本概要:
1. 自定义的View类要继承一个既存的View类或其子类;
2. 在子类重写父类的一些方法。要覆写的父类方法是用‘on’开头的,例如,onDraw()、onMeasure()和onKeyDown()等,这有点类似于重写Activity或ListActivity的生存周期回调的on…事件。
3. 使用新的扩展类,一旦完成,新扩展的类就能被用于替换基本的View对象。
提示:扩展类能够作为使用它们的Acticity的内部类来定义。这样对控制对它们的访问是有益的,当然可以创建一个新的公共的View类,这样就可以在应用程序范围内来使用。
完全定制化的组件
完全定制化的组件能够用于创建你所期望的显示效果的图形化组件。可以是看上去像旧的模拟仪表的图形化VU仪表,或者是一个长的歌词视图,有一个跳动的球沿着歌词移动,以便跟着这卡拉OK机歌唱,这两种情况,无论如何组织内置的组件都无法满足要求。
幸运的是,能够使用任意自己喜欢的方法来创建组件的外观和行为,唯一的限制就是你的想象力、屏幕的尺寸和可利用的处理能力(因为应用程序最终可能运行在比桌面工作站处理能力要弱的设备上)。
以下是创建完全定制组件的步骤:
1. 毋庸置疑,能够扩展的最通用的视图是View类,因此通常是继承这个View类来创建自己的新的组件;
2. 提供一个能够从XML中获取属性和参数的构造器,并且也能够使用自己属性和参数(如VU仪表的颜色和范围,指针的宽度和阻尼等);
3. 创建组件中可能的事件监听器、属性访问器和修饰符以及尽可能准确的行为等;
4. 覆写onMeasure()回调方法,如果想要组件显示一些东西,也要覆写onDraw()回调。虽然它们都有默认的行为,onDraw()回调默认什么也不做,onMeasure()方法默认的要设置组件的尺寸为100x100;
5. 覆写其他的需要on…方法。
扩展onDraw()和onMeasure()
onDraw()方法会把能够实现的任何想要的东西放到一个Canvas对象上,如2D图形、标准或定制的组件、样式化的文本、或其他任何能够想到的东西。
注意:View类不能使用3D图形。如果要使用3D图形,必须继承SurfaceView类,而不是View类,并且要在一个独立的线程中描画。
onMeasure()方法有点复杂,它是组件和它的容器之间的渲染约束的关键部分。覆写onMeasure(),以便准确高效的报告组件被包含部分的尺寸。由于来自父容器限制的要求,使得尺寸的测量有些复杂,并且组件的尺寸一旦被计算完成,就要调用setMeasureDimension()方法来保存测量的宽度和高度。如果在onMeasure()方法中调用setMeasureDimension()方法失败,这个结果在测量时将是一个异常的值。
在上层看,实现onMeasure()方法的步骤如下:
1. 要用父容器的宽度和高度的计量规格来调用被覆写的onMensure()方法(widthMeasureSpec和heightMeasureSpec参数都是代表了尺寸的整数),这两个参数应该作为生成组件的宽度和高度的约束要求。对于这些规格约束类型的完整说明可以在View类说明的View.onMeasure(int,int)方法中找到。
2. 组件的onMeasure()方法应该计算用于渲染组件所需的尺寸(宽度和高度)。组件应该尽量保留在被传入的规格范围内,尽管它能够选择超出规格范围(在这种情况下,父容器能够选择做的事情包括:裁剪、滚动、抛出异常、或者要求onMeasure()方法用不同的尺寸规格再试)。
3. 一旦组件的宽度和高度被计算完成,就必须调用setMeasuredDimension(int width, int height)方法来保存计算结果。不这样做就会抛出一个异常。
下表是framework调用View类的其他标准方法:
分类 |
方法 |
说明 |
Creation |
Constructors |
构造器的调用有两种类型:1.在代码中创建View对象;2.用布局文件填充View对象。第二种类型应该解析和应用布局文件中的任何属性定义。 |
onFinishInflate() |
View对象和它的所有子对象都用XML填充完之后,调用这个方法。 |
|
Layout |
onMeasure(int, int) |
调用这个方法决定View对象及其所有子对象的尺寸要求。 |
onLayout(boolean,int,int,int,int) |
当View对象给它的所有子对象分配尺寸和位置时,调用这个方法。 |
|
onSizeChanged(int,int,int,int) |
当View对象的尺寸发生改变时,调用这个方法。 |
|
Drawing |
onDraw(Canvas) |
当View对象渲染它的内容时,调用这个方法。 |
Event |
onKeyDown(int,KeyEvent) |
当一个键的按下事件发生时,调用这个方法 |
onKeyUp(int,KeyEvent) |
当一个键弹起事件发生时,调用这个方法 |
|
onTrackballEvent(MotionEvent) |
当鼠标轨迹球滚动事件发生时,调用这个方法。 |
|
onTouchEvent(MotionEvent) |
当触屏事件发生时,调用这个方法。 |
|
Focus |
onFocusChanged(boolean,int,Rect) |
当View对象获取或失去焦点时,调用这个方法。 |
onWindowFocusChanged(boolean) |
当包含View对象的窗口获得或失去焦点时,调用这个方法。 |
|
Attaching |
onAttachedToWindow() |
当View对象被绑定到一个窗口时,调用这个方法。 |
onDetachedFromWindow() |
当View对象被从它的窗口中分离的时候,调用这个方法。 |
|
onWindowVisibilityChanged(int) |
当包含View对象的窗口的可见性发生改变时,调用这个方法。 |
|
定制View的例子
在API Demos中提供了一个定制的View对象的例子:CustomView。这个定制的View定义在LabelView类中。
LabelView示例展示了很多定制组件的不同特征:
1. 继承View类的完全定制化的组件;
2. 参数化的带有View填充参数(在XML中定义的参数)方式构造View对象。有一些填充参数使用通过这个View的父类传递过来的,还有一些用于labelView对象而定义的定制的属性;
3. 你所期望看到的标准的公共类型的方法,如setText()、setTextSize()、setTextColor()等等;
4. 一个重写的onMeasure()方法,它决定和设置了组件的渲染尺寸。(注意:在LabelView类中,实际的工作是由一个私有的measureWidth()方法来做的。)
5. 一个重写的onDraw()方法,它在提供的Canvas上描画标签。
从这个示例的custom_view_1.xml中,能够看到一些LabelView定制View的用法。实际上,可以看到android:命名空间参数和定制的app:命名空间的组合。这些app:参数是LabelView类所承认的并用于工作的一些定制化的属性,并且这些参数在示例的R资源定义类的styleable内部类中被定义。
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;public class CrossView extends View {private float mRotation;private Paint mPaint;public CrossView( Context context, AttributeSet attrs ) {//AttributeSet对象在实例化时被系统传给了视图super( context, attrs );//start 创建paint对象mPaint = new Paint();mPaint.setAntiAlias( true );mPaint.setColor( 0xFFFFFFFF );//end 创建paint对象//使用obtainStyledAttributes方法来创建一个TypedArray,这是访问存储于AttributeSet中的值的一个方便类,这类执行内部缓存,//所以当你结束使用它之后随时调用回收函数。注意:需同时使用<declare-styleable>名称和<arr>名称的访问自定义属性TypedArray arr = getContext().obtainStyledAttributes( attrs,R.styleable.cross );int color = arr.getColor( R.styleable.cross_android_color, Color.WHITE );float rotation = arr.getFloat( R.styleable.cross_rotation, 0f );//remember to call this when finishedarr.recycle();setColor(color);setRotation(rotation);}private void setRotation( float rotation ) {// TODO Auto-generated method stubmRotation = rotation;}private void setColor( int color ) {// TODO Auto-generated method stubmPaint.setColor( color );}//重写onMeasure方法@Overrideprotected void onMeasure( int widthMeasureSpec, int heightMeasureSpec ) {// TODO Auto-generated method stubsuper.onMeasure( widthMeasureSpec, heightMeasureSpec );//需要使用计算好的宽和高的值作为该方法的实参setMeasuredDimension( calculateMeasure(widthMeasureSpec), calculateMeasure(heightMeasureSpec) );}float[] mPoints = {0.5f,0f,0.5f,1f,0f,0.5f,1f,0.5f};@Overrideprotected void onDraw( Canvas canvas ) {// TODO Auto-generated method stubsuper.onDraw( canvas );canvas.save();//所有的在画布上绘图的调用都应当受对应的sava()和restore()的约束int scale = getWidth();canvas.scale( scale, scale );canvas.rotate( mRotation );canvas.drawLines( mPoints, mPaint );//绘制十字的两条线canvas.restore();//所有的在画布上绘图的调用都应当受对应的sava()和restore()的约束}private static final int DEFAULT_SIZE = 100;//默认的试图尺寸//实现计算测量值的代码private int calculateMeasure(int measureSpec){int result = ( int ) ( DEFAULT_SIZE*getResources().getDisplayMetrics().density );int specMode = MeasureSpec.getMode( measureSpec );//在MeasureSpec中检索模式int specSize = MeasureSpec.getSize( measureSpec );//在MeasureSpec中检索尺寸//基于模式选择尺寸if(specMode == MeasureSpec.EXACTLY){result = specSize;}else if(specMode == MeasureSpec.AT_MOST){result = Math.min( result, specSize );}return result;}
}
(二)自定义属性<?xml version="1.0" encoding="utf-8"?>
<!-- 该文件被放置在res/values/目录下 -->
<resources><!-- 声明属性 --><declare-styleable name="cross"><attr name="android:color"/><attr name="rotation" format="string"/></declare-styleable><!-- <attr name="test" format="string"/><declare-styleable name="foo"><attr name="test"/></declare-styleable><declare-styleable name="bar"><attr name="test"/></declare-styleable> -->
</resources>
(三)在XML中使用自定义View
<?xml version="1.0" encoding="utf-8"?><!-- 要使用在XML中的自定义属性,首先必须为视图声明命名空间 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:example="http://schemas.android.com/apk/res/com.example"android:orientation="vertical"android:layout_width="fill_parent"android:layout_height="fill_parent"><!-- 添加CrossView --><com.example.CrossViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"/><com.example.CrossViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"example.rotation="30" android:color="#0000FF"/>/><com.example.CrossViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"example.rotation="40" android:color="#FFFF00"/>
</LinearLayout>
转载于:https://www.cnblogs.com/wxishang1991/p/android.html
Android 用户界面---定制组件(Custom Components)相关推荐
- Android用户界面 UI组件--TextView及其子类(二) Button,selector选择器,sharp属性
1.XML文件中的OnClick 属性可以指定在Activity中处理点击事件的方法,Activity中必须定义该属性指定的值作为方法的名字且有一个View类型的参数,表示此物件被点击. 2.使用se ...
- RaSa2.5.x配置之二:管道组件(Pipeline Components)
目录 语言模型(Language Models) MitieNLP SpacyNLP HFTransformersNLP 分词器(Tokenizers) WhitespaceTokenizer Jie ...
- Android定制组件之图文展示之中国好声音
传送门☞轮子的专栏☞转载请注明☞http://blog.csdn.net/leverage_1229 今天我们学习如何自定义TextView组件,让它既能显示文本,又能显示图像,达到"图文并 ...
- android用户界面组件都是放置在,Android开发工程师第十章 节 用户界面高级组件.ppt...
Android开发工程师第十章 节 用户界面高级组件.ppt 电子相册的设计与实现 4.图片放大与缩小显示的实现 在触摸ImageSwitcher中显示的图片后,全屏显示该图片,要全屏显示该图片,只要 ...
- android java与界面的关联_Android Studio安卓学习笔记(三)Android用户界面的设计布局与组件(一)用户界面布局设计(1)...
当我们创建了一个安卓项目后,我们会发现真正建立一个完善的安卓项目并不是想象的那么容易.其实和设计GUI可视化界面一样,开发安卓也需要考虑很多方面,主要考虑的还是界面布局和需要的组件. 一:Androi ...
- Android Studio安卓学习笔记(三)Android用户界面的设计布局与组件(一)用户界面布局设计(1)...
当我们创建了一个安卓项目后,我们会发现真正建立一个完善的安卓项目并不是想象的那么容易.其实和设计GUI可视化界面一样,开发安卓也需要考虑很多方面,主要考虑的还是界面布局和需要的组件. 一:Androi ...
- Android 之 四大组件、六大布局、五大存储
Android 之四大组件.六大布局.五大存储:https://blog.csdn.net/shenggaofei/article/details/52450668 Android 四大组件.五大存储 ...
- Android四大基本组件介绍与生命周期
Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器. 一:了解四大基本组件 Activity ...
- Android四大基本组件和生命周期的介绍
Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器. 一:了解四大基本组件 Activity ...
最新文章
- ubuntu 配置nfs server
- 7th思妙想 Fun事连连,今天范式7岁啦!
- ITK:将矢量图像投射为另一种类型
- Python 去除列表中重复的元素
- HttpClient和DefaultHttpClient
- 一维数组反转c语言_C语言实现数组的循环左移,右移,翻转的示例
- Yii2语言国际化配置
- Could not find the required component ‘tf2_geometry_msgs‘. The following CMake error indicates that
- 企业微信PC端打不开h5页面
- 工作中,掌握这四个说话技巧,再也不用担心自己不会说话
- 小米java模拟器_Android沉浸式简单实现(暂未测试全部机型,根据资料修改,模拟器,小米6,,荣耀做了简单测试)...
- 获取IFeatureWorkspace所有要素类、表
- DDOS防御的发展和演变
- SQL注入攻击及危害
- 黑白照片如何变彩色?建议收藏这些方法
- 仿淘宝开放平台之消息服务——消息中心推送消息至消费者
- Windows 下编译 taglib
- 于明:保护个人隐私的安全方案
- 异地就医联网进展如何?正式签约定点医疗机构已达数百家
- php把字符串变为数组_php怎么把字符串转换成数组?