揭秘Android视图绘制的流程步骤

 更新时间:2023年06月02日 08:37:02   作者:午后一小憩  
在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视图绘制的流程步骤的详细内容,更多关于Android 视图绘制的资料请关注脚本之家其它相关文章!

相关文章

  • android RecyclerView的一些优化点介绍

    android RecyclerView的一些优化点介绍

    大家好,本篇文章主要讲的是android RecyclerView的一些优化点介绍,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • Android编程实现震动与振铃的方法详解

    Android编程实现震动与振铃的方法详解

    这篇文章主要介绍了Android编程实现震动与振铃的方法,结合实例形式分析了Android实现震动与振铃的Vibrator类及MediaPlayer类相关使用技巧,需要的朋友可以参考下
    2018-03-03
  • 总结Android App内存优化之图片优化

    总结Android App内存优化之图片优化

    网上有很多大拿分享的关于Android性能优化的文章,主要是通过各种工具分析,使用合理的技巧优化APP的体验,提升APP的流畅度,但关于内存优化的文章很少有看到。下面是我在实践过程中使用的一些方法,很多都是不太成熟的项目,只是将其作为一种处理方式分享给大家。
    2016-08-08
  • Android自定义TabLayout效果

    Android自定义TabLayout效果

    这篇文章主要为大家详细介绍了Android自定义TabLayout效果的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • Android studio 2020中的Android SDK 下载教程

    Android studio 2020中的Android SDK 下载教程

    这篇文章主要介绍了Android studio 2020中的Android SDK 下载教程,本文图文并茂给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • Android Rxjava3 使用场景详解

    Android Rxjava3 使用场景详解

    本文主要介绍了Android Rxjava3 使用场景详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • android实现背景平铺的三种方法

    android实现背景平铺的三种方法

    这篇文章主要介绍了Android的图片平铺效果的实现方法,主要有使用系统API、使用XML配置、自定义绘制三种方法,需要的朋友可以参考下
    2014-02-02
  • Android的Activity跳转动画各种效果整理

    Android的Activity跳转动画各种效果整理

    Android的Activity跳转就是很生硬的切换界面。其实Android的Activity跳转可以设置各种动画,本文整理了一些,还有很多动画效果,就要靠我们发挥自己的想象力
    2013-06-06
  • Android GPS室内定位问题的解决方法(location为null)

    Android GPS室内定位问题的解决方法(location为null)

    这篇文章主要为大家详细介绍了Android GPS室内定位问题的解决方法,location为null,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-02-02
  • Android实现拖动效果的两种方法

    Android实现拖动效果的两种方法

    这篇文章主要为大家详细介绍了Android实现拖动效果的两种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04

最新评论