制止为零,宽高的常用准确方法

作者: 编程应用  发布:2019-10-01

图片 1

初稿地址:http://blog.csdn.net/growing_tree/article/details/69220191

深信不疑有那多少个爱人都有过在 Activity 中经过 getWidth() 之类的措施赢得 View 的宽高值,大概在 onCreate() 生命周期方法中,也说不定在 onResume() 生命周期方法中。然则,不幸的是,并不可能获得所要的结果,宽高值均为 0。

信赖有广大相爱的人都有过在 Activity 中经过 getWidth() 之类的措施获得 View 的宽高值,只怕在 onCreate() 生命周期方法中,也大概在 onResume() 生命周期方法中。不过,不幸的是,并不可能赢得所要的结果,宽高值均为 0。

万一对 View 的绘图展现流程熟知的话,就能分晓难点所在。大家清楚,在自定义 View 时,日常都要重写 onMeasure、onLayout、onDraw 那多少个艺术。同理,Activity 的源委显示到设备上时,那几个 View 也要经历这几个等第。

假使对 View 的绘图展现流程熟识的话,就能分晓难题所在。大家驾驭,在自定义 View 时,平日都要重写 onMeasure、onLayout、onDraw 那多少个形式。同理,Activity 的内容呈现到设备上时,那几个 View 也要经历这一个等第。

故此,当我们在 Activity 的生命周期方法中平昔获得 View 的宽高时,View 恐怕还没实践完 measure 阶段,那么自然赢获得的宽高结果为 0。那也提示大家一点,在 onCreate 方法中只相符做些一些初叶化设置职业,使用 View 执行动画也许其余操作时,必要求小心考虑 View 绘制的耗费时间进度。

进而,当大家在 Activity 的生命周期方法中央直属机关接得到 View 的宽高时,View 大概还没实行完 measure 阶段,那么自然得到到的宽高结果为 0。那也提醒大家一些,在 onCreate 方法中只相符做些一些初阶化设置职业,使用 View 施行动画恐怕别的操作时,一定要注意怀念 View 绘制的耗费时间进度。

那么难点来了,怎么着技巧在 Activity 代码中拿走到 View 的实际宽高值呢?这里给大家总括一些常用方法。

那么难题来了,如何才干在 Activity 代码中收获到 View 的实在宽高值呢?这里给大家总括一些常用方法。

view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (Build.VERSION.SDK_INT >= 16) { view.getViewTreeObserver().removeOnGlobalLayoutListener; }else { view.getViewTreeObserver().removeGlobalOnLayoutListener; } int width = view.getWidth;

addOnGlobalLayoutListener

view.getViewTreeObserver().addOnGlobalLayoutListener(
        new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override 
    public void onGlobalLayout() { 
        if (Build.VERSION.SDK_INT >= 16) { 
            view.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
        } else { 
            view.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
        } 
        int width = view.getWidth(); 
    }
});

ViewTreeObserver,看名就能够猜到其意义,视图树的阅览者,能够监听 View 的大局变化事件。譬如,layout 变化,draw 事件等。能够阅读源码明白越来越多事件。

留意:使用时索要留意及时移除该事件的监听,防止后续每三回发生全局 View 变化均触发该事件,影响属性。这里用的是 OnGlobalLayoutListener,移除监听时留意 API 的本子宽容管理。

ViewTreeObserver,断章取义,视图树的观察者,可以监听 View 的大局变化事件。比如,layout 变化,draw 事件等。可以翻阅源码领会更加多事件。

addOnPreDrawListener

view.getViewTreeObserver().addOnPreDrawListener(
            new ViewTreeObserver.OnPreDrawListener() { 
    @Override 
    public boolean onPreDraw() { 
        view.getViewTreeObserver().removeOnPreDrawListener(this); 
        int width = view.getWidth(); return false; 
    }
});

那边一样是利用 ViewTreeObserver 阅览者类,只但是这里监听的是 draw 事件。

小心:使用时索要专一及时移除该事件的监听,防止后续每一遍产生全局 View 变化均触发该事件,影响属性。这里用的是 OnGlobalLayoutListener,移除监听时介怀 API 的本子包容处理。

view.post()

view.post(new Runnable() { 
    @Override 
    public void run() { 
        int width = view.getWidth(); 
    }
});

接纳 Handler 通讯机制,加多三个 Runnable 到 message queue 中,当 view layout 管理完了时,自动发送音信,文告 UI 线程。借此机制,神奇获取 View 的宽高属性。代码简洁,使用轻巧,比较 ViewTreeObserver 监听处理,还不供给手动移除旁观者监听事件。

view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { view.getViewTreeObserver().removeOnPreDrawListener; int width = view.getWidth(); return false; }});

onLayout()

view = new View(this) { 
    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
        super.onLayout(changed, l, t, r, b); 
        int = view.getWidth(); 
    }
};

行使 View 绘制进度中的 onLayout() 方法获得宽高值,那也是为一个无需依附任何类如故措施,仅靠自身就可以幸不辱命获取宽高属性的一手。可是局限性在于,在 Activity 中应用代码创立 View 的景观很少,通常都以获得 layout 文件所加载 View 的宽高。

此间同样是使用 ViewTreeObserver 观望者类,只不过这里监听的是 draw 事件。

addOnLayoutChangeListener

view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
    @Override 
    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
        view.removeOnLayoutChangeListener(this); 
        int width = view.getWidth(); 
    }
});

监听 View 的 onLayout() 绘制进程,一旦 layout 触发变化,立时回调 onLayoutChange
格局。注意,用完也要介河南越调用 remove 方法移除监听事件。

view.post(new Runnable() { @Override public void run() { int width = view.getWidth;

ViewCompat.isLaidOut(view)

if (ViewCompat.isLaidOut(view)) { 
    int width = view.getWidth();
}

严俊意义上来说,那不能够充作二个获取宽高的秘诀之一。充其量只可以是二个料定规范。独有当 View 起码经历过一次 layout 时,isLaidOut() 方法才干回到 true,继而才干收获到 View 的实在宽高。所以,当大家的代码中有一再调用获取宽高时,才有异常的大或者接纳那些办法判定管理。

选用 Handler 通讯机制,增添四个 Runnable 到 message queue 中,当 view layout 处理达成时,自动发送音讯,通告 UI 线程。借此机制,美妙获取 View 的宽高属性。代码简洁,使用简便,相比较 ViewTreeObserver 监听管理,还无需手动移除观看者监听事件。

getMeasuredWidth()

最终,借此地儿补充有个别学问,getMeasuredWidth() 与 getWidth() 大概getMeasuredHeight() 与 getHeight() 的界别。很四个人轻易对此产生模糊,不明了那多少个办法到底有啥差距,使用时应该怎样挑选。其实,官方文书档案介绍 View class 时,对于 Size 部分,有这么一段话:

The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.
The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().
The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().

这段话足以说明 getMeasuredXXX() 与 getXXX() 的区分和挂钩所在。说得直白一点,measuredWidth 与 width 分别对应于视图绘制 的 measure 与 layout 阶段。很关键的有些是,大家要精晓,View 的宽高是由 View 自身和 parent 容器共同决定的,要理解有其一 MeasureSpec 类的留存。

诸如,View 通过笔者 measure() 方法向 parent 需要 100x100 的宽高,那么这些宽高正是 measuredWidth 和 measuredHeight 值。可是,在 parent 的 onLayout() 阶段,通过 childview.layout() 方法只分红给 childview 50x50 的宽高。那么,这几个 50x50 宽高就是 childview 实际绘制并出示到显示器的宽高,也正是 width 和 height 值。

假设你对自定义 View 进度很在行的话,通晓这一部分剧情就非常轻便一些。事实上,开荒进程中,getWidth() 和 getHeight() 方法用的愈来愈多一些。

view = new View { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); int = view.getWidth(); }};

利用 View 绘制进程中的 onLayout() 方法赢得宽高值,那也是为叁个不需求依靠别的类依然措施,仅靠自身就会成功获取宽高属性的手法。可是局限性在于,在 Activity 中采用代码创造 View 的情况很少,日常都以获取 layout 文件所加载 View 的宽高。

view.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { view.removeOnLayoutChangeListener; int width = view.getWidth;

监听 View 的 onLayout() 绘制进程,一旦 layout 触发变化,立即回调 onLayoutChange 方法。注意,用完也要在乎调用 remove 方法移除监听事件。

if (ViewCompat.isLaidOut { int width = view.getWidth();}

严谨意义上来说,那不能看做三个到手宽高的艺术之一。充其量只可以是二个论断标准。只有当 View 最少经历过壹次 layout 时,isLaidOut() 方法技艺回来 true,继而本领获得到 View 的实在宽高。所以,当大家的代码中有一再调用获取宽高时,才有比很大也许使用这么些主意判定管理。

终极,借此地儿补充有些学问,getMeasuredWidth() 与 getWidth() 只怕getMeasuredHeight() 与 getHeight() 的差异。很四个人轻松对此发生模糊,不清楚这两个艺术到底有何样界别,使用时应有怎样抉择。其实,官方文书档案介绍 View class 时,对于 Size 部分,有这么一段话:

The size of a view is expressed with a width and a height. A view actually possess two pairs of width and height values.

The first pair is known as measured width and measured height. These dimensions define how big a view wants to be within its parent (see Layout for more details.) The measured dimensions can be obtained by calling getMeasuredWidth() and getMeasuredHeight().

The second pair is simply known as width and height, or sometimes drawing width and drawing height. These dimensions define the actual size of the view on screen, at drawing time and after layout. These values may, but do not have to, be different from the measured width and height. The width and height can be obtained by calling getWidth() and getHeight().

这段话足以说明 getMeasuredXXX() 与 getXXX() 的区分和维系所在。说得直白一点,measuredWidth 与 width 分别对应于视图绘制 的 measure 与 layout 阶段。很主要的一些是,大家要知道,View 的宽高是由 View 本身和 parent 容器共同决定的,要明白有那个 MeasureSpec 类的留存。

举例,View 通过作者 measure() 方法向 parent 央求 100x100 的宽高,那么那几个宽高正是 measuredWidth 和 measuredHeight 值。可是,在 parent 的 onLayout() 阶段,通过 childview.layout() 方法只分红给 childview 50x50 的宽高。那么,那么些 50x50 宽高便是 childview 实际绘制并呈现到荧屏的宽高,也正是 width 和 height 值。

只要您对自定义 View 进度很在行的话,精晓这一部分剧情就很轻松一些。事实上,开拓进度中,getWidth() 和 getHeight() 方法用的更加的多一些。

本文由金沙澳门官网送注册58发布于编程应用,转载请注明出处:制止为零,宽高的常用准确方法

关键词:

上一篇:没有了
下一篇:没有了