Carson带你学Android:你真的了解view.post()吗

Carson带你学Android:你真的了解view.post()吗,第1张

为什么viewpost()能保证获取到view的宽高?

Viewpost()的原理: 以Handler为基础,Viewpost() 将传入任务添加到 View绘制任务所在的消息队列尾部,从而保证Viewpost() 任务的执行时机是在View 绘制任务完成之后的。 其中,几个关键点:

所以:

具体源码分析请看: Android:为什么viewpost()能保证获取到view的宽高?

为什么onCreate()使用viewpost()无法立刻执行任务(如获取宽高),需要在onResume()后才可获取?

在onCreate()时,AttachInfo还没被赋值(为null)(是在viewdispatchAttachedToWindow()才被赋值),所以会走下述源码的过程2;通过上面分析,此过程的作用仅是:保存了通过post()添加的任务,并没执行。

若只是创建一个 View & 调用它的post(),那么post的任务会不会被执行?

不会。主要原因是:

每个View中post() 需执行的任务,必须得添加到窗口视图-执行绘制流程 - 任务才会被post到消息队列里去等待执行,即依赖于dispatchAttachedToWindow ();

若View未添加到窗口视图,那么就不会走绘制流程,post() 添加的任务最终不会被post到消息队列里,即得不到执行。(但会保存到HandlerAction数组里)

上述例子,因为它没有被添加到窗口视图,所以不会走绘制流程,所以该任务最终不会被post到消息队列里 & 执行

此时只需要添加将View添加到窗口,那么post()的任务即可被执行

viewpos()传入的任务被执行的有效期是多久?

在整个 Activity 的生命周期内都可以正常使用 Viewpost() 任务

任务被执行是构造AttachInfo,所以任务释放即时释放AttachInfo (置为null)。而AttachInfo 的释放 *** 作(置为null)是在 Activity 生命周期 onDestory 方法之后

下面,我们将分析,什么时候调用上述入口,即DecorViewdispatchDetachedFromWindow();

此时需从 将DecorView从WindowManager中移除 开始讲起:移除 Window 窗口任务是通过 ActivityThreadhandleDestoryActivity()完成。

Viewpost() 任务被执行的有效期是在 Activity 生命周期 onDestory()后。本质是追踪AttachInfo的释放过程(置为null)

AttachInfo的释放过程是在 将DecorView从WindowManager中移除时:回调DecorViewdispatchDetachedFromWindow(),其具体行为是:

而上述过程是在ActivityThreadhandleDestoryActivity()中回调 ActivityonDestory()之后。

至此,关于viewpost()的四大常见疑问 (坑)内容讲解完毕。

不定期分享关于 安卓开发 的干货,追求 短、平、快 ,但 却不缺深度

在代码里修改,先获取这两个Button, 然后获取一个的宽,通过setLayoutParams(ViewGroupLayoutParams

params),修改第二个的宽高,注意,获取view的宽高的方法有3中,你要选择合适的。

根据人体工程学的研究,发现人的两只眼睛的视野范围并不是方的,而是一个长宽比例为16:9的长方形,所以,为了让电视画面更加符合人眼的视觉比例,现在的**和连续剧大部分都做成了16:9的长方形画面,也称为宽银幕、宽屏

android开发中ImageView在显示的时候,受限于屏幕大小和宽高。通常是被缩放过,且不是宽和高都充满ImageView的,获得被实际绘制的宽高大小代码如下:

final ImageView iv = (ImageView) findViewById(Ridiv_test);

        ivsetImageResource(Rdrawableabc);

        

        //等待ImageVivew加载完成

        ivpost(new Runnable(){    

            @Override

            public void run() {

                // TODO Auto-generated method stub

                

                //ImageView的宽和高

                Logd("lxy", "iv_W = " + ivgetWidth() + ", iv_H = " + ivgetHeight());

                //获得ImageView中Image的真实宽高,

                int dw = ivgetDrawable()getBounds()width();

                int dh = ivgetDrawable()getBounds()height();

                Logd("lxy", "drawable_X = " + dw + ", drawable_Y = " + dh);

                

                //获得ImageView中Image的变换矩阵

                Matrix m = ivgetImageMatrix();

                float[] values = new float[10];

                mgetValues(values);

                

                //Image在绘制过程中的变换矩阵,从中获得x和y方向的缩放系数

                float sx = values[0];

                float sy = values[4];

                Logd("lxy", "scale_X = " + sx + ", scale_Y = " + sy);

                

                //计算Image在屏幕上实际绘制的宽高

                int cw = (int)(dw  sx);

                int ch = (int)(dh  sy);

                Logd("lxy", "caculate_W = " + cw + ", caculate_H = " + ch);

            }});

上一篇我们分析了自定义像素的屏幕适配,它是以px为单位,设计的标准机型和显示机型的宽高比,动态缩放view。

现在,我们不用px为单位,而是直接以当前view在父容器中的比例,来缩放view。

比如,我定义一个view,它的宽为父容器的一半,高也为父容器的一半。

既然需要使用自定义属性,首先就需要添加attrs,声明自定义属性。

我们实现的目的是子view以父容器的宽高为标准,按照百分比规定自身宽高,所以需要自定义个ViewGroup用来包裹子view,顺便计算出子view的宽高。

以RelativeLayout为例:

继承了RelativeLayout后,我们不能丢失RelativeLayout原来的属性,还要增加我们自定义的属性。

原始RelativeLayout的属性被定义在RelativeLayout的内部静态类中(LayoutParams)。

该类中定义的如:above、below、center等属性,都是声明在子view中。同时百分比属性也是需要定义在子view中。

所以,我们的自定义百分比布局也需要继承该内部类,再添加自定义属性。

再分析下view的创建与LayoutParams的关系。

onCreateView()中始终需要调用setContentView(layoutID)。

最终在PhoneWindow的setContentView(int layoutResID)方法中,调用方法解析layoutResID

方法一路延伸最终来到LayoutInflater类的inflate()方法。

关键点:源码中,子view的LayoutParams是由父容器的generateLayoutParams()创建

那我们的自定义LayoutParams如何被创建呢?

在父容器中重写generateLayoutParams方法,返回我们子view的LayoutParams。

最终在onMeasure方法中,根据百分比计算出子view的宽高。

整体思路

1、自定义属性。

2、自定义LayoutParams,继承自RelativeLayoutLayoutParams。

3、创建自定义LayoutParams,父容器用generateLayoutParams()方法创建子view的layoutParams。

4、在onMeasure中获取子view的LayoutParams,按比例计算出宽高并赋值。

注意:子view的LayoutParams是由父容器在generateLayoutParams()中创建。

view获取宽高常见的方式:

但是这种方式 不是万能的,有时候对于ViewGroup无效 ,这时候要借助viewgroup的onMeasure方法:

注意这里使用的是 getMeasuredHeight ,不是getHeight,计算的是子view的原始高度,不是显示高度。

以上就是关于Carson带你学Android:你真的了解view.post()吗全部的内容,包括:Carson带你学Android:你真的了解view.post()吗、安卓开发:一个view宽度等于另一个view的宽度、屏幕的宽高比是如何计算出来的等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9376810.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-27
下一篇 2023-04-27

发表评论

登录后才能评论

评论列表(0条)

保存