Android系统如何实现UI的自适应
做Android应用的人都知道,要一个apk适用多个不同的手机屏幕是很容易的,就是在项目的res文件夹下面有多套相关的资源文件。程序运行的时候,Android系统会根据当前设备的信息去加载不同文件夹下的资源文件。但是Android系统是怎么做到这一点的呢?上网上搜了一下,很少有这方便的介绍,只好自己研究下代码了。下面是我研究代码得到的结果(正确性有待确认),在这里分享一下。
这里以ICS上在Activity的onCreate()方法里面调用setContentView(int resourceID)为例,介绍一下系统如何根据我们的id(R.layout.xxxx)找到合适的layout文件进行解析加载:
如果你的res下面有三种不同的layout:layout, layout-sw480dp和 layout-sw600dp,这里的sw<N>dp表示这个layout文件夹下面的布局文件只有在设备短边的最小宽带为N时才加载。你的设备是800x480的分辨率,那么这个apk安装在你的设备上就会加载 layout-sw480dp里面的布局文件。下面是framework的java层调用链:
Activity.setContentView(int resourceID) -> PhoneWindow.setContentView(int resourceID) -> LayoutInflater.inflate(int resource, ViewGroup root) -> LayoutInflater.inflate(int resource, ViewGroup root, boolean attachToRoot) -> Resources.getLayout(int id) -> Resources.loadXmlResourceParser(int id, String type) -> Resources.getValue(int id, TypedValue outValue, boolean resolveRefs) -> AssetManager.getResourceValue(int ident, int density, TypedValue outValue, boolean resolveRefs) -> AssetManager.loadResourceValue(int ident, short density, TypedValue outValue, boolean resolve)
在上面的掉用链中:
1. 最后加载的是哪个xml是由Resources.getValue(int id, TypedValue outValue, boolean resolveRefs)调用完成之后的outValue.string决定的,因为outValue.string的值就是你的资源文件的具体路径,如:
1) xxx/values/xxx.xml
2) xxx/layout-sw600dp/xxx.xml
2. AssetManager.loadResourceValue()调的是frameworks/base/core/jni/android_util_AssetManager.cpp里面的native方法, 如何获得正确的outValue值,在native方法俩面主要有以下几步:
1) 调用frameworks/base/libs/utils/ResourceTypes.cpp 的ResTable::getResource(),遍历所有资源文件
2) 在ResTable::getResource()里面调用ResTable::getEntry()来确定资源文件来自哪个entry,即layout,或者layout-sw<N>dp,由此可见,ResTable::getEntry()是我们这个问题的关键
3) 在ResTable::getEntry()里面:
a) 首先获取本设备的configurion信息,屏幕分辨率,屏幕大小,locale,横竖屏等。
b) 根据得到的本设备的configurion信息,过滤掉不适应本设备的entry,比如设备是800x480的,那么超过此分辨率的资源(例:layout-sw600dp)就要被过滤掉,实现在frameworks/base/include/utils/ResourceTypes.h中ResTable_config的match函数中
c) 对过滤后的resource进行最佳适配,找到最符合的entry文件。因为之前已经将不符合的,即大分辨率的entry已经被过滤掉了,所以这里就找剩下的最大的就是最佳适配的。实现在frameworks/base/include/utils/ResourceTypes.h中ResTable_config的isBetterThan()函数中。
3. 我做了一个尝试,就是想让800x480分辨率的设备上的应用都加载 layout-sw600dp里面的资源文件。所以将上面b)步骤的frameworks/base/include/utils/ResourceTypes.h里面ResTable_config的match函数改动如下:
/*if (smallestScreenWidthDp != 0 && smallestScreenWidthDp > settings.smallestScreenWidthDp){ return false; }*/ if (smallestScreenWidthDp != 0 && smallestScreenWidthDp > 600) { return false ; } |
我将settings.smallestScreenWidthDp强制换成了600,这样的话,所有比600dp小的(包含600)在内的资源文件在做过滤时就被保留了下来,而c)步骤不做检查,只找最大的,所以layout-sw600dp就成了系统认为的“最合适”的资源问价了。
将重新编译frameworks/base/libs/utils/生成的lib库push到/system/libs下面,再重启手机,然后启动上述应用,就可以了看见程序加载的layout-sw600dp的ui了。
Android系统如何实现UI的自适应的更多相关文章
- android系统如何自适应屏幕大小
1.屏幕相关概念 1.1分辨率 是指屏幕上有横竖各有多少个像素 1.2屏幕尺寸 指的是手机实际的物理尺寸,比如常用的2.8英寸,3.2英寸,3.5英寸,3.7英寸 android将屏幕大小分为四个级别 ...
- Android系统自适应屏幕大小
1.屏幕相关概念1.1分辨率是指屏幕上有横竖各有多少个像素1.2屏幕尺寸指的是手机实际的物理尺寸,比如常用的2.8英寸,3.2英寸,3.5英寸,3.7英寸android将屏幕大小分为四个级别(smal ...
- Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析
参考:Android系统Surface机制的SurfaceFlinger服务渲染应用程序UI的过程分析 一句话概括一下Android应用程序显示的过程:Android应用程序调用SurfaceFlin ...
- 苹果IOS与谷歌 android系统的UI设计原则
一.苹果为IOS的界面设计提出了六大原则: 1.整体美学 整体美学指的是一个应用的表现和行为与它的功能完美集成,传达连贯的信息. 人们关心一个应用是否提供它承诺的功能,但他们也被应用的外观和行为强烈影 ...
- Android系统UI交互控件Action Bar初探
过年期间,Google正式宣布取消Android系统中MENU键的使用,也就是基于Android 4.0系统的手机都应没有MENU这一固定按键.这无疑是个变革性的改动,在我眼中,这似乎把Android ...
- [Android]官网《UI/Application Exerciser Monkey》中文翻译
以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5049041.html 翻译自 Android Develope ...
- Android系统自带APP分析——短信app
Android操作系统本身就是一个巨大的开源软件仓库,熟悉它既可以了解到Android系统的设计框架,也可以获得高效的应用程序编写方式.本文所分析的源码来自于Google官方的AOSP源码4.0.1_ ...
- 深入浅出 - Android系统移植与平台开发(六)- 为Android启动加速
作者:唐老师,华清远见嵌入式学院讲师. Android的启动速度一直以来是他的诟病,虽然现在Android设备的硬件速度越来越快,但是随着新 版本的出现,其启动速度一直都比较慢,当然,作为程序员,我们 ...
- 从Android系统出发,分析Android控件构架
从Android系统出发,分析Android控件构架 Android中所有的控件追溯到根源,就是View 和ViewGroup,相信这个大家都知道,但是大家也许会不太清楚它们之间的具体关系是什么,在A ...
随机推荐
- poj 1850 1019 (简单位数dp)
#include<iostream> #include<cstdio> #include<cstring> using namespace std; ][],l,a ...
- parent.location.href和location.href区别
parent.location.href='ind.php'parent用于框架结构,需要全网页转向如果你的网页是左右框架,那么,直接把当前页面全部转到ind.php中 location.href=' ...
- RecyclerView更通用——listView的onItemClick,onLongItemClick,addHeaderView,addFooterView
一.点击事件 setOnItemClickListener,setOnItemLongClickListener RecyclerView中虽然没有提供上面这两个接口,但是给我们提供了另外一个接口:O ...
- Linux下批量替换文件内容方法
1:查找find . -type f -name "*.html"|xargs grep ‘yourstring’ 2:查找并替换find -name '要查找的文件名' | xa ...
- mvc wcf 并发提示,存储Application,验证是否有用户在操作
System.Web.HttpContext httpContext = System.Web.HttpContext.Current; Hashtable departmentSalary = (H ...
- java2实用教程102小程序(分数计算和流水线计算
import java.util.Scanner; public class test{ public static void main(String args[]){ Rational a=new ...
- 如何实现一个通用的IHttpHandler 万能的IHttpHandler HttpWebRequest文件上传
昨天遇到一个比较奇怪的需求,大致是需要在服务器上部署一个http服务,但是服务的具体功能不知道,以后在客服端实现.这里介绍一下系统背景,有一个系统运(部署在美国)行了很多年了,给系统产生了很多文件,现 ...
- 将Activity设置成半透明的对话框
将Activity设置成半透明的对话框 在定义Activity时指定Theme.Dialog主题就可以将Activity设置成对话框风格.通过修饰Theme.Dialog主题的android:wind ...
- NT头 IMAGE_NT_HEADER
typedef struct_IMAGE_NT_HEADERS{ DWORD Signature; // 固定为 0x00004550 “PE00" IMAGE_FILE_HEADER Fi ...
- python实现发工资脚本
好开心啊,在旁边大神的帮助下,终于实现了发工资的python脚本,之前用shell写的老出错,刚才测试,发80个人工资详情,妥妥的,代码如下: from email.mime.multipart im ...