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); }

总而言之,也就是说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) 

这些方法最终都会调用到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);

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());
    }

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

调用示例

private WindowManager mWindowManager;
private WindowManager.LayoutParams mLayoutParams;
private CustomViewLayout mCustomViewLayout;//自定义布局
mWindowManager.addView(mCustomViewLayout, mLayoutParams);

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视图层级中添加新的视图。

你可能感兴趣的:(android)