首页 > 实用文档 > 其他范文

Android 刮刮卡自定义view(通用10篇)

Olaf

【简介】感谢网友“Olaf”参与投稿,以下是小编为大家准备的Android 刮刮卡自定义view(共10篇),希望对大家有所帮助。

篇1:Android 刮刮卡自定义view

…… 此处隐藏23627字 ……

当布局变化的时候,比如方向变化,尺寸的变化,会调用该方法 它会触发measure和layout过程,但不会进行 draw过程

最佳实践

以上都是理论知识,也差不多是对多篇文章的总结性内容。下面开始实现一个自定义View和ViewGroup

自定义View

其实自定义View的大部分逻辑都是在onDraw上,onLayout基本上无需重新,onMeasure需要实现测量逻辑。

下面是一个简单的毫无任何作用的自定义View,其唯一目的就是演示onDraw和onMeasure

package cn.edu.zafu.sourcedemo;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.util.AttributeSet;import android.view.View;/** * Created by lizhangqu on 2015/5/3. */public class CustomView extends View { private Paint paint=null; private Rect rect=null; private int bgColor=Color.parseColor(#673AB7);//写死背景色,实际是自定义属性 private int minContentWidth=50;//最小内容宽度,不包含内边距 private int minContentHeight=50;//最小内容高度,不包含内边距 public CustomView(Context context) { this(context, null); } public CustomView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } /*初始化*/ private void init() { paint=new Paint(); paint.setAntiAlias(true); paint.setDither(true); paint.setColor(bgColor); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //其实所有逻辑可以简单调用resolveSize函数进行测量,这里自己实现一遍,理清思路 //获得宽度和高度的mode和size int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); //最终的宽高存在这两个变量中 int width; int height; if (widthMode == MeasureSpec.EXACTLY) {// 父视图指定了大小width = widthSize; } else {//父视图指定必须在这个大小内//注意内边距,再加上自身需要的宽度width=getPaddingLeft()+getPaddingRight()+minContentWidth;if (widthMode == MeasureSpec.AT_MOST) { //如果是AT_MOST,必须在父控件指定的范围内,取width和widthSize中小的那个 width = Math.min(width, widthSize);} } if (heightMode == MeasureSpec.EXACTLY) {// 父视图指定了大小height = widthSize; } else {//父视图指定必须在这个大小内//注意内边距,再加上自身需要的高度height =getPaddingTop()+getPaddingBottom()+minContentHeight;if (heightMode == MeasureSpec.AT_MOST) { //如果是AT_MOST,必须在父控件指定的范围内,取width和widthSize中小的那个 height = Math.min(height, heightSize);} } setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); rect=new Rect(getPaddingLeft(),getPaddingTop(),getMeasuredWidth()-getPaddingRight(),getMeasuredHeight()-getPaddingBottom());//绘制的时候注意内边距 canvas.drawRect(rect,paint); }}

自定义Viewgroup

实现一个纵向排布子View的ViewGroup,效果如图所示,见代码,解释看注释

package cn.edu.zafu.sourcedemo;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;/** * Created by lizhangqu on 2015/5/3. */public class CustomViewGroup extends ViewGroup { public CustomViewGroup(Context context) { this(context, null); } public CustomViewGroup(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } //重写onLayout抽象方法 @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { final int count = getChildCount(); MyLayoutParams lp = null; for (int i = 0; i < count; i++) {View child = getChildAt(i);//获得当前Viewlp = (MyLayoutParams) child.getLayoutParams();//获得LayoutParams,强制转换为MyLayoutParamschild.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y + child.getMeasuredHeight());//调用当前View的layout方法进行布局 } } //重写onMeasure实现测量逻辑 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 0; int lastWidth = 0; int height = getPaddingTop(); final int count = getChildCount(); //获得子View个数 for (int i = 0; i < count; i++) {View child = getChildAt(i);//获得当前子ViewmeasureChild(child, widthMeasureSpec, heightMeasureSpec);//测量子View,必须调用MyLayoutParams lp = (MyLayoutParams) child.getLayoutParams();//获得LayoutParamswidth = Math.max(width, child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);//比较当前View与之前的View宽度,取大者,注意这个宽度包含了marginlp.x = getPaddingLeft() + lp.leftMargin;//设置当前View的x左边lp.y = height + lp.topMargin;//设置当前View的y左边height = height + lp.topMargin + child.getMeasuredHeight() + lp.bottomMargin;//累加高度 } width=width+getPaddingLeft() + getPaddingRight(); //加上左右内边距 height = height + getPaddingBottom(); //加上下边界 setMeasuredDimension(resolveSize(width, widthMeasureSpec), resolveSize(height, heightMeasureSpec)); //设置宽高,resolveSize方法会根据尺寸大小和MeasureSpec计算最佳大小 } //重写生成LayoutParams的三个方法 @Override public MyLayoutParams generateLayoutParams(AttributeSet attrs) { return new MyLayoutParams(getContext(), attrs); } //重写生成LayoutParams的三个方法 @Override protected MyLayoutParams generateDefaultLayoutParams() { return new MyLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); } //重写生成LayoutParams的三个方法 @Override protected MyLayoutParams generateLayoutParams(LayoutParams p) { return new MyLayoutParams(p.width, p.height); } //继承MarginLayoutParams实现自己的LayoutParams,x,y代表控件的左边和上边左边 public static class MyLayoutParams extends MarginLayoutParams { public int x;//左 public int y;//上 public MyLayoutParams(Context context, AttributeSet attrs) {super(context, attrs); } public MyLayoutParams(int w, int h) {super(w, h); } }}

相关图文

相关专题

推荐文章