Android的自定义控件起步

来源:互联网 发布:win7如何安装linux系统 编辑:程序博客网 时间:2024/05/17 16:44

Android的自定义控件起步

控件大概分为两类
ViewGroup和View。ViewGroup可以包含多个View,然之后形成一个树形结构 即为控件数。上层控件负责下层控件的测量和绘制,传递交互事件。而且每棵树的顶部都有一个ViewParent对象。是整棵数的控制中心

View的测量

一个View如果你不告诉它有多大那么它就如盲头苍蝇一样乱飞,没有方向。所以绘制的时候需要给它一个指引。而指引用到的方法是onMeasure()而且操作这个方法的人是我。那么我就可以决定View的大小,就像主宰的View一样。但是只有方法没有实体的内容。那? 怎么操作。Android为我们提供了一个强大的类MeasureSpec。它为我们提供了3种测量模式,分别是EXACTLY,AT_MOST,UNSPECIFIED。

   EXACTLY   精确模式 子控件不会超过父控件的大小   AT_MOST   最大值模式 控件大小随子控件的内容而变化  不超过父控件即可   UNSPECIFIED View想多大就多大

下面说一下它的对应

   EXACTLY      400dp 精确到多小   AT_MOST      warp_content   UNSPECIFIED  match_content

默认支持的是EXACTLY模式

自定义View需要注意的是onMeasure和onDraw方法 当然还有其他方法但是这两个重要一点

onMeasure方法了

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {    super.onMeasure(widthMeasureSpec,heightMeasureSpec);    }

我们看一下它实现了父类的那个方法竟然可以控制view的大小。

  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));    }

查看源码可知道我们只需要把宽高传进去setMeasuredDimension即可

 Measure the view and its content to determine the measured width and the     measured height. This method is invoked by {@link #measure(int, int)} and     should be overridden by subclasses to provide accurate and efficient      measurement of their contents.

而且根据这段话可以推出这个方法决定了View的大小

大概意思就是测量View和它的内容来决定测量的高度和宽度。这个方法会由measure(int, int)唤醒和应该由子类将她重写和提供精确和高效的测量他们呢的内容

现在我们就需要对宽高进行重新定义

第一步:从MeasureSpec获取具体的测量模式和大小

//       获取测量模式        int specMode = MeasureSpec.getMode(measureSpec);//       获取大小        int specSize =  MeasureSpec.getSize(measureSpec);

第二步:接下来就是判断测量模式 宽高都是这个模式进行获取

        if(specMode == MeasureSpec.EXACTLY){            result = specSize;        }else {//            这里获取的是px  建议使用dp因为是无关密度            result = 200;            if(specMode == MeasureSpec.AT_MOST){                result = Math.min(result,specSize);            }        }

接下来的一步就是使用这个控件啦

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical">    <com.example.viewbymyself.Test        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#000" />    <com.example.viewbymyself.Test        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:background="#613a3a" />    <com.example.viewbymyself.Test        android:layout_width="300dp"        android:layout_height="300dp"        android:background="#ff7854" /></LinearLayout>

OnDraw方法

要想在界面上画出想要的图案那么就需要重写这个方法,一般情况下使用Canvas和Paint就可以实现自己图案当然还需要其他辅助方法但是这两个是最重要的。
@Override
protected void onDraw(Canvas canvas) {
// yi 在调用父类前实现自己的逻辑
super.onDraw(canvas);
// er 在调用父类后实现自己的逻辑
}

如果是继承Button的话 yi就是在Button绘制之前实现 er就是Button绘制之后实现

ViewGroup可以掌控着一个或多View的父控件

ViewGroup比自定义View多一个方法需要重写的方法就是OnLayout 控制显示其子View的显示逻辑位置如果还支持warp_content那么就需要重写onMeasure

ViewGroup会管理子View的显示和大小 但是当viewGroup的大小为warp_content的时候 ViewGroup就需要对子View进行遍历 获取所有子View的大小来进行决定自己的大小 测量完毕后将其放进合适的位置 这个过程就是View的Layout过程。ViewGroup在执行Layout过程时同样适用遍历来调用view的layout方法 将其显示在具体位置 从而达成布局

ViewGruop的绘制
通常不需要绘制 当设置背景颜色时会调用OnDraw方法 但是ViewGroup会使用dispatchDraw()方法来绘制其子View,其过程同样是遍历子View并调用子View的绘制方法来完成绘制工作。

0 0
原创粉丝点击