安卓自定义View详解

page1image376

安卓自定义View

知识点:1.ViewRoot和DecorView2.MeasureSpec3.measure layout draw4. 定义View

ViewRoot和DecorView

page4image376

ViewRootDecorView

ViewRootDecorView

page5image1264

右图是UI界 的架构图,每个Activity都包含 个Window对象,Android中通常有PhoneWindow来实现,PhoneWindow将 个DecorView设置为整个应 窗 的根View.DecorView将要显示的内容呈现在PhoneWindow

ViewRootDecorView

ViewRoot是连接WindowManagerDecorView的纽带,View的整个绘制流程的三 步(measurelayoutdraw)都是通过ViewRoot完成的。当Activity对象被创建完毕后,会将DecorView添加到Window中(Window是对窗 的抽象,DecorView是 个窗 的顶级容 View,其本质是 个FrameLayout),同时会创建ViewRootImpl(ViewRoot的实现类)对象,并将ViewRootImplDecorView建 关联。整个View树的绘图流程是在ViewRoot.Java类的performTraversals()函数展开的,该函数做的执 过程可简单概况为

根据之前设置的状态,判断是否需要重新计算视图 (measure)、是否重新需要安置视图的位置(layout)、以及是否需要重绘(draw),其框架过程如下:

整个View树的绘图流程是在ViewRoot.Java类的performTraversals()函数展开的,该函数做的执 过程可简单概况

page6image2752

ViewRootDecorView

下图是View树结构,Activity中使 的findViewById(),就是在控件树中以树的深度优先遍历来查找对应的元素.每棵树的顶部都有 个ViewParent对象,是整棵树的控制核 ,所有的交互事件都由它统 调度和发配,从 可以对整个视图进 整体的控制

page7image1800

MeasureSpec

MeasureSpec

是 个32int值,很 程度上决定 个View的尺 规格。受 View的影响。系统会将ViewLayoutParams根据 View施加的规则转换成对应的MeasureSpec,再根据MeasureSpec来测 出View的宽/ 。

2位代表SpecMode

30位代表SpecSize

page9image3880

UNSPECIGFIED: ViewView有限制,要多 给多 EXACTLY: View已经测出View的需要的精确 ,View最终的 就是SpecSize的值。对应

match_parent和具体数值AT_MOST: View指定 个可 的 SpecSizeView 能 于这个值,对应于wrap_content

page10image592

MeasureSpec(http://www.alliedjeep.com/119103.htm)下面是MeasureSpec 的工作原理

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 makeSafeMeasureSpec(int size, int mode) {

if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {

return 0; }

return makeMeasureSpec(size, mode); }

public static int getMode(int measureSpec) {

return (measureSpec & MODE_MASK); }

public static int getSize(int measureSpec) {

return (measureSpec & ~MODE_MASK); }

static int adjust(int measureSpec, int delta) { final int mode = getMode(measureSpec);
int size = getSize(measureSpec);
if (mode == UNSPECIFIED) {

// No need to adjust size for UNSPECIFIED mode.

return makeMeasureSpec(size, UNSPECIFIED); }

size += delta; if (size < 0) {

Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size + ") spec: " + toString(measureSpec) + " delta: " + delta);

size = 0; }

return makeMeasureSpec(size, mode); }

//... }

page10image16184 page10image16344 page10image16504 page10image16664 page10image16824 page10image16984 page10image17144 page10image17304 page10image17464 page10image17624 page10image17784 page10image17944 page10image18104 page10image18264 page10image18424 page10image18584 page10image18744 page10image18904 page10image19064 page10image19224 page10image19384 page10image19544 page10image19704 page10image19864 page10image20024 page10image20184 page10image20344 page10image20504 page10image20664 page10image20824 page10image20984 page10image21408 page10image21568 page10image21728 page10image21888 page10image22048 page10image22208 page10image22368 page10image22528 page10image22688 page10image22848
page11image832

MeasureSpec(http://www.alliedjeep.com/119103.htm)普通View

page11image1848 page11image2008

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 sizeis 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 =View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;

resultMode = MeasureSpec.UNSPECIFIED; } else if (childDimension ==

LayoutParams.WRAP_CONTENT) {
// Child wants to determine its own size....

find out how
// big it should be

resultSize =View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;

resultMode = MeasureSpec.UNSPECIFIED; }

break; }

page11image24632 page11image24792 page11image24952 page11image25112 page11image25272 page11image25432 page11image25592 page11image25752 page11image25912 page11image26072 page11image26232 page11image26392 page11image26552 page11image26712 page11image26872 page11image27032 page11image27192 page11image27352 page11image27512 page11image27672 page11image27832 page11image27992 page11image28152 page11image28312 page11image28472 page11image28632 page11image28792 page11image28952 page11image29112 page11image29272 page11image29432 page11image29592 page11image29752 page11image29912 page11image30072 page11image30232 page11image30392 page11image30552 page11image30712 page11image30872 page11image31032 page11image31192 page11image31352 page11image31512 page11image31672 page11image31832 page11image31992 page11image32152 page11image32312 page11image32472 page11image32632 page11image32792 page11image32952 page11image33112 page11image33272 page11image33432 page11image33592 page11image33752 page11image33912 page11image34072 page11image34232 page11image34392 page11image34552 page11image34712 page11image34872 page11image35032 page11image35192 page11image35352

MeasureSpec(http://www.alliedjeep.com/119103.htm)下 代码描述 DecorViewMeasureSpec的产 过程

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

page12image2080 page12image2240 page12image2328 page12image2416

}

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;

page12image7592

根据它的LayoutParams中的宽 的参数来分,LayoutParams.MATCH_PARENT:其模式为精确模式, 就是窗 的 LayoutParams.WRAP_CONTENT:其模式为最 模式, 定,但是 能超过窗 的 固定 ( 如100dp):其模式为精确模式, 为<span style="font-siz

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值