自定义组件的简单使用—View

来源:互联网 发布:微信弹幕软件 编辑:程序博客网 时间:2024/05/02 01:44

自定义组件的简单使用—View

1、 控件是怎么来的?
每一个控件都是使用绘图的方式绘制出来的

2、开发自定义组件的几种方法
A、从0开始开发自定义组件,从View或ViewGroup类继承,难度最大
B、从已有组件继承,比如定义ImageView、ListView继承,为已有组件添加新的功能
C、将多个已有的组件组合成一个新的组件

3、View类
A、构造方法
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
如果给组件定义了样式和主题,则会调用该方法。

 public MyView(Context context, AttributeSet attrs) {      super(context, attrs); } 在layout文件中使用组件,则调用该方法。会自动将组件的属性传递给attrs参数,从该参数中可以获取定义在xml的属性。 <com.trkj.dept12_customer1.MyView    android:layout_width="wrap_content"    android:layout_height="wrap_content" /> public MyView(Context context) {      super(context); } 直接代码创建组件,一般会调用该方法,所以属性都使用默认值 Button btn = new Button(this);

B、onDraw()方法
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}

用于组件的绘制

C、onMeasure()方法
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
该方法用于确定组件的大小

A、参数:
widthMeasureSpec:保存了宽度的模式(match_parent、wrap_content、具体值)和大小
heightMeasureSpec:保存了高度的模式(match_parent、wrap_content、具体值)和大小

绝大部分情况下,我们只需要计算wrap_content(跟随内容)的情况

B、关于测量模式,一共有三种:
MeasureSpec.AT_MOST:是最大尺寸,当控件的layout_width或layout_height指定为WRAP_CONTENT时,控件大小一般随着控件的子空间或内容进行变化,此时控件尺寸只要不超过父控件允许的最大尺寸即可。该模式必须要通过编程计算。

 MeasureSpec.EXACTLY:是精确尺寸,当我们将控件的layout_width或layout_height指定为具体数值时如andorid:layout_width="50dip",或者为match_parent是,都是控件大小已经确定的情况,都是精确尺寸。 MeasureSpec.UNSPECIFIED:是未指定尺寸,这种情况不多,一般都是父控件是AdapterView,通过measure方法传入的模式。

C、如何获取组件的测量模式和大小?
//获取宽度使用的模式
int wmode = MeasureSpec.getMode(widthMeasureSpec);
//获取宽度大小
int wsize = MeasureSpec.getSize(widthMeasureSpec);

 //获取高度使用的模式 int hmode = MeasureSpec.getMode(heightMeasureSpec); //获取高度大小 int hsize = MeasureSpec.getSize(heightMeasureSpec);

D、测量出组件的宽度和高度之后,如果应用该大小?
//下面的方法一定要调用,用于应用计算出来的宽度和高度
setMeasuredDimension(wsize, hsize);

E、onMeasure()的完整写法:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取宽度使用的模式
int wmode = MeasureSpec.getMode(widthMeasureSpec);
//获取宽度大小
int wsize = MeasureSpec.getSize(widthMeasureSpec);

      //组件的实际宽度      int width = 0;      if(wmode == MeasureSpec.AT_MOST){           //计算宽度      }else{           //wsize就是父容器的大小,在EXACTLY模式下,父窗口的大小的组件的大小           width = wsize;      }        //获取高度使用的模式      int hmode = MeasureSpec.getMode(heightMeasureSpec);      //获取高度大小      int hsize = MeasureSpec.getSize(heightMeasureSpec);      int height = 0;      if(hmode == MeasureSpec.AT_MOST){           //计算高度      }else{           height = hsize;      }      //下面的方法一定要调用,用于应用计算出来的宽度和高度      setMeasuredDimension(width, height); }

4、案例:模拟TextView,角为圆角

/** * qq:2286502415 * @time:2016-1-16 * @author Administrator * */public class MyView extends View {    private String text = "中华文艺复兴";    private Paint paint;    public MyView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public MyView(Context context, AttributeSet attrs) {        super(context, attrs);        paint = new Paint();        paint.setAntiAlias(true);        paint.setColor(Color.WHITE);        paint.setTextSize(40);    }    public MyView(Context context) {        super(context);    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        int width = getMeasuredWidth();        int height = getMeasuredHeight();        Log.e("tag: ", "onDraw");        // 画填充的圆角矩形        Paint p = new Paint();        p.setColor(Color.RED);        canvas.drawRoundRect(new RectF(1, 1, width - 1, height - 1), 15, 15, p);        // 画文字        // 计算出文字所占的大小        Rect bounds = new Rect();        paint.getTextBounds(text, 0, text.length(), bounds);//从第一个到最后一个文字的距离        int left = (width - bounds.width()) / 2;//居中        int top = (height - bounds.height()) / 2;        Log.i("MyView", "top:" + top);        Log.i("MyView", "height:" + bounds.height());        canvas.drawText(text, left, top + bounds.height(), paint);        //各参数意义(文本,字符串的左边在屏幕的位置,字符串下边线距离屏幕顶端的距离,画笔。参考:http://blog.csdn.net/sirnuo/article/details/21165665)    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        // 计算出文字所占的大小        Rect bounds = new Rect();        paint.getTextBounds(text, 0, text.length(), bounds);        Log.e("tag: ", "onMeasure");        // 获取宽度使用的模式        int wmode = MeasureSpec.getMode(widthMeasureSpec);        // 获取宽度大小        int wsize = MeasureSpec.getSize(widthMeasureSpec);        // 组件的实际宽度        int width = 0;        if (wmode == MeasureSpec.AT_MOST) {            // 计算宽度            width = bounds.width();        } else {            // wsize就是父容器的大小,在EXACTLY模式下,父窗口的大小的组件的大小            width = wsize;        }        // 获取高度使用的模式        int hmode = MeasureSpec.getMode(heightMeasureSpec);        // 获取高度大小        int hsize = MeasureSpec.getSize(heightMeasureSpec);        int height = 0;        if (hmode == MeasureSpec.AT_MOST) {            // 计算高度            height = bounds.height();        } else {            height = hsize;        }        // 下面的方法一定要调用,用于应用计算出来的宽度和高度        setMeasuredDimension(width, height);    }}

效果图:
这里写图片描述

0 0