android 自定义view
来源:互联网 发布:淘宝黑搜原理 编辑:程序博客网 时间:2024/06/03 23:50
在继承View类时,需要重写两个方法,分别是onMeasure和onLayout。
1,在方法onMeasure中调用setMeasuredDimension方法void android.view.View.setMeasuredDimension(int measuredWidth, int measuredHeight)
public class MyTestView extends View {private Bitmap backGround;private Context mContext;public MyTestView(Context context) {super(context);init(context);// TODO Auto-generated constructor stub}public MyTestView(Context context, AttributeSet attrs) {super(context, attrs);init(context);// TODO Auto-generated constructor stub}public MyTestView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);init(context);// TODO Auto-generated constructor stub}private void init(Context mContext){mContext = mContext;backGround = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.jiaoyu);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {System.out.println("widthMeasureSpec"+widthMeasureSpec+" heightMeasureSpec"+heightMeasureSpec);setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));}private int measureWidth(int widthMeasureSpec) {int result = 0;int model = MeasureSpec.getMode(widthMeasureSpec);int size = MeasureSpec.getSize(widthMeasureSpec);if (model == MeasureSpec.EXACTLY) {result = size;} else {if (backGround != null) {result = backGround.getWidth() + getPaddingLeft()+ getPaddingRight();}if (model == MeasureSpec.AT_MOST) {result = Math.min(result, size);}}return result;}private int measureHeight(int heightMeasureSpec){int result = 0;int model = MeasureSpec.getMode(heightMeasureSpec);int size = MeasureSpec.getSize(heightMeasureSpec);if (model == MeasureSpec.EXACTLY) {result = size;} else {if (backGround != null) {result = backGround.getHeight() + getPaddingTop()+ getPaddingBottom();}if (model == MeasureSpec.AT_MOST) {result = Math.min(result, size);}}return result;}@Overrideprotected void onLayout(boolean changed, int left, int top, int right,int bottom) {// TODO Auto-generated method stubsuper.onLayout(changed, left, top, right, bottom);}protected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);this.setBackgroundResource(R.color.red);canvas.save();canvas.translate(15, 0);canvas.drawBitmap(backGround, 0, 0, new Paint());canvas.restore();}}
解析View.MeasureSpec类
android.view.View.MeasureSpec
MeasureSpec对象,封装了layout规格说明,并且从父view传递给子view。每个MeasureSpec对象代表了width或height的规格。
MeasureSpec对象包含一个size和一个mode,其中mode可以取以下三个数值之一:
UNSPECIFIED,1073741824 [0x40000000],未加规定的,表示没有给子view添加任何规定。
EXACTLY,0 [0x0],精确的,表示父view为子view确定精确的尺寸。
AT_MOST,-2147483648 [0x80000000],子view可以在指定的尺寸内尽量大。
view在测量显示的时候是受到父View的限制的,如果父View的宽高设置为wrap_content,那么就对子View的显示没有什么限制,可以让子View按照最大的尺寸显示,如果父View的尺寸限定了,那么子View的显示的大小一定不会超过父view,如果超过的话会被截掉。
MeasureSpec,是从父view传给子View的,所以MeasureSpec中规定了子View显示的最大区域。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" > <com.fy.communityapp.view.MyTestView android:layout_width="fill_parent" android:layout_centerInParent="true" android:layout_height="fill_parent" android:paddingLeft="10dp" android:visibility="gone" android:paddingRight="20dp" > </com.fy.communityapp.view.MyTestView></RelativeLayout>
如果我们给RelativeLayout设定宽高为 match-parent或者wrap_content,那么MyTestView的宽显示的最大区域都为整个屏幕的宽度(高度同理),如过 宽度设定为一个固定的值的话,那么子View MyTestView 显示的最大宽度也为这个值。
int model = MeasureSpec.getMode(heightMeasureSpec);
int size = MeasureSpec.getSize(heightMeasureSpec);而我们在计算的时候 这个size就是RelativeLayout测量出的MyTestView显示的最大宽度,这个最大宽度是不会超过父View的宽度的
例如:
if (model == MeasureSpec.EXACTLY) {result = size;} else {if (backGround != null) {result = backGround.getHeight() + getPaddingTop()+ getPaddingBottom();}if (model == MeasureSpec.AT_MOST) {result = Math.min(result, size);}}如果你给MyTestView设定的固定的值比父view设定的固定的值要大,那么MyTestView最多显示父View宽度的空间,如果设定的固定的值比父view设定的固定的值要小,那么显示的是MyTestView设定的值。
如果 MyTestView设定的宽为match-parent的话,那么显示的也是屏幕的宽度,如果设定的是wrap_content,那么MyTestView所能显示的最大宽度为屏幕宽,但是显示的是MyTestView的所能显示的宽度就是以下计算结果
if (backGround != null) {result = backGround.getHeight() + getPaddingTop()+ getPaddingBottom();}if (model == MeasureSpec.AT_MOST) {result = Math.min(result, size);}
得到的值,肯定是比size要小的。
那么这个MyTestView的所能显示的宽度,是如何计算的呢?
包括你显示的Text或者图片的宽度+paddingLeft+paddingRight
就是MyTestView所能显示的宽度了。
2、onDraw()
如果我们自定义的控件中画一个图
如果我们给MyTestView设定了属性Padding的话,就像我们代码中一样,paddingleft是10,paddingRight是20,那么我们如果直接用
protected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);this.setBackgroundResource(R.color.red);canvas.drawBitmap(backGround, 0, 0, new Paint());}
那么显示的时候宽度虽然算上paddingleft和paddingRight了但是,图像是在画的时候,是在最左边画起的如图
右边红色的宽度就是paddingLeft+paddingRight
如果想要我们的左填充起到应有的效果的话,那么我们就移动canvas 15是10dp转换后的px值
protected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);this.setBackgroundResource(R.color.red);canvas.save();canvas.translate(15, 0);canvas.drawBitmap(backGround, 0, 0, new Paint());canvas.restore();}
这样就得到我们想要的结果了,左边padding10dp,右边padding20dp
参考:自定义ViewGroup http://blog.csdn.net/loongggdroid/article/details/17515113
0 0
- Android View---自定义View
- Android View---自定义View
- Android 自定义View 之 自定义View属性
- 【自定义View系列】android自定义View概述
- Android自定义view自定义属性
- Android自定义控件 -- 自定义View
- android自定义view(自定义数字键盘)
- Android自定义View-自定义属性
- Android自定义View-自定义属性
- Android 自定义View
- Android 自定义 View
- android自定义View
- Android 中自定义 view
- android 自定义view组件
- Android 自定义 View
- android 自定义view
- Android:如何自定义View
- android 自定义View
- 黑马程序员---银行业务控制系统
- 链队列
- 随机数 权重 概率
- Struts2远程代码执行漏洞分析(S2-013)
- 初识计算几何、
- android 自定义view
- keil 默认包含目录
- HashMap遍历的两种方式,推荐使用entrySet()
- LINUX使用nohup命令后台执行提交作业
- 初识设计模式 chapter 05-单件模式
- MFC图片加载
- Java 线程池的原理与实现
- vim 使用
- IOS的同步处理机制