• Android Framework中的addView和addWindow


    调用方式

    addView

    addView方法是用于将视图添加到布局中的方法,通常用于在应用程序级别的布局中动态添加视图。
    addView()是ViewGroup类的方法,用于在一个已经存在的父视图中添加一个子视图。它只能在UI线程中调用,因为它会更新UI。

    相关代码

    代码路径:frameworks/base/core/java/android/view/ViewGroup.java

        /**
         * 

    Adds a child view. If no layout parameters are already set on the child, the * default parameters for this ViewGroup are set on the child.

    * *

    Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

    * * @param child the child view to add * * @see #generateDefaultLayoutParams() */
    public void addView(View child) { addView(child, -1); } /** * Adds a child view. If no layout parameters are already set on the child, the * default parameters for this ViewGroup are set on the child. * *

    Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

    * * @param child the child view to add * @param index the position at which to add the child * * @see #generateDefaultLayoutParams() */
    public void addView(View child, int index) { if (child == null) { throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup"); } LayoutParams params = child.getLayoutParams(); if (params == null) { params = generateDefaultLayoutParams(); if (params == null) { throw new IllegalArgumentException( "generateDefaultLayoutParams() cannot return null "); } } addView(child, index, params); } /** * Adds a child view with this ViewGroup's default layout parameters and the * specified width and height. * *

    Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

    * * @param child the child view to add */
    public void addView(View child, int width, int height) { final LayoutParams params = generateDefaultLayoutParams(); params.width = width; params.height = height; addView(child, -1, params); } /** * Adds a child view with the specified layout parameters. * *

    Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

    * * @param child the child view to add * @param params the layout parameters to set on the child */
    @Override public void addView(View child, LayoutParams params) { addView(child, -1, params); } /** * Adds a child view with the specified layout parameters. * *

    Note: do not invoke this method from * {@link #draw(android.graphics.Canvas)}, {@link #onDraw(android.graphics.Canvas)}, * {@link #dispatchDraw(android.graphics.Canvas)} or any related method.

    * * @param child the child view to add * @param index the position at which to add the child or -1 to add last * @param params the layout parameters to set on the child */
    public void addView(View child, int index, LayoutParams params) { if (DBG) { System.out.println(this + " addView"); } if (child == null) { throw new IllegalArgumentException("Cannot add a null child view to a ViewGroup"); } // addViewInner() will call child.requestLayout() when setting the new LayoutParams // therefore, we call requestLayout() on ourselves before, so that the child's request // will be blocked at our level requestLayout(); invalidate(true); addViewInner(child, index, params, false); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103

    总而言之,也就是说addView的调用方式有下面这几种

    addView(View child)   // child 被添加的View,默认index为-1
    addView(View child, int index)   // index 被添加的View的索引
    addView(View child, int width, int height)   // width,height被添加的View指定的宽高,默认index为-1
    addView(View view, ViewGroup.LayoutParams params)   // params被添加的View指定的布局参数,默认index为-1
    addView(View child, int index, LayoutParams params) 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这些方法最终都会调用到addView(View child, int index, LayoutParams params),其中index的取值范围小于等于1,且为整数
    当index为负数时,会一直在最下面的一层添加view;当index=0,就是第一层添加view层;当index=1时,就会在第二层添加view层。
    注:其对应的removeView方法同样在ViewGroup中。

    调用示例

    private LinearLayout mLinearLayout;
    mLinearLayout = findViewById(R.id.container);
    TextView textView = new TextView(this);
    textView.setText("test");
    mLinearLayout.addView(textView,-1);
    
    • 1
    • 2
    • 3
    • 4
    • 5

    addWindow

    addWindow方法是用于将窗口添加到窗口管理器中的方法,通常用于创建系统级别的窗口,例如:悬浮窗、对话框、Toast提示等。
    addWindow()是通过WindowManager接口的实现类,WindowManagerImpl的addView方法,逐步调用到WindowManagerService中的addWindow(),用于在屏幕上添加一个新的顶级窗口。它可以在非UI线程中调用,因为它不会更新UI。

    相关代码

    代码路径:frameworks/base/core/java/android/view/WindowManager.java
    代码路径:frameworks/base/core/java/android/view/WindowManagerImpl.java

        public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
            applyTokens(params);
            mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow,
                    mContext.getUserId());
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    WindowManagerImpl实际调用的是WindowManagerGlobal的addView方法
    注:其对应的removeView方法同样在WindowManagerImpl中。

    调用示例

    private WindowManager mWindowManager;
    private WindowManager.LayoutParams mLayoutParams;
    private CustomViewLayout mCustomViewLayout;//自定义布局
    mWindowManager.addView(mCustomViewLayout, mLayoutParams);
    
    • 1
    • 2
    • 3
    • 4

    addView和addWindow的区别

    1. 使用场景:addView()方法是在已经存在的ViewGroup中添加新的视图,而addWindow()方法是添加一个新的窗口。

    2. 管理对象:addView()方法是对ViewGroup对象进行操作,而addWindow()方法是对WindowManager对象进行操作。

    3. 权限:为了使用addWindow()方法,需要在AndroidManifest.xml文件中添加权限android.permission.SYSTEM_ALERT_WINDOW,否则会抛出SecurityException异常。

    4. 布局位置:addWindow()方法可以更灵活地控制窗口的布局位置,可以通过LayoutParams参数来设置,在屏幕上任意指定位置显示。而addView()方法则是将视图直接添加到ViewGroup中,并按照其布局规则进行显示。

    5. 堆栈管理:addWindow()方法可以创建一个独立的窗口,在应用程序堆栈中单独管理,可以独立于Activity页面进行操作。而addView()方法则只是在现有的Activity视图层级中添加新的视图。

  • 相关阅读:
    机器人内部传感器阅读梳理及心得-速度传感器-数字式速度传感器
    2022年高教杯国赛数学建模思路分享
    水墨屏RFID超高频标签|RFID电子纸之组态软件操作说明2
    Linux 进程间通信
    python多线程系列—Lock锁(三)
    Unity编辑器扩展之自定义Inspector面板
    TEMU平台要求电子产品提供的UL测试报告如何办理?
    《MLB棒球创造营》:走近棒球运动·旧金山巨人队
    总结/笔记-逻辑函数封装
    【JAVA】网页版登录注册系统
  • 原文地址:https://blog.csdn.net/yimelancholy/article/details/134424279