我们先来了解下Android屏幕适配的背景
由于Android系统的开放性,任何用户、开发者、OEM厂商、运营商都可以对Android进行定制,修改成他们想要的样子
这无形之中导致了Android屏幕碎片化愈来愈严重,屏幕愈来愈多样化
如需详细数据,请走这边,我的翻译能力还是有限度的,只能保证看懂,但是翻译起来还是有难度的,所以各位看官还是自给自足吧
背景基本就是这样子了,说下基本概念吧
屏幕尺寸
屏幕尺寸指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米
比如常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等
屏幕分辨率
屏幕分辨率是指在横纵向上的像素点数,单位是px,1px=1个像素点。一般以纵向像素*横向像素,如1960*1080。
屏幕像素密度
屏幕像素密度是指每英寸上的像素点数,单位是dpi,即“dot per inch”的缩写。屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。
dp、dip、dpi、sp、px
px我们应该是比较熟悉的,前面的分辨率就是用的像素为单位,大多数情况下,比如UI设计、Android原生API都会以px作为统一的计量单位,像是获取屏幕宽高等。
dip和dp是一个意思,都是Density Independent Pixels的缩写,即密度无关像素,上面我们说过,dpi是屏幕像素密度,假如一英寸里面有160个像素,这个屏幕的像素密度就是160dpi,那么在这种情况下,dp和px如何换算呢?在Android中,规定以160dpi为基准,1dip=1px,如果密度是320dpi,则1dip=2px,以此类推。
假如同样都是画一条320px的线,在480*800分辨率手机上显示为2/3屏幕宽度,在320*480的手机上则占满了全屏,如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。这也是为什么在Android开发中,写布局的时候要尽量使用dp而不是px的原因。
而sp,即scale-independent pixels,与dp类似,但是可以根据文字大小首选项进行放缩,是设置字体大小的御用单位。
mdpi、hdpi、xdpi、xxdpi
名称 | 像素密度 | 启动图标 | 倍数 |
---|---|---|---|
mdpi | 120dpi-160dpi | 48x48px | 1x |
hdpi | 160dpi-240dpi | 72x72px | 1.5x |
xhdpi | 240dpi-320dpi | 96x96px | 2x |
xxhdpi | 320dpi-480dpi | 144x144px | 3x |
xxxhdpi | 480dpi-640dpi | 192x192px | 4x |
到这里我们已经基本了解了Android适配的原因和Android适配的名词,接下来便来简单聊聊怎么做Android的屏幕适配工作
1.在适合的情况下使用使用适合的图片,就如下图所示,没有趁手的图片,就用原生图标,你们就凑合着看吧
2.合理使用warp_parent,match_parent,weight,权重的使用还是比较多的,也就是大家经常所说的百分比,一般都会使用0dp,较少的使用match_parent。
3.使用相对布局,线性布局,帧布局(FrameLayout),基本不使用绝对布局
相对布局会极大可能做出正确的位置关系,防止两个view之间产生错位的现象
无论使用哪种布局,view的大小都会随着设备dpi的变化产生相应的变化,但是相对位置不会产生过分的变化
4.使用尺寸限定符
上面所提到的灵活布局或者是相对布局,可以为我们带来的优势就只有这么多了。虽然这些布局可以拉伸组件内外的空间以适应各种屏幕,但它们不一定能为每种屏幕都提供最佳的用户体验。因此,我们的应用不仅仅只实施灵活布局,还应该应针对各种屏幕配置提供一些备用布局。
如何做到这一点呢?我们可以通过使用配置限定符,在运行时根据当前的设备配置自动选择合适的资源了,例如根据各种屏幕尺寸选择不同的布局。
很多应用会在较大的屏幕上实施“双面板”模式,即在一个面板上显示项目列表,而在另一面板上显示对应内容。平板电脑和电视的屏幕已经大到可以同时容纳这两个面板了,但手机屏幕就需要分别显示。因此,我们可以使用以下文件以便实施这些布局:
res/layout/main.xml,单面板(默认)布局:
<?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" >
<fragment
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.demo.fragment1" />
</LinearLayout>
res/layout-sw600dp/main.xml,双面板布局:
<?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" >
<fragment
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.demo.fragment1" />
<fragment
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.demo.fragment2" />
</LinearLayout>
使用布局别名
当存在横竖屏切换的时候,res/layout/layout_land;res/layout/layout_port
只需要对其中大部分xml文件作出相应修改即可满足于横竖屏的切换布局
5.使用.9png
.9的制作,实际上就是在原图片上添加1px的边界,然后按照我们的需求,把对应的位置设置成黑色线,系统就会根据我们的实际需求进行拉伸。
左上边代表拉伸
右下边代表padding box
先看下面两张图,我们理解一下这四条线的含义。
上图和下图的区别,就在于右下边的黑线不一样,具体的效果的区别,看右边的效果图。上图效果图中深蓝色的区域,代表内容区域,我们可以看到是在正中央的,这是因为我们在右下边的是两个点,这两个点距离上下左右四个方向的距离就是padding的距离,所以深蓝色内容区域在图片正中央,我们再看下图,由于右下边的黑线是图片长度,所以就没有padding,从效果图上的表现就是深蓝色区域和图片一样大,因此,我们可以利用右下边来控制内容与背景图边缘的padding。
说白了就是第一张图有padding,这玩意一画全明白
6.距离用dp,文字用sp,不要用px,但是这个dp并不是绝对的,无需考虑太多,因为我们大部分都是使用match和warp的,在相对距离的情况下再使用dp来进行控制**
7.关于高清设计图尺寸的问题
Google官方给出的高清设计图尺寸有两种方案
第一种是 mdpi放大得到hdpi,xhdpi,xxhdpi,xxxhdpi
第二种是xxxhdpi缩小得到xxhdpi,xhdpi,hdpi,mdpi
这两种方法的区别就是:第一种方法容易出席那像素丢失的问题,推荐使用第二种
8.Image的属性:scaleType
一般这个属性都设置为ScaleType="centerCrop"
能获得最好的适配效果
9.动态设置
在一些情况下,需要动态设置空间大小或者位置,比如popwindow的显示位置和相对偏移量
我们可以动态获取当前屏幕属性设置合适数值
public class ScreenSizeUtil {
public static int getScreenWidth(Activity activity) {
return activity.getWindowManager().getDefaultDisplay().getWidth();
}
public static int getScreenHeight(Activity activity) {
return activity.getWindowManager().getDefaultDisplay().getHeight();
}
}