Activity 中view 的布局
来源:互联网 发布:淘宝订单进度条 编辑:程序博客网 时间:2024/06/10 08:19
android 中view 代表一块图形区域。每一个view 都与一个依赖一个父view。在每一个Activity 中有一个Window 代表一个屏幕,包含一个View 树和窗口的layout 参数。View tree的root View可以通过getDecorView得到。 在 new 一个activity 时,通常把APK的view和布局通过setContentView(R.layout.activity_main)设置到View树中。
一.在activity中有一个: private Window mWindow; 看一看这个mWindow是怎么来的:在Activity 的attach函数中:
追踪一下这个函数,看一下调用流程:
./frameworks/base/core/java/com/android/internal/policy/PolicyManager.java:
这是一个 final 类,通过反射的方法获取一个com.android.internal.policy.impl.Policy类的静态对象:sPolicy,调用这个类的makeNewWindow:
./frameworks/base/policy/src/com/android/internal/policy/impl/Policy.java
在这个类中返回了new PhoneWindow(context);
./frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java 现在我们找到了这个Window 对象。Window 的庐山真面目:
继承自 Window。window 的关系搞清楚了。
二.在Activity中通过mWindow.getDecorView() 获取activity view树的布局。又来到了window 中。DecorView 是PhoneWindow的一个内部类:
其实就是一个FrameLayout 布局,FrameLayout extend ViewGroup。所有Activity 中的view 都添加到这个布局中。installDecor 函数:
这就是在PhoneWindow 的mDecorView 。需要注意一下mContentParent 这个变量。下面会分析到。
总结一下在一个Activity 中,有一个PhoneWindwo 对象,这个对象有有一个内部类Decorview ,Decorview extend FrameLayout extend ViewGroup 。这个Activity 的 view 都保存在这里,形成一个View 树。
三.
Activity 的 setContentView:
PhoneWindow 的setContentView:
mLayoutInflater.inflate(layoutResID, mContentParent); 在这行代码中,view 被设置进了mContentParent 这个父View中,在 PhoneWindow 中:
private ViewGroup mContentParent
在刚才分析DecorView的时候, 在installDecor中会调用 mContentParent = generateLayout(mDecor), 生成mContentParent;看一下实现:
一开始获取一些窗口的属性,然后根据这些属性确定 layoutResource 的值,layoutResource 为com.android.internal.R.layout.screen_开头;就是 framework-res.apk里面的资源:src/android$ ls frameworks/base/core/res/res/layout/screen*
frameworks/base/core/res/res/layout/screen_action_bar.xml frameworks/base/core/res/res/layout/screen_simple.xml
frameworks/base/core/res/res/layout/screen_custom_title.xml frameworks/base/core/res/res/layout/screen_title_icons.xml
frameworks/base/core/res/res/layout/screen_progress.xml frameworks/base/core/res/res/layout/screen_title.xml
frameworks/base/core/res/res/layout/screen_simple_overlay_action_mode.xml frameworks/base/core/res/res/layout/screen.xml
然后解析:
contentParent 就是这些xml 文件里的一个ID_ANDROID_CONTENT 的view 。查找 ID_ANDROID_CONTENT定义:
frameworks/base/core/java/android/view/Window.java 124行:
public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
打开 screen.xml 文件:
content 是一个FrameLayout的布局,在这几个screen_*.xml文件中 都有一个id为:content的View。也就是说 mDecorView 是一个Activity的根布局,contentParent是mDecorView 一个子布局,提供给程序员的View的根布局。setContentView 的时候以contentParent为父节点。
四.
Activity的默认布局确定了,可以确定一下,修改xml 布局:
当我们进入桌面的时候,桌面效果如下:
homeshell.png
进入HelloWorld,没有任何变化。分析generateLayout的时候已经看到会根据窗口的属性选择不同的资源文件。桌面和一般的Activity使用了不同的资源配置。
修改screen_action_bar.xml
HelloWorld 的效果:
activity.png
从图中可以看到根布局是一个FrameLayout布局,就是mDecorView.DecorView extend FrameLayout。 被选中的区域为FrameLayout,就是mcontentParent,mcontentParent中有一个RelativeLayout,是我们setContentView 的R.layout.activity_main 布局文件。
一.在activity中有一个: private Window mWindow; 看一看这个mWindow是怎么来的:在Activity 的attach函数中:
点击(此处)折叠或打开
- mWindow = PolicyManager.makeNewWindow(this);
./frameworks/base/core/java/com/android/internal/policy/PolicyManager.java:
点击(此处)折叠或打开
- package com.android.internal.policy;
- import android.content.Context;
- import android.view.FallbackEventHandler;
- import android.view.LayoutInflater;
- import android.view.Window;
- import android.view.WindowManagerPolicy;
- import com.android.internal.policy.IPolicy;
- /**
- * {@hide}
- */
- public final class PolicyManager {
- private static final String POLICY_IMPL_CLASS_NAME =
- "com.android.internal.policy.impl.Policy";
- private static final IPolicy sPolicy;
- static {
- // Pull in the actual implementation of the policy at run-time
- try {
- Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
- sPolicy = (IPolicy)policyClass.newInstance();
- } catch (ClassNotFoundException ex) {
- throw new RuntimeException(
- POLICY_IMPL_CLASS_NAME + " could not be loaded", ex);
- } catch (InstantiationException ex) {
- throw new RuntimeException(
- POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(
- POLICY_IMPL_CLASS_NAME + " could not be instantiated", ex);
- }
- }
- // Cannot instantiate this class
- private PolicyManager() {}
- // The static methods to spawn new policy-specific objects
- public static Window makeNewWindow(Context context) {
- return sPolicy.makeNewWindow(context);
- }
- public static LayoutInflater makeNewLayoutInflater(Context context) {
- return sPolicy.makeNewLayoutInflater(context);
- }
- public static WindowManagerPolicy makeNewWindowManager() {
- return sPolicy.makeNewWindowManager();
- }
- public static FallbackEventHandler makeNewFallbackEventHandler(Context context) {
- return sPolicy.makeNewFallbackEventHandler(context);
- }
- }
./frameworks/base/policy/src/com/android/internal/policy/impl/Policy.java
点击(此处)折叠或打开
- package com.android.internal.policy.impl;
- import android.content.Context;
- import android.util.Log;
- import android.view.FallbackEventHandler;
- import android.view.LayoutInflater;
- import android.view.Window;
- import android.view.WindowManagerPolicy;
- import com.android.internal.policy.IPolicy;
- import com.android.internal.policy.impl.PhoneLayoutInflater;
- import com.android.internal.policy.impl.PhoneWindow;
- import com.android.internal.policy.impl.PhoneWindowManager;
- /**
- * {@hide}
- */
- // Simple implementation of the policy interface that spawns the right
- // set of objects
- public class Policy implements IPolicy {
- private static final String TAG = "PhonePolicy";
- private static final String[] preload_classes = {
- "com.android.internal.policy.impl.PhoneLayoutInflater",
- "com.android.internal.policy.impl.PhoneWindow",
- "com.android.internal.policy.impl.PhoneWindow$1",
- "com.android.internal.policy.impl.PhoneWindow$DialogMenuCallback",
- "com.android.internal.policy.impl.PhoneWindow$DecorView",
- "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState",
- "com.android.internal.policy.impl.PhoneWindow$PanelFeatureState$SavedState",
- };
- static {
- // For performance reasons, preload some policy specific classes when
- // the policy gets loaded.
- for (String s : preload_classes) {
- try {
- Class.forName(s);
- } catch (ClassNotFoundException ex) {
- Log.e(TAG, "Could not preload class for phone policy: " + s);
- }
- }
- }
- public Window makeNewWindow(Context context) {
- return new PhoneWindow(context);
- }
- public LayoutInflater makeNewLayoutInflater(Context context) {
- return new PhoneLayoutInflater(context);
- }
- public WindowManagerPolicy makeNewWindowManager() {
- return new PhoneWindowManager();
- }
- public FallbackEventHandler makeNewFallbackEventHandler(Context context) {
- return new PhoneFallbackEventHandler(context);
- }
- }
./frameworks/base/policy/src/com/android/internal/policy/impl/PhoneWindow.java 现在我们找到了这个Window 对象。Window 的庐山真面目:
点击(此处)折叠或打开
- public class PhoneWindow extends Window implements MenuBuilder.Callback {
二.在Activity中通过mWindow.getDecorView() 获取activity view树的布局。又来到了window 中。
点击(此处)折叠或打开
- public final View getDecorView() {
- if (mDecor == null) {
- installDecor();
- }
- return mDecor;
- }
点击(此处)折叠或打开
- private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
点击(此处)折叠或打开
- private void installDecor() {
- if (mDecor == null) {
- mDecor = generateDecor();
- mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
- mDecor.setIsRootNamespace(true);
- if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
- mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
- }
- }
- if (mContentParent == null) {
- mContentParent = generateLayout(mDecor);
- ......
- }
点击(此处)折叠或打开
- protected DecorView generateDecor() {
- return new DecorView(getContext(), -1);
- }
这就是在PhoneWindow 的mDecorView 。需要注意一下mContentParent 这个变量。下面会分析到。
总结一下在一个Activity 中,有一个PhoneWindwo 对象,这个对象有有一个内部类Decorview ,Decorview extend FrameLayout extend ViewGroup 。这个Activity 的 view 都保存在这里,形成一个View 树。
三.
Activity 的 setContentView:
点击(此处)折叠或打开
- public void setContentView(int layoutResID) {
- getWindow().setContentView(layoutResID);
- initActionBar();
- }
点击(此处)折叠或打开
- public void setContentView(int layoutResID) {
- if (mContentParent == null) {
- installDecor();
- } else {
- mContentParent.removeAllViews();
- }
- mLayoutInflater.inflate(layoutResID, mContentParent);
- final Callback cb = getCallback();
- if (cb != null && !isDestroyed()) {
- cb.onContentChanged();
- }
- }
private ViewGroup mContentParent
在刚才分析DecorView的时候, 在installDecor中会调用 mContentParent = generateLayout(mDecor), 生成mContentParent;看一下实现:
点击(此处)折叠或打开
- protected ViewGroup generateLayout(DecorView decor) {
- // Apply data from current theme.
- ......
- // Inflate the window decor.
- int layoutResource;
- int features = getLocalFeatures();
- System.out.println("Features: 0x" + Integer.toHexString(features));
- if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
- if (mIsFloating) {
- TypedValue res = new TypedValue();
- getContext().getTheme().resolveAttribute(
- com.android.internal.R.attr.dialogTitleIconsDecorLayout, res, true);
- layoutResource = res.resourceId;
- } else {
- layoutResource = com.android.internal.R.layout.screen_title_icons;
- System.out.println("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 = com.android.internal.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(
- com.android.internal.R.attr.dialogCustomTitleDecorLayout, res, true);
- layoutResource = res.resourceId;
- } else {
- layoutResource = com.android.internal.R.layout.screen_custom_title;
- }
- // XXX Remove this once action bar supports these features.
- removeFeature(FEATURE_ACTION_BAR);
- } 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(
- com.android.internal.R.attr.dialogTitleDecorLayout, res, true);
- layoutResource = res.resourceId;
- } else if ((features & (1 << FEATURE_ACTION_BAR)) != 0) {
- layoutResource = com.android.internal.R.layout.screen_action_bar;
- } else {
- layoutResource = com.android.internal.R.layout.screen_title;
- }
- // System.out.println("Title!");
- } else if ((features & (1 << FEATURE_ACTION_MODE_OVERLAY)) != 0) {
- layoutResource = com.android.internal.R.layout.screen_simple_overlay_action_mode;
- } else {
- // Embedded, so no decoration is needed.
- layoutResource = com.android.internal.R.layout.screen_simple;
- // System.out.println("Simple!");
- }
- mDecor.startChanging();
- View in = mLayoutInflater.inflate(layoutResource, null);
- decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
- ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
- if (contentParent == null) {
- throw new RuntimeException("Window couldn't find content container view");
- }
- if ((features & (1 << FEATURE_INDETERMINATE_PROGRESS)) != 0) {
- ProgressBar progress = getCircularProgressBar(false);
- if (progress != null) {
- progress.setIndeterminate(true);
- }
- }
- // Remaining setup -- of background and title -- that only applies
- // to top-level windows.
- if (getContainer() == null) {
- Drawable drawable = mBackgroundDrawable;
- if (mBackgroundResource != 0) {
- drawable = getContext().getResources().getDrawable(mBackgroundResource);
- }
- mDecor.setWindowBackground(drawable);
- drawable = null;
- if (mFrameResource != 0) {
- drawable = getContext().getResources().getDrawable(mFrameResource);
- }
- mDecor.setWindowFrame(drawable);
- // System.out.println("Text=" + Integer.toHexString(mTextColor) +
- // " Sel=" + Integer.toHexString(mTextSelectedColor) +
- // " Title=" + Integer.toHexString(mTitleColor));
- if (mTitleColor == 0) {
- mTitleColor = mTextColor;
- }
- if (mTitle != null) {
- setTitle(mTitle);
- }
- setTitleColor(mTitleColor);
- }
- mDecor.finishChanging();
- return contentParent;
- }
frameworks/base/core/res/res/layout/screen_action_bar.xml frameworks/base/core/res/res/layout/screen_simple.xml
frameworks/base/core/res/res/layout/screen_custom_title.xml frameworks/base/core/res/res/layout/screen_title_icons.xml
frameworks/base/core/res/res/layout/screen_progress.xml frameworks/base/core/res/res/layout/screen_title.xml
frameworks/base/core/res/res/layout/screen_simple_overlay_action_mode.xml frameworks/base/core/res/res/layout/screen.xml
- View in = mLayoutInflater.inflate(layoutResource, null);
- decor.addView(in, new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT));
- ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
- if (contentParent == null) {
- throw new RuntimeException("Window couldn't find content container view");
- }
frameworks/base/core/java/android/view/Window.java 124行:
public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
打开 screen.xml 文件:
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true"
- android:orientation="vertical">
- <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/content"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:foregroundInsidePadding="false"
- android:foregroundGravity="fill_horizontal|top"
- android:foreground="?android:attr/windowContentOverlay" />
- </LinearLayout>
四.
Activity的默认布局确定了,可以确定一下,修改xml 布局:
- diff --git a/base/core/res/res/layout/screen_simple.xml b/base/core/res/res/layout/screen_simple.xml
- index c1914e7..0b7f6e2 100644
- --- a/base/core/res/res/layout/screen_simple.xml
- +++ b/base/core/res/res/layout/screen_simple.xml
- @@ -25,7 +25,8 @@ enabled.
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true"
- - android:orientation="vertical">
- + android:orientation="vertical"
- + android:background="@android:color/holo_orange_dark">
- <ViewStub android:id="@+id/action_mode_bar_stub"
- android:inflatedId="@+id/action_mode_bar"
- android:layout="@layout/action_mode_bar"
- @@ -37,5 +38,6 @@ enabled.
- android:layout_height="match_parent"
- android:foregroundInsidePadding="false"
- android:foregroundGravity="fill_horizontal|top"
- - android:foreground="?android:attr/windowContentOverlay" />
- + android:foreground="?android:attr/windowContentOverlay"
- + android:background="@android:color/holo_green_dark"/>
- </LinearLayout>
homeshell.png
进入HelloWorld,没有任何变化。分析generateLayout的时候已经看到会根据窗口的属性选择不同的资源文件。桌面和一般的Activity使用了不同的资源配置。
修改screen_action_bar.xml
点击(此处)折叠或打开
- diff --git a/base/core/res/res/layout/screen_action_bar.xml b/base/core/res/res/layout/screen_action_bar.xml
- index f0b2313..62b34f6 100644
- --- a/base/core/res/res/layout/screen_action_bar.xml
- +++ b/base/core/res/res/layout/screen_action_bar.xml
- @@ -23,33 +23,39 @@ This is an optimized layout for a screen with the Action Bar enabled.
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:fitsSystemWindows="true"
- - android:splitMotionEvents="false">
- + android:splitMotionEvents="false"
- + android:background="@android:color/holo_red_dark">
- <com.android.internal.widget.ActionBarContainer android:id="@+id/action_bar_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- - style="?android:attr/actionBarStyle">
- + style="?android:attr/actionBarStyle"
- + android:background="@android:color/holo_green_dark">
- <com.android.internal.widget.ActionBarView
- android:id="@+id/action_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- - style="?android:attr/actionBarStyle" />
- + style="?android:attr/actionBarStyle"
- + android:background="@android:color/holo_green_light"/>
- <com.android.internal.widget.ActionBarContextView
- android:id="@+id/action_context_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"
- - style="?android:attr/actionModeStyle" />
- + style="?android:attr/actionModeStyle"
- + android:background="@android:color/white"/>
- </com.android.internal.widget.ActionBarContainer>
- <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" />
- + android:foreground="?android:attr/windowContentOverlay"
- + android:background="@android:color/holo_orange_light"/>
- <com.android.internal.widget.ActionBarContainer android:id="@+id/split_action_bar"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="?android:attr/actionBarSplitStyle"
- android:visibility="gone"
- - android:gravity="center"/>
- + android:gravity="center"
- + android:background="@android:color/holo_blue_light"/>
- </LinearLayout>
activity.png
从图中可以看到根布局是一个FrameLayout布局,就是mDecorView.DecorView extend FrameLayout。 被选中的区域为FrameLayout,就是mcontentParent,mcontentParent中有一个RelativeLayout,是我们setContentView 的R.layout.activity_main 布局文件。
0
上一篇:Android ListActivity学习
下一篇:TextView 滚动
相关热门文章
- Android之开发环境搭建
- Android自定义View的实现...
- AndroidManifest.xml配置文件...
- Android相对布局+圆角按钮+Sha...
- 查看Android应用包名package和...
- linux dhcp peizhi roc
- 关于Unix文件的软链接
- 求教这个命令什么意思,我是新...
- sed -e "/grep/d" 是什么意思...
- 谁能够帮我解决LINUX 2.6 10...
给主人留下些什么吧!~~
评论热议
0 0
- Activity 中view 的布局
- 启动一个子Activity,把Activity生成的View加载在当前的View布局中
- Android中window,view,Activity的关系
- Android中window,view,Activity的关系
- Android中window,view,Activity的关系
- android中Activity、View、Window的理解
- Activity中获取view的宽高
- Android中Activity、View、Window的关系
- Android动态控制布局中view的起点
- 切换Activity中布局的setContentView( )方法
- Android中Activity的简单布局切换
- 关于View的布局
- android 用java反射修改Activity的组件view的布局或者属性
- 在自定义的view中设置activity的控件
- Activity的布局
- 主Activity的布局
- view的相对布局 && InterfaceBuilder中一些属性的使用
- 事件从Activity到布局view再到最终组件的传递过程
- android jni 的编写一(JNI的静态注册)
- activity-alias的使用
- android启动速度优化
- Android ListActivity学习
- 前端浏览器缓存的一些机制和提高性能的方案
- Activity 中view 的布局
- TextView 滚动
- LVM 方式安装Ubuntu 及使用
- VIM 的配置和神一般的插件。
- Android recovery.img 支持adb shell
- 字符编码
- ext4 文件格式 和android ota 流程
- Makefile 总结
- 在frambuffer 下画图
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
床圆床
定做圆床
情趣圆床
圆床厂家
双人圆床价格
酒店圆床价格
圆床房间设计
情侣圆床
定制圆床
圆床酒店
电动圆床价格
欧式圆床卧室
圆床好不好
爱依瑞斯圆床
室内圆床
圆床怎么样
法式圆床
真皮圆床
圆床卧室装修
红色圆床
特价圆床
圆床多钱
哪里有卖圆床的
1.5米圆床
高级圆床
圆床房间图片
日式圆床
女孩圆床
圆床床单
结婚圆床
卧室圆床装修
多功能圆床
睡圆床
龙猫圆床
水床圆床
创意圆床
1.8米圆床
圆床好用吗
圆床宾馆
桑拿圆床
主卧室圆床