揭开Android视图制作的神秘面纱

在Android的UI中,View是至关重要的一个组件,它是用户界面的根本构建块。在View的制作进程中,涉及到许多重要的概念和技能。本文将具体介绍Android View的制作进程,让你能够更好地了解和把握Android的UI开发。

什么是View?

View是Android体系中的一个根本组件,它是用户界面上的一个矩形区域,能够用来展现文本、图片、按钮等等。View能够呼应用户的交互事情,比方点击、滑动等等。在Android中,一切的UI组件都是继承自View类。

View的制作进程

View的制作进程能够分为三个阶段:丈量、布局和制作。下面咱们将逐一介绍这三个阶段。

丈量阶段(Measure)

丈量阶段是View制作进程的第一个重要阶段。在丈量阶段,体系会调用View的onMeasure办法,丈量View的宽度和高度。在这个进程中,体系会依据View的LayoutParams和父容器的巨细来核算出View的巨细。

例:下面代码是一个自定义View的onMeasure办法例程。在丈量进程中,咱们设定了View的巨细。

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // 获取宽度的Size和Mode
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    // 如果Mode是精确的,直接返回
    if (widthMode == MeasureSpec.EXACTLY) {
        setMeasuredDimension(widthSize, heightMeasureSpec);
        return;
    }
    // 核算View的宽度
    int desiredWidth = getPaddingLeft() + getPaddingRight() + defaultWidth;
    int measuredWidth;
    if (desiredWidth < widthSize) {
        measuredWidth = desiredWidth;
    } else {
        measuredWidth = widthSize;
    }
    // 设置宽度和高度的Size和Mode
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int measuredHeight = defaultHeight;
    if (heightMode == MeasureSpec.EXACTLY) {
        measuredHeight = heightSize;
    } else if (heightMode == MeasureSpec.AT_MOST) {
        measuredHeight = Math.min(defaultHeight, heightSize);
    }
    setMeasuredDimension(measuredWidth, measuredHeight);
}

在丈量阶段结束后,体系会将核算好的宽度和高度传递给布局阶段。

布局阶段(Layout)

布局阶段是View制作进程的第二个重要阶段。在布局阶段,体系会调用View的onLayout办法,将View放置在父容器中的正确方位。在这个进程中,体系会依据View的LayoutParams和父容器的方位来确认View的方位。

例:下面代码是一个自定义ViewGroup的onLayout办法例程。在布局进程中,咱们遍历子View,并依据LayoutParams确认子View的方位和巨细。

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int count = getChildCount();
    int left = getPaddingLeft();
    int top = getPaddingTop();
    int right = getMeasuredWidth() - getPaddingRight();
    int bottom = getMeasuredHeight() - getPaddingBottom();
    for (int i = 0; i < count; i++) {
        View child = getChildAt(i);
        if (child.getVisibility() == GONE) {
            continue;
        }
        LayoutParams lp = (LayoutParams) child.getLayoutParams();
        int childLeft = left + lp.leftMargin;
        int childTop = top + lp.topMargin;
        int childRight = right - lp.rightMargin;
        int childBottom = bottom - lp.bottomMargin;
        child.layout(childLeft, childTop, childRight, childBottom);
    }
}

制作阶段(Draw)

制作阶段是View制作进程的最终一个重要阶段。在制作阶段,体系会调用View的onDraw办法,制作View的内容。在这个进程中,咱们能够使用Canvas目标来制作各种形状、文本和图片等等。

例:下面代码是一个自定义View的onDraw办法例程。在制作进程中,咱们使用Paint目标制作了一段文本。

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    //制作文本
    String text = "Hello World";
    Paint paint = new Paint();
    paint.setTextSize(50);
    paint.setColor(Color.RED);
    paint.setAntiAlias(true);
    canvas.drawText(text, 0, getHeight() / 2, paint);
}

除了制作内容,咱们还能够在制作阶段制作View的布景和远景。体系会调用drawBackgrounddrawForeground办法来制作布景和远景。值得注意的是,View的制作次序是:先制作布景,再制作内容,最终制作远景。

View的制作流程

View的制作流程能够看作是一个递归调用的进程,下面咱们将具体介绍这个进程。

Step 1:创立View

在View制作进程的开始阶段,咱们需要创立一个View目标,并将它添加到父容器中。在这个进程中,体系会调用View的结构函数,并将View的LayoutParams传递给它。

Step 2:丈量View

接下来,体系会调用View的measure办法,丈量View的宽度和高度。在这个进程中,View会依据自身的LayoutParams和父容器的巨细来核算出自己的宽度和高度。

Step 3:布局View

在丈量完结后,体系会调用View的layout办法,将View放置在父容器中的正确方位。在这个进程中,View会依据自身的LayoutParams和父容器的方位来确认自己的方位。

Step 4:制作布景

在布局完结后,体系会调用View的drawBackground办法,制作View的布景。在这个进程中,咱们能够使用Canvas目标来制作各种形状、文本和图片等等。

Step 5:制作内容

接下来,体系会调用View的onDraw办法,制作View的内容。在这个进程中,咱们能够使用Canvas目标来制作各种形状、文本和图片等等。

Step 6:制作远景

在制作内容完结后,体系会调用View的drawForeground办法,制作View的远景。在这个进程中,咱们同样能够使用Canvas目标来制作各种形状、文本和图片等等。

Step 7:制作子View

接着,体系会递归调用ViewGroup的dispatchDraw办法,制作一切子View的内容。在这个进程中,咱们能够使用Canvas目标来制作各种形状、文本和图片等等。

Step 8:完结制作

最终,一切的View制作完结,整个View树也就制作完结。

例:下面代码是一个自定义ViewGroup的制作流程例程。在制作进程中,咱们先画布景,再制作每个子View的内容。

public class MyViewGroup extends ViewGroup {
    public MyViewGroup(Context context) {
        super(context);
    }
    public MyViewGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // 丈量子View的宽高
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        // 获取ViewGroup的宽高巨细
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        // 设置ViewGroup的宽高
        setMeasuredDimension(widthSize, heightSize);
    }
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // 遍历一切子View,设置它们的方位和巨细
        int childCount = getChildCount();
        int left, top, right, bottom;
        for (int i = 0; i < childCount; i++) {
            View childView = getChildAt(i);
            left = childView.getLeft();
            top = childView.getTop();
            right = childView.getRight();
            bottom = childView.getBottom();
            childView.layout(left, top, right, bottom);
        }
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 画布景
        canvas.drawColor(Color.WHITE);
    }
    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        // 制作每个子View的内容
        for (int i = 0; i < getChildCount(); i++) {
            View childView = getChildAt(i);
            childView.draw(canvas);
        }
    }
}

在ViewGroup的制作流程中,体系会先调用ViewGroup的draw办法,然后依次调用dispatchDraw办法和制作每个子View的draw办法。ViewGroup的制作次序是先制作自己的布景,再制作每个子View的内容和布景,最终制作自己的远景。

总结

本文具体介绍了Android View的制作进程,包含丈量阶段、布局阶段和制作阶段。一起,咱们还在代码完成的视点,具体说明了Android ViewGroup的制作流程,帮助你更好地了解和把握Android的UI开发。

引荐

android_startup: 供给一种在应用发动时能够愈加简略、高效的方法来初始化组件,优化发动速度。不只支撑Jetpack App Startup的全部功用,还供给额外的同步与异步等候、线程控制与多进程支撑等功用。

AwesomeGithub: 根据Github的客户端,纯操练项目,支撑组件化开发,支撑账户密码与认证登陆。使用Kotlin语言进行开发,项目架构是根据JetPack&DataBinding的MVVM;项目中使用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等盛行开源技能。

flutter_github: 根据Flutter的跨平台版本Github客户端,与AwesomeGithub相对应。

android-api-analysis: 结合具体的Demo来全面解析Android相关的知识点, 帮助读者能够更快的把握与了解所阐述的要点。

daily_algorithm: 每日一算法,由浅入深,欢迎加入一起共勉。