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

自定义组件的简单使用—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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值