08.建立机制分析php
01.Activity、Window、View三者关系java
02.Toast源码深度分析android
04.Dialog源码分析github
05.PopupWindow源码分析segmentfault
07.弹窗常见问题ide
09.onAttachedToWindow和onDetachedFromWindow源码分析
弹窗有哪些类型
Window是什么?
R.layout.activity_main
。如何经过WindowManager添加Window(代码实现)?
以下所示
//1. 控件 Button button = new Button(this); button.setText("Window Button"); //2. 布局参数 WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, 0, 0, PixelFormat.TRANSPARENT); layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; layoutParams.gravity = Gravity.LEFT | Gravity.TOP; layoutParams.x = 100; layoutParams.y = 300; // 必需要有type否则会异常: the specified window type 0 is not valid layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; //3. 获取WindowManager并添加控件到Window中 WindowManager windowManager = getWindowManager(); windowManager.addView(button, layoutParams);
WindowManager的主要功能是什么?
添加、更新、删除View
public interface ViewManager{ public void addView(View view, ViewGroup.LayoutParams params); //添加View public void updateViewLayout(View view, ViewGroup.LayoutParams params); //更新View public void removeView(View view); //删除View }
DecorView是FrameLayout的子类,它能够被认为是Android视图树的根节点视图。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:fitsSystemWindows="true" android:orientation="vertical"> <!-- Popout bar for action modes --> <ViewStub android:id="@+id/action_mode_bar_stub" android:layout_width="match_parent" android:layout_height="wrap_content" android:inflatedId="@+id/action_mode_bar" android:layout="@layout/action_mode_bar" android:theme="?attr/actionBarTheme" /> <FrameLayout style="?android:attr/windowTitleBackgroundStyle" android:layout_width="match_parent" android:layout_height="?android:attr/windowTitleSize"> <TextView android:id="@android:id/title" style="?android:attr/windowTitleStyle" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@null" android:fadingEdge="horizontal" android:gravity="center_vertical" /> </FrameLayout> <FrameLayout android:id="@android:id/content" android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" android:foreground="?android:attr/windowContentOverlay" android:foregroundGravity="fill_horizontal|top" /> </LinearLayout>
在Activity中经过setContentView所设置的布局文件其实就是被加到内容栏之中的,成为其惟一子View,就是上面的id为content的FrameLayout中,在代码中能够经过content来获得对应加载的布局。
ViewGroup content = (ViewGroup)findViewById(android.R.id.content); ViewGroup rootView = (ViewGroup) content.getChildAt(0);
Activity 与 PhoneWindow 与 DecorView 关系图
App点击桌面图片启动过程
window启动流程
Activity 与 PhoneWindow 与 DecorView 之间什么关系?
ActivityThread中执行performLaunchActivity,从而生成了Activity的实例。源码以下所示,ActivityThread类中源码
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ... Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); ... } catch (Exception e) { ... } try { ... if (activity != null) { ... activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor); ... } ... } catch (SuperNotCalledException e) { throw e; } catch (Exception e) { ... } return activity; }
在attach该方法中完成window的初始化。源码以下所示,Activity类中源码
final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token, int ident, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, NonConfigurationInstances lastNonConfigurationInstances, Configuration config, String referrer, IVoiceInteractor voiceInteractor, Window window, ActivityConfigCallback activityConfigCallback) { mWindow = new PhoneWindow(this, window, activityConfigCallback); mWindow.setWindowControllerCallback(this); mWindow.setCallback(this); mWindow.setOnWindowDismissedCallback(this); mWindow.getLayoutInflater().setPrivateFactory(this); if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) { mWindow.setSoftInputMode(info.softInputMode); } if (info.uiOptions != 0) { mWindow.setUiOptions(info.uiOptions); } }
用户执行Activity的setContentView方法,内部是调用PhoneWindow的setContentView方法,在PhoneWindow中完成DecorView的建立。流程
public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); } @Override public void setContentView(int layoutResID) { ... if (mContentParent == null) { installDecor(); } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { mContentParent.removeAllViews(); } ... } private void installDecor() { if (mDecor == null) { mDecor = generateDecor(); mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS); mDecor.setIsRootNamespace(true); if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) { mDecor.postOnAnimation(mInvalidatePanelMenuRunnable); } } ... }