Android View体系(九)自定义View
来源:互联网 发布:qt 编程 编辑:程序博客网 时间:2024/06/05 18:39
前言
学习了以上的文章后,接下来我们来讲讲自定义View,自定义View一直被认为是高手掌握的技能,因为情况太多,想实现的效果又变化多端,但它也要遵循一定的规则,我们要讲的就是这个规则,至于那些变化多端的酷炫的效果就由各位来慢慢发挥了。但是需要注意的是凡事都要有个度,自定义View毕竟不是规范的控件,如果不设计好不考虑性能反而会适得其反,另外适配起来可能也会产生问题,笔者的建议是如果能用系统控件的还是尽量用系统控件。
1.自定义View简介
自定义View按照笔者的划分,分为两大类,一种是自定义View,一种是自定义ViewGroup;其中自定义View又分为继承View和继承系统控件两种。这篇文章首先先了解下两大类的其中一种:自定义View。
2.继承系统控件的自定义View
这种自定义View在系统控件的基础上进行拓展,一般是添加新的功能或者修改显示的效果,一般情况下我们在onDraw()方法中进行处理。这里举一个简单的例子:
<code class="hljs java">publicclass InvalidTextView extends TextView { privatePaint mPaint = newPaint(Paint.ANTI_ALIAS_FLAG); publicInvalidTextView(Context context) { super(context); initDraw(); } publicInvalidTextView(Context context, AttributeSet attrs) { super(context, attrs); initDraw(); } publicInvalidTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initDraw(); } privatevoid initDraw() { mPaint.setColor(Color.RED); mPaint.setStrokeWidth((float)1.5); } @Override protectedvoid onDraw(Canvas canvas) { super.onDraw(canvas); intwidth = getWidth(); intheight = getHeight(); canvas.drawLine(0, height /2, width, height /2, mPaint); }}</code>
这个自定义View继承TextView,并且在onDraw()方法中画了一条红色的横线,接下来在布局中引用这个InvalidTextView:
1
<code class="hljs avrasm"> <com.example.liuwangshu.mooncustomview.invalidtextview android:id="@+id/iv_text" android:textsize="16sp" android:layout_width="200dp" android:layout_height="100dp" android:layout_centerhorizontal="true" android:gravity="center" android:background="@android:color/holo_blue_light"></com.example.liuwangshu.mooncustomview.invalidtextview></code>
2.继承系统控件的自定义View
这种自定义View在系统控件的基础上进行拓展,一般是添加新的功能或者修改显示的效果,一般情况下我们在onDraw()方法中进行处理。这里举一个简单的例子:
?
<code class="hljs java">publicclass InvalidTextView extends TextView { privatePaint mPaint = newPaint(Paint.ANTI_ALIAS_FLAG); publicInvalidTextView(Context context) { super(context); initDraw(); } publicInvalidTextView(Context context, AttributeSet attrs) { super(context, attrs); initDraw(); } publicInvalidTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initDraw(); } privatevoid initDraw() { mPaint.setColor(Color.RED); mPaint.setStrokeWidth((float)1.5); } @Override protectedvoid onDraw(Canvas canvas) { super.onDraw(canvas); intwidth = getWidth(); intheight = getHeight(); canvas.drawLine(0, height /2, width, height /2, mPaint); }}</code>
3.继承View的自定义View
与上面的继承系统控件的自定义View不同,继承View的自定义View实现起来要稍微复杂一些,不只是要实现onDraw()方法,而且在实现过程中还要考虑到wrap_content属性以及padding属性的设置;为了方便配置自己的自定义View还会对外提供自定义的属性,另外如果要改变触控的逻辑,还要重写onTouchEvent()等触控事件的方法。
简单实现继承View的自定义View
按照上面的例子我们再写一个RectView类继承View来画一个正方形:
?
<code class="hljs java">publicclass RectView extends View { privatePaint mPaint = newPaint(Paint.ANTI_ALIAS_FLAG); privateint mColor=Color.RED; publicRectView(Context context) { super(context); initDraw(); } publicRectView(Context context, AttributeSet attrs) { super(context, attrs); initDraw(); } publicRectView(Context context, AttributeSet attrs, intdefStyleAttr) { super(context, attrs, defStyleAttr); initDraw(); } privatevoid initDraw() { mPaint.setColor(mColor); mPaint.setStrokeWidth((float)1.5); } @Override protectedvoid onDraw(Canvas canvas) { super.onDraw(canvas); intwidth = getWidth(); intheight = getHeight(); canvas.drawRect(0,0, width, height, mPaint); }}</code>
在布局中引用RectView:
1
<code class="hljs avrasm"> <com.example.liuwangshu.mooncustomview.rectview android:id="@+id/rv_rect" android:layout_width="200dp" android:layout_height="200dp" android:layout_centerhorizontal="true" android:layout_margintop="50dp" android:layout_below="@id/iv_text"></com.example.liuwangshu.mooncustomview.rectview></code>
对padding属性进行处理
如果我在布局文件中设置pading属性,发现没有任何的作用,看来还得对padding属性进行处理,只需要在onDraw()方法中稍加修改就可以了,在绘制正方形的时候考虑到padding属性就可以了:
?
<code class="hljs java">@Override protectedvoid onDraw(Canvas canvas) { super.onDraw(canvas); intpaddingLeft=getPaddingLeft(); intpaddingRight=getPaddingRight(); intpaddingTop=getPaddingTop(); intpaddingBottom=getPaddingBottom(); intwidth = getWidth()-paddingLeft-paddingRight; intheight = getHeight()-paddingTop-paddingBottom; canvas.drawRect(0+paddingLeft,0+paddingTop, width+paddingRight, height+paddingBottom, mPaint); }</code>
修改布局文件加入padding属性:
<code class="hljs avrasm"> <com.example.liuwangshu.mooncustomview.rectview android:id="@+id/rv_rect" android:layout_width="200dp" android:layout_height="200dp" android:layout_centerhorizontal="true" android:layout_margintop="50dp" android:layout_below="@id/iv_text" android:padding="10dp"></com.example.liuwangshu.mooncustomview.rectview></code>
对wrap_content属性进行处理
修改布局文件,让RectView的宽度分别为wrap_content和match_parent效果都是一样的:
导致这种情况的原因请查看Android View体系(七)从源码解析View的measure流程这篇文章。对于这种情况需要我们在onMeasure()方法中指定一个默认的宽和高,在设置wrap_content属性时设置此默认的宽和高就可以了 @Override
protectedvoid onMeasure(intwidthMeasureSpec, intheightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); intwidthSpecMode = MeasureSpec.getMode(widthMeasureSpec); intheightSpecMode = MeasureSpec.getMode(heightMeasureSpec); intwidthSpecSize=MeasureSpec.getSize(widthMeasureSpec); intheightSpecSize=MeasureSpec.getSize(heightMeasureSpec); if(widthSpecMode==MeasureSpec.AT_MOST&&heightSpecMode==MeasureSpec.AT_MOST){ setMeasuredDimension(400,400); }elseif(widthSpecMode==MeasureSpec.AT_MOST){ setMeasuredDimension(400,heightSpecSize); }elseif(heightSpecMode==MeasureSpec.AT_MOST){ setMeasuredDimension(widthSpecSize,400); }}</code>
需要注意的是setMeasuredDimeon()方法接数的单位是px,来看看效果:
自定义属性
android系统的控件以android开头的比如android:layout_width,这些都是系统自带的属性,为了方便配置RectView的属性,我们也可以自定义属性,首先在values目录下创建 attrs.xml
这个配置义了名为RectView的自定义属性组合,我们定义了rect_color属性,它的格式为color,接下来在RectView的构造函数中解析自定义属性的值public RectView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray mTypedArray=context.obtainStyledAttributes(attrs,R.styleable.RectView);
//提取RectView属性集合的rect_color属性,如果没设置默认值为Color.RED
mColor=mTypedArray.getColor(R.styleable.RectView_rect_color,Color.RED);
//获取资源后要及时回收
mTypedArray.recycle();
initDraw();
}
最后修改布局文
<code class="hljs java">packagecom.example.liuwangshu.mooncustomview;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 RectView extendsView { privatePaint mPaint = newPaint(Paint.ANTI_ALIAS_FLAG); privateint mColor=Color.RED; publicRectView(Context context) { super(context); initDraw(); } publicRectView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray mTypedArray=context.obtainStyledAttributes(attrs,R.styleable.RectView); //提取RectView属性集合的rect_color属性,如果没设置默认值为Color.RED mColor=mTypedArray.getColor(R.styleable.RectView_rect_color,Color.RED); //获取资源后要及时回收 mTypedArray.recycle(); initDraw(); } publicRectView(Context context, AttributeSet attrs, intdefStyleAttr) { super(context, attrs, defStyleAttr); initDraw(); } privatevoid initDraw() { mPaint.setColor(mColor); mPaint.setStrokeWidth((float)1.5); } @Override protectedvoid onMeasure(intwidthMeasureSpec, intheightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); intwidthSpecMode = MeasureSpec.getMode(widthMeasureSpec); intheightSpecMode = MeasureSpec.getMode(heightMeasureSpec); intwidthSpecSize=MeasureSpec.getSize(widthMeasureSpec); intheightSpecSize=MeasureSpec.getSize(heightMeasureSpec); if(widthSpecMode==MeasureSpec.AT_MOST&&heightSpecMode==MeasureSpec.AT_MOST){ setMeasuredDimension(400,400); }elseif(widthSpecMode==MeasureSpec.AT_MOST){ setMeasuredDimension(400,heightSpecSize); }elseif(heightSpecMode==MeasureSpec.AT_MOST){ setMeasuredDimension(widthSpecSize,400); } } @Override protectedvoid onDraw(Canvas canvas) { super.onDraw(canvas); intpaddingLeft = getPaddingLeft(); intpaddingRight = getPaddingRight(); intpaddingTop = getPaddingTop(); intpaddingBottom = getPaddingBottom(); intwidth = getWidth() - paddingLeft - paddingRight; intheight = getHeight() - paddingTop - paddingBottom; canvas.drawRect(0+ paddingLeft, 0 + paddingTop, width + paddingRight, height + paddingBottom, mPaint); }}</code>
- Android View体系(九)自定义View
- Android View体系(九)自定义View
- Android View体系(九)自定义View
- Android View体系(十一)自定义ViewGroup
- Android自定义View知识体系
- Android View体系(十)自定义组合控件
- 自定义View知识体系
- Android View---自定义View
- Android View---自定义View
- Android Custom View (自定义 View)
- Android自定义View(三)继承View
- Android view 详解(四) 自定义view
- Android 自定义属性 view (继承View)
- android 自定义view(二),继承view
- Android自定义view之(刻度尺view)
- Android View体系(三)属性动画
- Android View体系(一)视图坐标系
- Android View体系(一)视图坐标系
- Scala-基础语法
- QT面试题
- Echarts绘制横向柱状图(圆角+渐变)
- FFT,快速傅里叶变换学习笔记
- Are virtual interfaces supported on Quagga v0.98.3 (on Debian GNU/Linux 2.6.16)?
- Android View体系(九)自定义View
- Win7 64位系统打开 chm 文件右侧窗口显示空白的解决方法
- zabbix3.2监控Esxi5.5主机
- ycb去接水
- Halcon导出dxf文件转换至不同的图层
- “图解服务器端网络架构”小结
- CentOS7中配置NFS服务
- 网络编程知识总结 之 NSURL网络请求
- 初识安卓