• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > android View绘制源码分析

android View绘制源码分析

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android pdfview 源码,android view源码,android view源码分析,android view绘制流程,android view绘制等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

android View绘制源码分析


在开发过程中我们经常要进行view的自定义。如果熟练掌握自定义技巧的话就能做出很多控件出来。这篇博客来讲讲view绘制背后发生的那些事。

一, view的基础知识

view的绘制概括

首先先说说view绘制的整体过程。
View绘制的源码分析 ,它的三大流程都是在ViewRootImpl中完成的,从ViewRootImpl中的performTraversals开始,有三个方法performMeasure,performLayout,prformDraw分别对measure,layout,draw三个方法。在onMeasure对所有子元素进行measure过程 ,这时measure就从父容器传递到子元素。子元素重复父元素的过程。layout与draw类似,只是draw通过diapatchDraw来实现 。
measure完成后可以通过getMeasureWidth,getMeasureHeight分别获取View测量后的宽高。在实际情况下几乎所有情况它都等于最终宽高。layout过程决定view的四个顶点的坐标和实际view的宽高,完成之后可以通过getTop,getBottom,getLeft,getRight来拿 到view的四个顶点位置。并通过getWidth()和getHeight()来拿到最终宽高。draw决定了view的显示,只有完成才能显示在屏幕上。

MeasureSpec

在测量过程中系统会将View的LayoutParams根据容器所施加的规则转换成对应的MeasureSpec,然后再根据这个测量出view。
Measure是一个32位的int,高2位代表SpecMode,低30位代表SpecSize。SpecMode表示测量模式,SpecSize指在某种测量模式下规格的大小。其代码如下:

public static class MeasureSpec {
    private static final int MODE_SHIFT = 30;
    private static final int MODE_MASK  = 0x3 << MODE_SHIFT;

    public static final int UNSPECIFIED = 0 << MODE_SHIFT;

  public static final int EXACTLY     = 1 << MODE_SHIFT;
 public static final int AT_MOST     = 2 << MODE_SHIFT;

public static int makeMeasureSpec(int size, int mode) {
    if (sUseBrokenMakeMeasureSpec) {
        return size + mode;
    } else {
        return (size & ~MODE_MASK) | (mode & MODE_MASK);
    }
}
public static int getMode(int measureSpec) {
    return (measureSpec & MODE_MASK) ;
}
public static int getSize(int measureSpec) {
    return (measureSpec & ~MODE_MASK) ;
}

其实MeasureSpec中源码很值得我们学习。他用一个32位的int来表示模式和大小,节省了空间,也更直观。MeasureSpec通过将specMode和specSize打包成一个int来避免过多的对象内存分配。以上是MeasureSpec的打包和解包过程。
specMode有三种状态:UNSPECIFIED,EXACTLY(相当于match_parent和精确值这两种模式),AT_MOST(wrap_content)。

LayoutParams

对于一般容器,它的MeasureSpec是由父容器的MeasureSpec和自身的LayoutParams共同决定的。上篇博客LayoutInflater源码解析 我们己经介绍了android view的结构,PhoneWindow包了一层DecorView,DecorView里才是title和我们的content view。所以行分析DecorView。
先来看下DecorView的产生源码:

 childWidthMeasureSpec = getRootMeasureSpec(baseSize, lp.width);
                childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height);
                performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

再看下getRootMeasureSpec方法:

private static int getRootMeasureSpec(int windowSize, int rootDimension) {
        int measureSpec;
        switch (rootDimension) {

        case ViewGroup.LayoutParams.MATCH_PARENT:
            // Window can't resize. Force root view to be windowSize.
            measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
            break;
        case ViewGroup.LayoutParams.WRAP_CONTENT:
            // Window can resize. Set max size for root view.
            measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
            break;
        default:
            // Window wants to be an exact size. Force root view to be that size.//自定义
            measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
            break;
        }
        return measureSpec;
    }

这里很清楚,分别分MatchPraent和wrap_content和自定义来计算宽高。再来看下普通的view,在ViewGroup的measureChildWIthMargins中:

protected void measureChildWithMargins (View child,
        int parentWidthMeasureSpec , int widthUsed,
        int parentHeightMeasureSpec , int heightUsed) {
    final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams() ;

    final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec ,
            mPaddingLeft + mPaddingRight + lp. leftMargin + lp.rightMargin
                    + widthUsed, lp.width) ;
    final int childHeightMeasureSpec = getChildMeasureSpec(parentHeightMeasureSpec ,
            mPaddingTop + mPaddingBottom + lp. topMargin + lp.bottomMargin
                    + heightUsed, lp.height) ;

    child.measure(childWidthMeasureSpec , childHeightMeasureSpec);
}

再看下getChildMeasureSpec:

public static int getChildMeasureSpec(int spec, int padding , int childDimension) {
    int specMode = MeasureSpec.getMode(spec);
    int specSize = MeasureSpec. getSize(spec) ;

    int size = Math. max( 0, specSize - padding) ;

    int resultSize = 0;
    int resultMode = 0;

    switch (specMode) {
    // Parent has imposed an exact size on us
    case MeasureSpec.EXACTLY:
        if (childDimension >= 0) {
            resultSize = childDimension;
            resultMode = MeasureSpec. EXACTLY;
        } else if (childDimension == LayoutParams.MATCH_PARENT) {
            // Child wants to be our size. So be it.
            resultSize = size ;
            resultMode = MeasureSpec. EXACTLY;
        } else if (childDimension == LayoutParams.WRAP_CONTENT) {
            // Child wants to determine its own size. It can't be
            // bigger than us.
            resultSize = size ;
            resultMode = MeasureSpec. AT_MOST;
        }
        break;

    // Parent has imposed a maximum size on us
    case MeasureSpec.AT_MOST:
        if (childDimension >= 0) {
            // Child wants a specific size... so be it
            resultSize = childDimension ;
            resultMode = MeasureSpec. EXACTLY;
        } else if (childDimension == LayoutParams.MATCH_PARENT) {
            // Child wants to be our size, but our size is not fixed.
            // Constrain child to not be bigger than us.
            resultSize = size ;
            resultMode = MeasureSpec. AT_MOST;
        } else if (childDimension == LayoutParams.WRAP_CONTENT) {
            // Child wants to determine its own size. It can't be
            // bigger than us.
            resultSize = size ;
            resultMode = MeasureSpec. AT_MOST;
        }
        break;

    // Parent asked to see how big we want to be
    case MeasureSpec.UNSPECIFIED:
        if (childDimension >= 0) {
            // Child wants a specific size... let him have it
            resultSize = childDimension ;
            resultMode = MeasureSpec. EXACTLY;
        } else if (childDimension == LayoutParams.MATCH_PARENT) {
            // Child wants to be our size... find out how big it should
            // be
            resultSize = 0;
            resultMode = MeasureSpec. UNSPECIFIED;
        } else if (childDimension == LayoutParams.WRAP_CONTENT) {
            // Child wants to determine its own size.... find out how
            // big it should be
            resultSize = 0;
            resultMode = MeasureSpec. UNSPECIFIED;
        }
        break;
    }
    return MeasureSpec.makeMeasureSpec(resultSize, resultMode) ;
}

以上表明,如果父是EXACTLY,parentSize,那么子如果是EXACTLY,
1)具体的值size:那子的MeasureSpec就是EXACTLY,size;
2)MATCH_PARENT:那子的MeasureSpec就是EXACTLY,parentSize;
3)WRAP_CONTENT:那子的MeasureSpec就是AT_MOST,parentSize;

如果父是ATMOST,parentSize,那么子如果是EXACTLY,
1)具体的值size:那子的MeasureSpec就是EXACTLY,size;
2)MATCH_PARENT:那子的MeasureSpec就是A

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android View体系(五)从源码解析View的事件分发机制
  • android View绘制源码分析

相关文章

  • 2017-05-26Linux之使用NTP服务管理/同步服务器时间
  • 2017-05-26Android GreenDAO3.0——介绍,androidgreendao3.0
  • 2017-05-26安卓界面高级组件------拖动条和评星条,安卓------拖动
  • 2017-05-26初次使用Android Studio时的配置
  • 2017-05-26[Android学习]ListView显示多种item的处理办法
  • 2017-05-26React-Native系列Android——Touch事件原理及状态效果
  • 2017-05-26linux更改emc磁盘盘符
  • 2017-05-26接入微信分享过程的喜和泪
  • 2017-05-26Android中的LinearLayout布局,linearlayout垂直布局
  • 2017-05-26tomcat+java的web程序持续占cpu问题调试

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android菜单项内容大全,android菜单项大全
    • 【React Native开发】React Native控件之DrawerLayoutAndroid抽屉导航切换组件讲解(13)
    • Android学习第五篇——动画效果
    • Android 隐藏状态栏 标题栏
    • Android表单UI及相应控件的事件处理,android表单ui控件
    • 自定义组件,android自定义组件
    • eclipse — 导入android项目后识别成java项目的问题及解决,eclipseandroid
    • 手机安全卫士——主界面的开发,安全卫士主界面
    • Android开发学习之路--RxAndroid之lambda
    • android之仿微信双击放大字体及滑动冲突,文本显示不全,android放大字体

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有