自定义View的界面和行为
来源:互联网 发布:各省地方政府债务数据 编辑:程序博客网 时间:2024/05/16 13:58
Vew对象是所有控件和布局对象的基类, 呈现给用户的界面基本上就一棵view树, 要实现自定义的view对象, 可以继承已有的控件对象,如TextView, Button等,在对其中的一些方法进行重写来覆盖原先控件对象的行为和界面,也可以完全从View对象继承,然后重写VIew对象的一些重要方法,如onMeasure(), onDraw(),(这些on-like方法基本是对象对系统中特定事件所做出的反应, 如onTouchEvent,当用户点击一个控件时,系统就会回调该控件的onTouchEvent方法来通知对象用户点击了它,然后我们就可以在这个方法实现一些逻辑来对用户的行为做出反应, 这也是基于事件驱动/面向对象编程的一个特点,每一个对象有自己的属性(对象的描述)和行为(对外部事件做出的反应)), 系统在进行界面绘制的时候就会调用自定义控件的onMeasure和 onDraw等方法来完成界面的显示, 参考ApiDemo中的CustomView的实现,可以看出自定义View的几个步骤:
1> 定义一个继承View的类,这个类可以做为一个Activity中的一个内部类来实现(google推荐的做法), 也可以单独实现一个类,这样可以从xml布局文件中定义自定义的控件,不需要用代码是实例化一个对象。
2>控件重要方法/行为的重写, 有几个必需要实现的方法:
1.对象的构造函数, 一般要实现两个构造函数, 一个用于代码实例化对象,一个用于从xml布局文件中来构造特定属性的对象,通用的做法是在xml布局文件中定义控件对象,这样方便控件的布局。
2. onMeasure(int widthMeasureSpec, int heightMeasureSpec) 方法, 系统在绘制对象时,首先得确定对象在屏幕上占用多大的范围,因此在这个方法中,必须得确定好控件的尺寸然后通过一个特定的函数接口(setMeasuredDimension(width, height))去通知系统有关该控件的尺寸信息。系统传递进来的两个参数是一个约束条件,控件到底占据多大的尺寸由这两个参数决定, 每一个参数其实一个MeasureSpec对象,该对象包含了Measure's Mode和Size两个属性:
Mode CutsomView's size
UNSPECIFIED 系统对对象的size没进行约束,可以任意设置
EXACTLY 系统对对象的size已经定死了,只能为MeasureSpec对象中指定的size
AT_MOST 系统对对象的最大size进行了约束,即该对象的size不能超过MeasureSpec对象中指定的size
eg:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec)); } /** * Determines the width of this view * @param measureSpec A measureSpec packed into an int * @return The width of the view, honoring constraints from measureSpec */ private int measureWidth(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); //获取Mode. int specSize = MeasureSpec.getSize(measureSpec); //约束的Size. if (specMode == MeasureSpec.EXACTLY) { // We were told how big to be result = specSize; } else { // Measure the text result = (int) mTextPaint.measureText(mText) + getPaddingLeft() + getPaddingRight(); if (specMode == MeasureSpec.AT_MOST) { // Respect AT_MOST value if that was what is called for by measureSpec result = Math.min(result, specSize); } } return result; } /** * Determines the height of this view * @param measureSpec A measureSpec packed into an int * @return The height of the view, honoring constraints from measureSpec */ private int measureHeight(int measureSpec) { int result = 0; int specMode = MeasureSpec.getMode(measureSpec); int specSize = MeasureSpec.getSize(measureSpec); mAscent = (int) mTextPaint.ascent(); if (specMode == MeasureSpec.EXACTLY) { // We were told how big to be result = specSize; } else { // Measure the text (beware: ascent is a negative number) result = (int) (-mAscent + mTextPaint.descent()) + getPaddingTop() + getPaddingBottom(); if (specMode == MeasureSpec.AT_MOST) { // Respect AT_MOST value if that was what is called for by measureSpec result = Math.min(result, specSize); } } return result; }
3. void onDraw(Canvas canvas) , 确定好控件的尺寸之后,当系统开始绘图时,会调用View对象的onDraw方法,系统会传进来一个Canvas(画布)对象, 这个对象封装了一些draw-like的方法,由于这些方法需要一个Paint对象的参数,因此在自定义View的内部实现, 一般还得有个Paint对象, 这个对象顾名思义,画笔的意思,用于控制绘制过程中参数的设定,如颜色,大小 ,风格等(The Paint class holds the style and color information about how to draw geometries, text and bitmaps.)
Paint对象常用方法
setStrokeWidth(float width) //设置画笔的宽度(一般应用于几何图形)
setTextSize(float textSize) //绘制文字时的宽度
。。。
Canvas对象常用方法
Parameters
drawPoint(float x, float y, Paint paint) //画点
drawPoints(float[] pts, int offset, int count, Paint paint)
drawLine(float startX, float startY, float stopX, float stopY, Paint paint) //画线
drawCircle(float cx, float cy, float radius, Paint paint) //画圆
3> 通过上述的步骤实现了一个自定义控件后, 就可以拿来使用了,一种是通过代码来实现,可以在代码中new一个对象,然后通过Layout对象的addView
方法进行显示,但是这种方法有点复杂,没有xml布局文件那样直观和方便。因此还是用通用的做法来进行View的布局吧。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.android.apis"
//绿色的是属性命名空间的名字,红色的是包名,蓝色的。。。
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
//自定义控件的定义得加完整的包名和类名
<com.example.android.apis.view.LabelView
android:background="@drawable/red"
android:layout_width="match_parent"
android:layout_height="wrap_content"
//app开头的属性为自定义的属性,一般在对象的构造函数中进行解析
app:text="Red"/>
<com.example.android.apis.view.LabelView
android:background="@drawable/blue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:text="Blue" app:textSize="20dp"/>
<com.example.android.apis.view.LabelView
android:background="@drawable/green"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:text="Green" app:textColor="#ffffffff" />
</LinearLayout>
自定义属性的定义: 在工程res/values/目录下创建一个attrs.xml文件,在该文件中自定义属性的写法:
<resources>
<declare-styleable name="LabelView"> //定义一个属性集
<attr name="text" format="string" /> //定义一个属性
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
</declare-styleable>
</resources>
自定义属性的解析:
public LabelView(Context context, AttributeSet attrs) {
super(context, attrs);
initLabelView();
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.LabelView); //获取属性集合
CharSequence s = a.getString(R.styleable.LabelView_text); //获取LabelView对象的text属性值
if (s != null) {
setText(s.toString());
}
// Retrieve the color(s) to be used for this view and apply them.
// Note, if you only care about supporting a single color, that you
// can instead call a.getColor() and pass that to setTextColor().
setTextColor(a.getColor(R.styleable.LabelView_textColor, 0xFF000000));
int textSize = a.getDimensionPixelOffset(R.styleable.LabelView_textSize, 0);
//获取LabelView对象的textSize属性值
if (textSize > 0) {
setTextSize(textSize);
}
a.recycle(); //资源回收
}
- 自定义View的界面和行为
- 实现登录界面的自定义view
- 高级界面之自定义View的使用
- 自定义View-获取界面的rootview
- 自定义View界面大合集
- 自定义View实现手机qq5.X的抽屉特效和聊天界面联系人左滑功能
- Android中的UI界面控制方式和自定义View
- 自定义的surfaceview和view
- View 界面的放大和缩小
- Android自定义View-登录界面
- 自定义view实现联系人界面
- 最全的自定义View界面用法汇总--绘制自定义View
- 自定义View android 像支付宝支付界面的progress
- 自定义View新手实战-一步步实现精美的钟表界面
- 自定义View新手实战-一步步实现精美的钟表界面
- 一个可以在界面顶部展现的自定义 View
- 自定义view-使用xml控制界面的呈现
- 自定义view-仿虎扑直播比赛界面的打赏按钮
- 浏览器内核(解释引擎)
- 认识物理内存4G地址空间的局限--转载
- 2012硅谷的那些事儿--互联网
- Spring框架中获得DataSource对象的方法
- unity3d调用DLL
- 自定义View的界面和行为
- 模拟下拉框-美化你的网站
- 20121222不管有多二,生活还是继续
- 外媒评年度十大Mac应用 商务类中Office排第一
- 计算机网络基础——网络层
- 电商企业做好EDM营销的十个关键点
- 表空间space使用查询
- 写给喜欢抄博客的一群SB
- unity3d自适应分辨率变化。。很旧的东西了。。。