Android 屏幕适配
一、适配方式之dp
名词解释
分辨率:480*800,1280*720。表示物理屏幕区域内像素点的总和。(切记:跟屏幕适配没有任何关系)
因为我们既可以把1280*720 的分辨率做到4.0 的手机上面。我也可以把1280*720 的分辨率做到5.0 英寸的手机上面,如果分辨率相同,手机屏幕越小清晰。
px:pixels 的意思,像素,就是屏幕中最小的一个显示单元,是屏幕的物理像素点,与密度相关,密度大了,单位面积上的px 会比较多。
sp:与刻度无关的单位,同dip/dp 相似,会根据用户的字体大小偏好来缩放,主要用于设置字体的大小
dpi:dpi :dots per inch,像素密度,即每英寸屏幕所拥有的像素数,像素密度越大,显示画面细节就越丰富。常见取值120,160,240,320,480
计算公式:像素密度=\sqrt{(长度像素数^2+宽度像素数^2)}/ 屏幕尺寸
注意:屏幕尺寸单位为英寸,例:分辨率为1280*720 屏幕宽度为6 英寸计算所得像素密度约等于245,屏幕尺寸指屏幕对角线的长度
在Android 手机中dpi 分类:
dpi | 说明 |
---|---|
ldpi | Resources for low-density (ldpi) screens (~120dpi) |
mdpi | Resources for medium-density (mdpi) screens (~160dpi). (This is the baseline density.) |
hdpi | Resources for high-density (hdpi) screens (~240dpi). |
xhdpi | Resources for extra high-density (xhdpi) screens (~320dpi). |
在我们的Android 工程目录中有如下drawable-*dpi 目录,这些目录是用来适配不同分辨率手机的。
Android 应用在查找图片资源时会根据其分辨率自动从不同的文件目录下查找(这本身就是Android 系统的适配策略),如果在低分辨的文件目录中比如drawable-mdpi 中没有图片资源,其他目录中都有,当我们将该应用部署到mdpi 分辨率的手机上时,那么该应用会查找分辨率较高目录下的资源文件,如果较高分辨率目录下也没有资源则只好找较低目录中的资源了。
常见手机屏幕像素及对应分别率级别:
- ldpi:320*240
- mdpi:480*320
- hdpi:800*480
- xhdpi:1280*720
- xxhdpi:1920*1080
dp 和px 之间的简单换算关系:
- ldpi 的手机:1dp=0.75px
- mdpi 的手机:1dp=1.0px
- hdpi 的手机:1dp=1.5px
- xhdpi 的手机:1dp=2.0px
- xxhdpi 的手机:1dp=3.0px
Tips:根据上面的描述我们得出如下结论,对于mdpi 的手机,我们的布局通过dp 单位可以达到适配效果
dp 和px 之间的关系
Android 官方定义dip 等价于160dpi 屏幕下的一个物理像素点,即1dip=1px。转换公式如下:
dip =(dpi/(160 像素/英寸))px = density px
举例来说,在240 dpi 的屏幕上,1dip 等于1.5px
density :直接翻译的话也叫密度,但是他在Android 中特指dp 和px 的比例关系。常见取值1.5 ,1.0
dp:是dip(Density independent pixels) 的简写,指密度无关的像素。指一个抽象意义上的像素,程序用它来定义界面元素。一个与密度无关的,在逻辑尺寸上,与一个位于像素密度为160dpi 的屏幕上的像素是一致的。要把密度无关像素转换为屏幕像素,可以用这样一个简单的公式:
pixels=dips*(density/160)
举个例子,在DPI 为240 的屏幕上,1 个DIP 等于1.5 个物理像素。
布局时最好使用dp 来定义我们程序的界面,因为这样可以保证我们的UI 在各种分辨率的屏幕上都可以正常显示。
/*** 根据手机的分辨率从px(像素) 的单位转成为dp*/public static int px2dip(Context context, float pxValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (pxValue / scale + 0.5f);}/*** 根据手机的分辨率从dip 的单位转成为px(像素)*/public static int dip2px(Context context, float dpValue) {final float scale = context.getResources().getDisplayMetrics().density;return (int) (dpValue * scale + 0.5f);}
二、适配方式之dimens
跟drawable 目录类似的,在Android 工程的res 目录下有values 目录,这个是默认的目录,同时为了适配不同尺寸手机我们可以创建一个values-1280x720 的文件夹,同时将dimens.xml 文件拷贝到该目录下
在dimens.xml 中定义一个尺寸,如下所示
<resources><dimen name="width">160dp</dimen>
</resources>
在values-1280x720 目录中的dimens.xml 中定义同样的尺寸名称,但是使用不同的尺寸,如下所示
<resources><dimen name="width">180dp</dimen>
</resources>
当我们在布局文件中使用长或者宽度单位时,比如下图所示,应该使用@dimen/width 来灵活的定义宽度
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><TextView
android:layout_width="@dimen/width"android:layout_height="wrap_content"/></LinearLayout>
Tips:在values-1280x720 中, 中间的是大写字母X 的小写形式x , 而不是加减乘除的乘号。如果我们在values-1280x720 中放置了dimens 常量,一定记得也将该常量的对应值在values 目录下的dimens.xml 中放一份,因为该文件是默认配置,当用户的手机不是1280*720 的情况下系统应用使用的是默认values 目录中的dimens.xml
三、适配方式之layout
跟values 一样,在Android 工程目录中layout 目录也支持类似values 目录一样的适配,在layout 中我们可以针对不同手机的分辨率制定不同的布局,如下图所示
四、适配方式之java 代码适配
为了演示用java 代码控制适配的效果,因此假设有这样的需求,让一个TextView 控件的宽和高分别为屏幕的宽和高的一半。
我们新创建一个Android 工程,修改main_activity.xml,布局文件清单如下:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><!-- 当前控件宽高为屏幕宽度的各50% --><TextView
android:id="@+id/tv"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#000000"android:text="@string/hello_world"/>
</RelativeLayout>
在MainActivity.java 类中完成用java 代码控制TextView 的布局效果,其代码清单如下:
public class MainActivity extends Activity {private static final String tag = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//去掉titlerequestWindowFeature(Window.FEATURE_NO_TITLE);setContentView(R.layout.activity_main);//获取TextView 控件TextView tv = (TextView) findViewById(R.id.tv);//找到当前控件的夫控件(父控件上给当前的子控件去设定一个规则)DisplayMetrics metrics = new DisplayMetrics();//给当前metrics 去设置当前屏幕信息(宽(像素)高(像素))getWindowManager().getDefaultDisplay().getMetrics(metrics);//获取屏幕的高度和宽度Constant.srceenHeight = metrics.heightPixels;Constant.srceenWidth = metrics.widthPixels;//日志输出屏幕的高度和宽度Log.i(tag, "Constant.srceenHeight = "+Constant.srceenHeight);Log.i(tag, "Constant.srceenWidth = "+Constant.srceenWidth);//宽高各50%RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(//数学角度上四舍五入(int)(Constant.srceenWidth*0.5+0.5),(int)(Constant.srceenHeight*0.5+0.5));//给tv 控件设置布局参数tv.setLayoutParams(layoutParams);}}
其中Constant 类是一个常量类,很简单,只有两个常量用来记录屏幕的宽和高,其代码清单如下:
public class Constant {public static int srceenHeight;public static int srceenWidth;
}
五、适配方式之weight 权重适配
在控件中使用属性android:layout_weight=”1”可以起到适配效果,但是该属性的使用有如下规则:
- 只能用在线性控件中,比如LinearLayout。
- 竖直方向上使用权重的控件高度必须为0dp(Google 官方的推荐用法)
- 水平方向上使用权重的控件宽度必须为0dp(Google 官方的推荐用法)
六、屏幕适配的处理技巧
手机自适应主要分为两种情况:横屏和竖屏的切换,以及分辨率大小的不同。
横屏和竖屏的切换
Android 应用程序支持横竖屏幕的切换,Android 中每次屏幕的切换动会重启Activity,所以应该在Activity销毁(执行onPause()方法和onDestroy()方法)前保存当前活动的状态;在Activity 再次创建的时候载入配置,那样,进行中的游戏就不会自动重启了!有的程序适合从竖屏切换到横屏,或者反过来,这个时候怎么办呢?可以在配置Activity 的地方进行如下的配置android:screenOrientation=”portrait”(landscape 是横向,portrait 是纵向)。这样就可以保证是竖屏总是竖屏了。
而有的程序是适合横竖屏切换的。如何处理呢?首先要在配置Activity 的时候进行如下的配置:
android:configChanges="keyboardHidden|orientation"
另外需要重写Activity 的onConfigurationChanged ()方法。实现方式如下:
@Overridepublic void onConfigurationChanged(Configuration newConfig){super.onConfigurationChanged(newConfig);if(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE){//TODO}elseif(this.getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT){//TODO}}
分辨率大小不同
对于分辨率问题,官方给的解决办法是创建不同的layout 文件夹,这就需要对每种分辨率的手机都要写一个布局文件,虽然看似解决了分辨率的问题,但是如果其中一处或多处有修改了,就要每个布局文件都要做出修改,这样就造成很大的麻烦。那么可以通过以下几种方式解决:
1、使用layout_weight
目前最为推荐的Android 多屏幕自适应解决方案。
该属性的作用是决定控件在其父布局中的显示权重,一般用于线性布局中。其值越小,则对应的layout_width或layout_height 的优先级就越高(一般到100 作用就不太明显了);一般横向布局中,决定的是layout_width 的优先级;纵向布局中,决定的是layout_height 的优先级。
传统的layout_weight 使用方法是将当前控件的layout_width 和layout_height 都设置成fill_parent,这样就可以把控件的显示比例完全交给layout_weight;这样使用的话,就出现了layout_weight 越小,显示比例越大的情况(即权重越大,显示所占的效果越小)。不过对于2 个控件还好,如果控件过多,且显示比例也不相同的时候,控制起来就比较麻烦了,毕竟反比不是那么好确定的。于是就有了现在最为流行的0px 设值法。看似让人难以理解的layout_height=0px 的写法,结合layout_weight,却可以使控件成正比例显示,轻松解决了当前Android 开发最为头疼的碎片化问题之一。
2、清单文件配置
不建议使用这种方式,需要对不同的界面写不同的布局
需要在AndroidManifest.xml 文件的元素如下添加子元素
<supports-screens android:largeScreens="true"android:normalScreens="true"android:anyDensity="true"android:smallScreens="true"android:xlargeScreens="true"></supports-screens>
以上是为我们的屏幕设置多分辨率支持(更准确的说是适配大、中、小三种密度)。
Android:anyDensity="true"
这一句对整个的屏幕都起着十分重要的作用,值为true,我们的应用程序当安装在不同密度的手机上时,程序会分别加载hdpi,mdpi,ldpi 文件夹中的资源。相反,如果值设置为false,即使我们在hdpi,mdpi,ldpi,xdpi 文件夹下拥有同一种资源,那么应用也不会自动地去相应文件夹下寻找资源。而是会在大密度和小密度手机上加载中密度mdpi 文件中的资源。
有时候会根据需要在代码中动态地设置某个值,可以在代码中为这几种密度分别设置偏移量,但是这种方法最好不要使用,最好的方式是在xml 文件中不同密度的手机进行分别设置。这里地图的偏移量可以在values-xpdi,values-hpdi,values-mdpi,values-ldpi 四种文件夹中的dimens.xml 文件进行设置。
其他
说明:
- 在不同分辨率的手机模拟器下,控件显示的位置会稍有不同
- 通过在layout 中定义的布局设置的参数,使用dp(dip),会根据不同的屏幕分辨率进行适配
- 但是在代码中的各个参数值,都是使用的像素(px)为单位的
技巧:
1、尽量使用线性布局,相对布局,如果屏幕放不下了,可以使用ScrollView(可以上下拖动)
ScrowView 使用的注意:
在不同的屏幕上显示内容不同的情况,其实这个问题我们往往是用滚动视图来解决的,也就是ScrowView;需要注意的是ScrowView 中使用layout_weight 是无效的,既然使用ScrowView 了,就把它里面的控件的大小都设成固定的吧。
2、指定宽高的时候,采用dip 的单位,dp 单位动态匹配
3、由于android 代码中写的单位都是像素,所有需要通过工具类进行转化
4、尽量使用9-patch 图,可以自动的依据图片上面显示的内容被拉伸和收缩。其中在编辑的时候,灰色区域是被拉伸的,上下两个点控制水平方向的拉伸,左右两点控制垂直方向的拉伸
百分比布局
百分比布局github 地址
支持百分比设置的布局有百分比相对布局PercentRelativeLayout、百分比线性布局PercentLinearLayout、
百分比帧布局PercentFrameLayout,它们的使用与之前的常用布局使用类似。
百分比相对布局PercentRelativeLayout 中包含了3 个view 控件,前2 个view 是显示在第三个view 上面,第一个view 设置了父控件高度的百分之二十,父控件宽度的百分之七十,第二个view 显示在第一个view 的右边并设置了父控件高度的百分之二十,父控件宽度的百分之三十。这样前2个view 的刚好显示整个屏幕的宽度,屏幕高度的百分之二十。第三个view 设置了父控件高度的百分之八十,宽度为整个屏幕。这样百分比就设置好了,运行效果如图所示。
因为百分比支持库是随着Android Support Library 23 一起的,如果要使用请确保你已经在SDKManager 中的Android Support Library 更新了最新的版本。然后在build.gradle 文件中添加下面这样的依赖:
compile 'com.android.support:percent:23.0.0'
布局文件
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><View
android:id="@+id/top_left"android:layout_width="0dp"android:layout_height="0dp"android:layout_alignParentTop="true"android:background="#ff44aacc"app:layout_heightPercent="20%"app:layout_widthPercent="70%" /><View
android:id="@+id/top_right"android:layout_width="0dp"android:layout_height="0dp"android:layout_alignParentTop="true"android:layout_toRightOf="@+id/top_left"android:background="#ffe40000"app:layout_heightPercent="20%"app:layout_widthPercent="30%" /><View
android:id="@+id/bottom"android:layout_width="match_parent"android:layout_height="0dp"android:layout_below="@+id/top_left"android:background="#ff00ff22"app:layout_heightPercent="80%" />
</android.support.percent.PercentRelativeLayout>
动态加载布局
使用限定符
屏幕大小,layout-large
限定符 | 描述 |
---|---|
small | 小屏幕 |
normal | 中等屏幕 |
large | 大屏幕 |
xlarge | 超大屏幕 |
分辨率
分辨率 | 描述 |
---|---|
ldpi | 低分辨率,120dpi以下 |
mdpi | 中等分辨率,120~160dpi |
hdpi | 高分辨率,160~240dpi |
xhdpi | 超高分辨率,240~320dpi |
xxhdpi | 超超高分辨率,320~480dpi |
方向
屏幕方向 | 描述 |
---|---|
land | 横屏 |
port | 竖屏 |
最小宽度限定符,layout-sw600dp
- Android 屏幕适配方案
- Android 百分比布局库(percent-support-lib) 解析与扩展
- Android 增强版百分比布局库 为了适配而扩展
- Android AutoLayout全新的适配方式 堪称适配终结者
Android 屏幕适配相关推荐
- 鸿洋android屏幕适配四部曲-传送门
鸿洋android屏幕适配四部曲-传送门 两分钟理解Android中PX.DP.SP的区别 https://blog.csdn.net/donkor_/article/details/77680042 ...
- android屏幕适配详解
android屏幕适配详解 官方地址:http://developer.android.com/guide/practices/screens_support.html 一.关于布局适配建议 1.不要 ...
- Android屏幕适配全攻略(最权威的官方适配指导)(转),共大家分享。
Android的屏幕适配一直以来都在折磨着我们这些开发者,本篇文章以Google的官方文档为基础,全面而深入的讲解了Android屏幕适配的原因.重要概念.解决方案及最佳实践,我相信如果你能认真的学习 ...
- Android屏幕适配全攻略(最权威的官方适配指导) (转)
招聘信息: Cocos2d-X 前端主程 [新浪微博]手机客户端iOS研发工程师 20k-40k iOS 开发工程师 iOS高级开发工程师(中国排名第一的企业级移动互联网云计算公司 和创科技 红圈营销 ...
- android 屏幕分辨率 屏幕密度,Android屏幕适配——多分辨率多屏幕密度
为什么要适配,适配的好处等等这里就不说了,直接说我们要怎么适配,请看下面的内容. 1.重要概念 px:pixel,像素Android原生API,UI设计计量单位,如获取屏幕宽高. 屏幕分辨率:指在纵向 ...
- 【收藏】Android屏幕适配全攻略(最权威的Google官方适配指导)
来源:http://blog.csdn.net/zhaokaiqiang1992 更多:Android AutoLayout全新的适配方式, 堪称适配终结者 Android的屏幕适配一直以来都在折磨着 ...
- Android 屏幕适配攻略(六)设置通知样图标与启动图标适配
Android 屏幕适配攻略(六)设置通知样图标与启动图标适配 1 Android中资源文件中的图片加载分析 Android中对屏幕的像素适配处理分类 屏幕密度 对应的标签 对应的像素 120dip ...
- Android 动态创建控件并设置控件的大小之Android屏幕适配攻略(五)
Android 屏幕适配攻略(五)动态创建控件并设置控件的大小 题记 -- 执剑天涯,从你的点滴积累开始,所及之处,必精益求精,即是折腾每一天. 重要消息 flutter中网络请求dio使用分析 视频 ...
- Android 屏幕适配攻略(四)获取手机屏幕的相关信息 与动态设置控件的大小
Android 屏幕适配攻略(四)获取手机屏幕的相关信息 与动态设置控件的大小 1 动态获取手机屏幕的 屏幕密度与对应像素比例 例如在 320 * 480 尺寸为 3.2 英寸的手机 ,对应的像素密度 ...
最新文章
- 批量处理SQL Oracle下:
- C 语言编程 — 运算符
- svn仓库出现already locked error解决方法:cleanup
- 微信小程序勾选协议与提交按钮联动
- Android-PopupWindow
- SPARK安装一:Windows下VirtualBox安装CentOS
- 【HDU - 3440】House Man(差分约束)
- PowerDesigner逆向工程从现有数据库生成PDM
- 打开页面直接显示内容
- Transaction And Lock--已提交读快照
- WUSTOJ 1285: Factors(Java)
- gb2312编码在线转换_文件打开乱码?来了解一下文件编码
- Java关键字和标识符
- java中如何实现货币兑换_java货币转换
- 探寻微博背后的大数据原理:微博推荐算法简述
- 基于Xposed修改微信运动步数
- ubuntu修复linux分区表,硬盘分区表的修复(Ubuntu安装盘的另类用法)
- linux下登录不上oracle,Oracle特定用户登录失败案例 ORA-20001
- 记录:英文参考文献格式
- 【中秋系列】马上中秋了,给老板写了个猜灯谜小脚本,猜到的越多奖金就越高?赚翻了~