android6.0原生brower_android原生browser分析(二)--界面篇
我们先看一张浏览器的主界面,上面标示浏览器界面各部分对应的类,这里是以平板上的界面为例。给张图是为了给大家一个直观的感觉。
BrowserActivity是整个应用的主界面,在onCreate中创建了Controller对象,Controller对象是整个应用最重要的管理类,这个后面再说。
@Override
public void onCreate(Bundle icicle) {
mController = createController();
}
Controller的创建中新建了UI类,UI 类是最主要的视图类,它虽然不是 View 类的子类,只是一个包含很多抽象方法的接口,但是它的实现类包含了重要的 View 视图成员。后面将通过 UI 的实现类 BaseUi 将这些视图成员和 BrowserActivity中布局文件中视图ID一一对应起来,关于这点后面描述。
private Controller createController() {
Controller controller = new Controller(this);
boolean xlarge = isTablet(this);
UI ui = null;
if (xlarge) {
ui = new XLargeUi(this, controller);
} else {
ui = new PhoneUi(this, controller);
}
controller.setUi(ui);
return controller;
}
由上,我们看到根据isTablet() 方法获取的值,将会创建不同的 UI 类。
看一下isTablet()方法:
public static boolean isTablet(Context context) {
return context.getResources().getBoolean(R.bool.isTablet);
}
可以看出,这里是通过一个资源文件的值来确定的,实际上这里是用来区分这个是手机应用还是平板应用的。取值为true的时候获取的是XLargeUi对象,取值为false 的时候,获取的是 PhoneUi 对象。 由于我的项目是平板的,就以XLargeUi 为例进行分析。
在此,我们把这几个类的继承关系理一理:
public interface UI {
//....
}
public abstract class BaseUi implements UI {
//...
}
public class XLargeUi extends BaseUi {
//...
}
public class PhoneUi extends BaseUi {
//...
}
我们现在来看看XLargeUi 的定义:
public class XLargeUi extends BaseUi {
private ActionBar mActionBar;
private TabBar mTabBar;
private NavigationBarTablet mNavBar;
/**
* @param browser
* @param controller
*/
public XLargeUi(Activity browser, UiController controller) {
super(browser, controller);
//other code
mNavBar = (NavigationBarTablet) mTitleBar.getNavigationBar();
mTabBar = new TabBar(mActivity, mUiController, this);
mActionBar = mActivity.getActionBar();
setupActionBar();
}
private void setupActionBar() { mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
mActionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
mActionBar.setCustomView(mTabBar);
}
//other code
}
构造方法中传入了两个参数,第一个是应用的主界面 BrowserActivity ,第二个是 UiController 对象,该对象主要做 Ui 进行控制,如对选项卡的操作,加载 URL 等。
构造函数中主要做了下面的事情:
1 、通过 TitleBar 类型成员变量 mTitleBar获取NavigationBarTablet类型的对象mNavBar ,这个对象即是导航工具栏。就是浏览器界面的如下的工具栏
该对象主要用于更新导航栏的状态,即对前进后退键、 URL 输入框、 URL图标进行操作。
成员变量mTitleBar是从 BaseUi 继承而来的。
2 、 新创建一个TabBar类型的对象,这个TabBar对象是只有平板才有的。创建时传入主界面 BrowserActivity 、UiController 对象、XLargeUi自身。创建的对象即选项卡栏
该对象将用来进行选项卡的相关操作,增加、删除、更新选项卡,改变收藏夹图标favicon ,修改 URL 标题等。
3 、通过 主界面 BrowserActivity 获取 ActionBar 对象。
4 、设置 ActionBar 的样式,并将选项卡栏 TabBar对象设置为 ActionBar 的自定义视图。
关于 BaseUi
BaseUi 是平板界面 XLargeUi和手机界面 PhoneUi 共有的父类。
public abstract class BaseUi implements UI {
Activity mActivity;
UiController mUiController;
TabControl mTabControl;
private UrlBarAutoShowManager mUrlBarAutoShowManager;
protected TitleBar mTitleBar;
private NavigationBarBase mNavigationBar;
protected PieControl mPieControl;
public BaseUi(Activity browser, UiController controller) {
mActivity = browser;
mUiController = controller;
mTabControl = controller.getTabControl();
FrameLayout frameLayout = (FrameLayout) mActivity.getWindow()
.getDecorView().findViewById(android.R.id.content);
LayoutInflater.from(mActivity)
.inflate(R.layout.custom_screen, frameLayout);
//...
setFullscreen(BrowserSettings.getInstance().useFullscreen());
mTitleBar = new TitleBar(mActivity, mUiController, this,
mContentView);
mTitleBar.setProgress(100);
mNavigationBar = mTitleBar.getNavigationBar();
mUrlBarAutoShowManager = new UrlBarAutoShowManager(this);
}
}
先从构造方法来看:
构造方法传入了两个参数:第一个是应用的主界面 BrowserActivity ,第二个是 UiController 对象,也就是创建XLargeUi时传入的两个参数。
构造方法中主要完成了如下的事情:
1 、通过 UiController 对象获取 TabControl 类型的对象 mTabControl 。
2 、为 BrowserActivity设置视图。查看BrowserActivity的代码,通篇没有找到 setContentView 的影子,那么它是怎么为 activity 设置视图的呢?原来是在这里。
FrameLayout frameLayout = (FrameLayout) mActivity.getWindow()
.getDecorView().findViewById(android.R.id.content);
LayoutInflater.from(mActivity)
.inflate(R.layout.custom_screen, frameLayout);
这里是将资源文件对应的视图加入到 android.R.id.content 定义的 FrameLayout 中。这是怎么回事呢?
原来 activity 中的 setContentView 如下:
public void setContentView(int layoutResID) {
getWindow().setContentView(layoutResID);
//...
}
Activity 中:
public Window getWindow() {
return mWindow;
}
mWindow = PolicyManager.makeNewWindow(this);
PolicyManager 中:
public final class PolicyManager {
private static final String POLICY_IMPL_CLASS_NAME =
"com.android.internal.policy.impl.Policy";
private static final IPolicy sPolicy;
static {
try {
Class policyClass = Class.forName(POLICY_IMPL_CLASS_NAME);
sPolicy = (IPolicy)policyClass.newInstance();
} catch (InstantiationException ex) {
throw new RuntimeException( "exception", ex);
}
}
public static Window makeNewWindow(Context context) {
return sPolicy.makeNewWindow(context);
}
}
IPolicy 中:
public interface IPolicy {
public Window makeNewWindow(Context context);
}
Policy 中
public class Policy implements IPolicy
//...
public Window makeNewWindow(Context context) {
return new PhoneWindow(context);
}
}
所以 Activity 的 getWindow() 获取的是 PhoneWindow 对象。
而 PhoneWindow 继承了 Window ,并覆写了 setContentView , PhoneWindow 中 setContentView(int layoutResID) 方法如下:
@Override
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();
}
}
就是将该布局资源文件填入 mContentParent ,那么 mContentParent 是什么呢?看下面
private void installDecor() {
if (mContentParent == null) {
mContentParent = generateLayout(mDecor);
//....
}
}
protected ViewGroup generateLayout(DecorView decor) {
//...
ViewGroup contentParent = (ViewGroup)findViewById(ID_ANDROID_CONTENT);
//...
return contentParent;
}
由上可知,是由 ID 为 ID_ANDROID_CONTENT 的资源文件定义的。
该值由 Window 类继承而来,看看定义
public static final int ID_ANDROID_CONTENT = com.android.internal.R.id.content;
mActivity.getWindow() 获得一个 Window 对象,该对象调用 getDecorView() 找到的 android.R.id.content ,正是此处的 com.android.internal.R.id.content ,所以 activity 的 setContentView 实际就是将 view 加入到 android.R.id.content 定义的 ViewGroup 中,上面的第二步操作就等价于在 BrowserActivity中 setContentView 。
3 、根据 BrowserSettings 中的配置值设置是否全屏。
4 、新建一个 TitleBar 对象。需要传入的参数是 BrowserActivity,UiController, BaseUi , FrameLayout, 前两个参数是作为 BaseUi 构造方法的参数传进来的,第三个是 BaseUi 本身,第四个参数是布局中的一个 FrameLayout 。 TitleBar 对象是手机和平板共有的,而 TabBar 是平板特有的,故有这样的设计。
5 、设置 TitleBar 中的 ProgressBar 的最大值为 100 。这个 ProgressBar 也就是显示加载网页的进度的。加载时显现,加载完毕时消失。
6 、获得 NavigationBarBase 对象,在平板中获得的是 NavigationBarTablet,在手机中获得的是NavigationBarPhone. 即导航栏。
7 、创建一个 UrlBarAutoShowManager 对象,该对象用来控制网页滚动过程中显示和隐藏标题栏 TitleBar.
回过头来看一下XLargeUi ,我们提到了NavigationBarTablet类型的对象mNavBar和TabBar类型的对象,为什么这两个不在 BaseUi 里面定义呢?
这是因为这两个是平板界面中特有的,手机界面中不存在。mNavBar在手机界面中是转为NavigationBarPhone 类型的,而 TabBar是选项卡栏,手机屏幕小,所有没有选项卡栏。
android6.0原生brower_android原生browser分析(二)--界面篇相关推荐
- Android原生(Native)C开发之二 framebuffer篇
为什么80%的码农都做不了架构师?>>> Android原生(Native)C开发之二 framebuffer篇 如对Android原生(Natvie)C开发还任何疑问,请参阅 ...
- android6.0中app crash流程分析
要根据这个流程分析一下如何在应用中截获系统的app crash弹框,然后做到更人性化 基于Android 6.0的源码剖析, 分析Android应用Crash是如何处理的. /frameworks/b ...
- Android 系统(41)---Android7.0 PowerManagerService亮灭屏分析(二)
Android7.0 PowerManagerService亮灭屏分析(二) 3029 在PowerManagerService中对各种状态进行判断后,将其数值封装进DisplayPowerReque ...
- Android6.0 Sensor架构和问题分析
本文在借鉴网友的资料后再重新梳理了一遍,都是站在前人的基础.巨人的肩膀上再次总结分析出来的,仅供大家参考! 本文主要描述了在Android 6.0系统.MTK6755平台上sensor相关软硬件的体系 ...
- Android6.0的Looper源码分析(1)
1 Looper简介 Android在Java标准线程模型的基础上,提供了消息驱动机制,用于多线程之间的通信.而其具体实现就是Looper. Android Looper的实现主要包括了3个 ...
- 值得你关注的Android6.0上的重要变化(二)
十.Android KeyStore变化 此版本上Android Keystore provider不再支持DSA,仍旧支持ECDSA. 锁屏密码在(如用户或设备管理器)禁用或重置的情况下,不 ...
- Android6.0 mtk去除原生相机设置中的选项
Android去除原生相机设置中的录像中的一些选项,其中代码路径是: 6753_M\alps\vendor\mediatek\proprietary\packages\apps\Camera\src\ ...
- Android7.0 PowerManagerService亮灭屏分析(二)
在PowerManagerService中对各种状态进行判断后,将其数值封装进DisplayPowerRequest中传入DisplayPowerController中进一步处理.在亮屏过程中Disp ...
- [Android6.0][RK3399] PWM Backlight 驱动分析
DTS 分析 backlight: backlight {status = "disabled";compatible = "pwm-backlight";pw ...
最新文章
- python列表遍历 空列表_Python list列表执行reversed()后执行pop()返回迭代对象遍历为空问题...
- 最短路径——Floyd算法HDU Today(hdu2112)
- ROS笔记(13) 记录与回放数据
- gradle 不支持多级子模块_解决gradle多模块依赖在Idea中能运行,gradle build失败的问题。...
- lda 协方差矩阵_数据降维算法总结(LDAamp;PCA)
- react ssr php,一文吃透 React SSR 服务端渲染和同构原理
- 〖Demo〗-- 多级评论
- Java面试题:程序计数器为什么是私有的?
- Socket TCP UDP
- 从超大规模云服务提供商处学习效率
- Multisim14.1中/英文版软件下载和安装教程|兼容WIN10
- Linux redis常用命令
- 关于彻底卸载手心输入法的终极操作
- Nginx-RTMP功能调研
- Unity内动态影子的各种做法
- Aspose.Words 将Word(DOC / DOCX)转换为HTML教程
- telegraf 使用 inputs.exec插件收集监控数据
- Spring Boot(二): 集成Mybatis
- 2021年全球与中国重型泥浆泵行业市场规模及发展前景分析
- Python全栈面试题