fred-ye / summary

my blog
43 stars 9 forks source link

[Android]一种Adroid应用程序屏幕适配的思路 #48

Open fred-ye opened 9 years ago

fred-ye commented 9 years ago

一种Adroid应用程序屏幕适配的思路

在Android中做屏幕适配一直都是一个比较麻烦的活。今天总结一下我们的一种屏幕适配的思路。文章的侧重点是如何用同一个Android项目去同时适配手机和平板。

基本的几个概念

1. px

像素--用来计算数码影像的最小单位。我们通常说的Nexus 5 屏幕分辨率是1080*1920,指的便是这款手机的宽是1080px, 高为1920px。注意px均为整数,不存在小数的情况。

2. 英寸

很好理解,通常我们所说的5寸屏,指的便是屏幕的尺寸是5英寸。测量的是屏幕的对角线长度。

3. dpi

dpi是Dots Per Inch的缩写,即每英寸的点数,此处的点指的是像素,它表示的是每英寸所包含的像素个数。比如320X480分辨率的手机,宽2英寸,高3英寸, 每英寸包含的像素点的数量为320/2=160dpi(横向)或480/3=160dpi(纵向),160就是这部手机的dpi,横向和纵向的这个值都是相同的,原因是大部分手机屏幕使用正方形的像素点,dpi用来描述屏幕密度。 也可以通过计算屏幕对角线的分辨率再除以屏幕尺寸这种方式。

4. dp

也称为dip, device independent pixels 独立设备像素。px = dpi / 160 * dp

图片

这一部份不是我想说的重点,简单提一下: 以下内容部份摘自 http://www.stormzhang.com/android/2014/05/16/android-screen-adaptation/ android中的图片资源都是放在drawable目录下,具体有以下这么几个文件夹

注意Android系统会根据屏幕的密度去从对应的文件夹中寻找图片,如果没有寻找到,会再考虑从其它的文件中寻找。

布局

接下来,看一下,如何用同一个Android项目去适配手机和平板。 android 中允许用指定availabe width这种方式(w<N>dp)来布局。指定最小的屏幕的宽度。需要注意一点的是,此处的宽度会随着屏幕的旋转而发生变化。当我们的app中提供了几个这种配置的布局文件夹,Android系统在使用时会选择最接近但不超过屏幕尺寸的那个文件夹中的布局文件。注意,此处对屏幕尺寸的比较是基于dp的。相关内容可以参看(这里)[http://wear.techbrood.com/guide/topics/resources/providing-resources.html] 举两个例子:

  1. 假设我们现在有一个屏幕密度为160dpi的标准屏平板,横放时宽度是1024dp,此时如果我们的layout文件只有layout-w960dp, layout-w1280dp,会发现这个平板会采用layout-w960dp里面的布局。
  2. 如果有一个屏幕密度为320dpi的平板,屏幕的分辨率为1280*720。如果此时布局文件有layout-w960dp, layout-w400dp, layout-nodpi, layout这么四个文件夹。最终在横屏时,它会采用layout-w960dp 因为其横屏时屏幕的宽度为1280/2 = 640dp;在竖屏时, 它会采用layout-nodpi,因为720/2=360,layout-w960dp, layout-w400dp肯定是不会采用了。只会从剩下的layout-nodpi和layout里面选。最终发现,选择的是layout-nodpi里面的布局。

回到刚开始的问题,我们如何用同一个Android项目去适配手机和平板

我们的思路是这样子的:

  1. 对于手机,我们采用一套布局,将其放到layout文件夹中。
  2. 对于平板,根据当前比较火的平板的尺寸,定义了4套布局,分别是layout-w1280dp, layout-w1024dp, layout-w960dp, layout-nodpi。添加一个layout-nodpi 是为了handle可能会匹配不上的情况,即如果有一个平板,假设其width的dp大于1280。此时,如果没有layout-nodpi,程序会一启动就挂。
  3. 针对同一个屏,phone的布局文件名和tablet中的布局文件名会不一样。如针对主屏, MainActivity, phone上的布局文件为activity_main, tablet上的布局文件为activity_main_hd。这样在使用时就不会乱。
  4. 平板上统一强制采用横屏的方式显示。

    测试时会用到的一些代码

1. 获得屏幕的一些基本信息

DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
Log.i("MutiScreen", "width:" + metric.widthPixels + "  height:" + metric.heightPixels
                + "  density:" + metric.density + "   dpi:" + metric.densityDpi);

2. 如何区分平板和手机

public static boolean isTablet(Context context) {
    return (context.getResources().getConfiguration().screenLayout
                & Configuration.SCREENLAYOUT_SIZE_MASK)
                >= Configuration.SCREENLAYOUT_SIZE_LARGE;
}