点击事件用MotionEvent来表示,当点击事件产生后,事件最先传递给Activity,所以先了解一下Activity的构成 ,首先Activity会调用setContentView()方法加载布局
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
}
上面那个mWindon有是哪来的?
//Activity里的
public Window getWindow() {
return mWindow;
}
最终Activity的attach()方法中发现了mWindow
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);
}
getWindow()又指的是PhoneWindow,接下来看看PhoneWindow的setContextView()方法
public void setContentView(int layoutResID) {
//第一次进来为null
if (mContentParent == null) {
installDecor();
}
原来mWindow指的就是PhoneWindow,PhoneWindow是继承抽象类Window的,getWindow()得到的是一个PhoneWindow,因为Activity中setContentView()方法调用是getWindow().setContentView(layoutResID)
接下来看看 installDecor()这个方法做了什么
private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
}
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
}
...
}
接下来查看 generateDecor()
protected DecorView generateDecor() {
return new DecorView(getContext(), -1);
}
这里是创建了一个DecorView,这个DecorView就是Activity中的根View。接下来查看DecorView的源码,DecorView是PhoneWindow类的内部类,并且继承了FrameLayout。
在回到 installDecor()中 generateLayout(mDecor) 源码
protected ViewGroup generateLayout(DecorView decor) {
//根据不同的情况加载不同的布局给layoutResource
int layoutResource;
int features = getLocalFeatures();
if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
layoutResource = R.layout.screen_swipe_dismiss;
} else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleIconsDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = R.layout.screen_title_icons;
}
// XXX Remove this once action bar supports these features.
removeFeature(FEATURE_ACTION_BAR);
// System.out.println("Title Icons!");
} else if ((features & ((1 << FEATURE_PROGRESS) | (1 << FEATURE_INDETERMINATE_PROGRESS))) != 0
&& (features & (1 << FEATURE_ACTION_BAR)) == 0) {
// Special case for a window with only a progress bar (and title).
// XXX Need to have a no-title version of embedded windows.
layoutResource = R.layout.screen_progress;
// System.out.println("Progress!");
} else if ((features & (1 << FEATURE_CUSTOM_TITLE)) != 0) {
// Special case for a window with a custom title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogCustomTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else {
layoutResource = R.layout.screen_custom_title;
}
} else if ((features & (1 << FEATURE_NO_TITLE)) == 0) {
// If no other features and not embedded, only need a title.
// If the window is floating, we need a dialog layout
if (mIsFloating) {
TypedValue res = new TypedValue();
getContext().getTheme().resolveAttribute(
R.attr.dialogTitleDecorLayout, res, true);
layoutResource = res.resourceId;
} else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
layoutResource = a.getResourceId(
R.styleable.Window_windowActionBarFullscreenDecorLayout,
R.layout.screen_action_bar);
} else {
//
layoutResource = R.layout.screen_title;
}
} else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
layoutResource = R.layout.screen_simple_overlay_action_mode;
} else {
// Embedded, so no decoration is needed.
layoutResource = R.layout.screen_simple;
// System.out.println("Simple!");
}
//把系统的布局加载到DecorView
View in = mLayoutInflater.inflate(layoutResource, null);
decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
...
return contentParent;
}
PhoneWindow的generateLayout() 主要是内容就是根据不同的情况加载不同的布局给layoutResource
看一下R.layout.screen_title
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:fitsSystemWindows="true">
<!-- Popout bar for action modes -->
<ViewStub android:id="@+id/action_mode_bar_stub"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<FrameLayout android:id="@android:id/title_container"
android:layout_width="match_parent"
android:layout_height="?android:attr/windowTitleSize"
style="?android:attr/windowTitleBackgroundStyle">
</FrameLayout>
<FrameLayout android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>
上面ViewStub是用来显示ActionBar的,下面FrameLayout: 一个是title,用来显示标题,另一个content
用来显示内容。
Acitivty的构成.png
总结:Activity.setContentView(layoutResource)-> getWindow().setContentView(layoutResID)
->attach()->PhoneWindow.setContentView(layoutResID)->PhoneWindow.installDecor()->PhoneWindow.generateDecor()->PhoneWindow.generateLayout(DecorView decor) 。
网友评论