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方法是用于将窗口添加到窗口管理器中的方法,通常用于创建系统级别的窗口,例如:悬浮窗、对话框、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()方法是在已经存在的ViewGroup中添加新的视图,而addWindow()方法是添加一个新的窗口。
管理对象:addView()方法是对ViewGroup对象进行操作,而addWindow()方法是对WindowManager对象进行操作。
权限:为了使用addWindow()方法,需要在AndroidManifest.xml文件中添加权限android.permission.SYSTEM_ALERT_WINDOW
,否则会抛出SecurityException异常。
布局位置:addWindow()方法可以更灵活地控制窗口的布局位置,可以通过LayoutParams参数来设置,在屏幕上任意指定位置显示。而addView()方法则是将视图直接添加到ViewGroup中,并按照其布局规则进行显示。
堆栈管理:addWindow()方法可以创建一个独立的窗口,在应用程序堆栈中单独管理,可以独立于Activity页面进行操作。而addView()方法则只是在现有的Activity视图层级中添加新的视图。