当前位置: 代码迷 >> Android >> Android屏幕适配小结
  详细解决方案

Android屏幕适配小结

热度:79   发布时间:2016-04-28 01:22:20.0
Android屏幕适配总结
在开发过程中其实我们已经接触到了屏幕适配方面的相关知识,慢慢的总结归纳,剖析其原理。
使用相对布局
LinearLayout却不允许你精准的控制它子view的关系,子view在LinearLayout中只能简单一个接一个的排成行。如果你需要你的子view不只是简简单单的排成行的排列,更好的方法是使用RelativeLayout,它允许你指定你布局中控件与控件之间的关系。

尽量使用match_parent 而不是fill_parent 。
能够使用权重的地方尽量使用权重(android:layout_weight)
如果是纯色背景,尽量使用android的shape 自定义。

多个图片资源与Layout布局
 需要根据dpi值准备图片资源:
drawable
主要放置xml配置文件或者对分辨率要求较低的图片
drawalbe-ldpi
低分辨率的图片,如QVGA (240x320)
drawable-mdpi
中等分辨率的图片,如HVGA (320x480)
drawable-hdpi
高分辨率的图片,如WVGA (480x800),FWVGA (480x854)
drawable-xhdpi
至少960dp x 720dp
根据物理尺寸的大小准备布局:
layout
放一些通用布局xml文件,比如界面顶部和底部的布局,不会随着屏幕大小变化,类似windos窗口的title bar
layout-small
屏幕尺寸小于3英寸左右的布局
layout-normal
屏幕尺寸小于4.5英寸左右
layout-large
4英寸-7英寸之间
layout-xlarge
7-10英寸之间
注意:使用多个布局来适配,配置文件一定要加上这段配置代码,不然有时可能会出问题
    <supports-screens android:largeScreens="true"
                android:normalScreens="true" android:anyDensity="true" />

Android有个自动匹配机制去选择对应的布局和图片资源。 系统会根据机器的分辨率来分别到这几个文件夹里面去找对应的图片或者layout。 在开发程序时为了兼容不同平台不同屏幕,建议各自文件夹根据需求均存放不同版本图片与layout。


代码中设置控件的尺寸    
 DisplayMetrics displayMetrics = new DisplayMetrics();
 getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
  int screenWidth= displayMetrics.widthPixels;
 int screenHeight= displayMetrics.heightPixels;
screenWidth和screenHeight就是屏幕的宽高。设置控件的宽高时,既可以使用setWidth(int),setHeight(int)也可以使用setLayoutParams(new LayoutParams( int width,int height));来实现。不过好像有的控件不支持setWidth直接设置,而使用LayoutParams设置的话,所有控件都可以。


使用密度独立像素(dp)
不同的屏幕有不同的像素密度,所以,同样单位的像素在不同的设备上会有不同的物理尺寸。因此,在指定单位的时候,通常使用dp或者sp。一个dp代表一个密度独立像素,也就相当于在每英寸160点的屏幕上,1dp = 1px。
sp也是一个基本的单位,不过它主要是用在文本尺寸上(它也是一种尺寸规格独立的像素),所以,你在定义文本尺寸的时候应该使用这种规格单位(不要使用在布尺寸上)。

为了提供更好的用户体验,你应该使用以下几种规格为不同的屏幕密度提供位图资源:
xhdpi:2.0
hdpi:1.5
mdpi:1.0(标准线)
ldpi:0.75
这也就意味着如果在xhdpi设备上你需要一个200x200的图片,那么你则需要一张150x150的图片用于hdpi,100x100的用于mdpi以及75x75的用户ldpi设备。


使用据尺寸限定词
布局文件放在加上类似large,sw600dp等这样限定词的文件夹中,以此来告诉系统根据屏幕选择对应的布局文件。但是比较麻烦,一般用的比较少。



使用点9图片
支持不同的屏幕尺寸同时也意味着你的图片资源也必须能兼容不同的屏幕尺寸。
比如,一个button的背景图片就必须要适应该button的各种形状。
如果你在使用组件时可以改变图像的大小,你很快就会发现这是一个不明确的选择,因为运行的时候,图片会被拉伸或者压缩(这样容易造成图像失真)。避免这种情况的解决方案就是使用点9图片。



确定当前布局模式
当你在实现不同布局的时候,首先,你应该确定用户在当前的情况下看到的view应该是个什么样子。
比如,你可能想知道当前用户到底是处于“单个方框”的模式还是“多个方框”的模式。
这个时候,你就可以通过查询指定的view是不是存在并是否显示来判断当前的模式:
View view = findViewById(R.id.article);
               boolean mIsDualPane = view != null &&  
                                                               view.getVisibility() == View.VISIBLE; 
另一个关于如何适配已经存在的不同组件的例子是在组件执行操作之前先检查它是否是可用的。

根据当前布局模式响应
根据当前不同的布局有一些操作肯定会带来不一样的结果。

在其他Activity中复用Fragment
设计为多屏幕适配的UI时有一个复用的原则:
 将你的界面变为单独部分,这样它能在某些屏幕配置上被实现为一个方框,而在其他屏幕配置中,则被实现为一个单独的activity。
当你在设计fragment的时候,有一个非常重要的知识点: 
不要为某个特定的activity设计耦合度高的fragment。通常的做法是,通过定义抽象接口,并在接口中定义需要与该fragment进行交互的activity的抽象方法, 然后与该fragment进行交互的activity实现这些抽象接口方法的具体方法。 
 在Fragment中定义需要与Activity交互的接口,让Activity去实现它。

处理屏幕配置变化
如果使用的是单独的activity来实现你界面的不同部分,你需要注意的是,屏幕变化(如旋转变化)的时候,你也应该根据屏幕配置的变化来改变你UI的变化。。
这也就意味着,当用户在竖屏模式下观看文章的时候,你需要检测屏幕是否被改变为了横屏,如果改变了,则结束当前activity并返回到主activity中,这样,UI就能显示为两个方框的模式了。

使用最小宽度限定词
老版Galaxy Tab和一般的7寸平板,有很多的应用都想针对这些不同的设备(比如5寸和7寸的设备)定义不同的布局,但是这些设备都被定义为了large尺寸屏幕。正是因为这个,所以Android在3.2的时候开始使用最小宽度限定词。最小宽度限定词允许你根据设备的最小宽度(dp单位)来指定不同布局。

这样意味着当你的设备的最小宽度等于600dp或者更大时,系统选择
layout-sw600dp/main.xml(two_panes)的布局,而小一点的屏幕则会选择      layout/main.xml(single_panes)的布局。 然而,在3.2之前还没有将sw600dp作为一个限定词出现,所以,你还是需要使用large限定词来做。 因此,你还是应该要有一个布局文件名为
res/layout-large/main.xml,和res/layout-sw600dp/main.xml一样。

如何避免像这样出现重复的布局文件?
解决方案一
layout-sw600dp和layout-xlarge同时存在,建立不同的values文件夹的layout.xml
比如有一个布局要兼容大小屏幕,在Activity中引入的布局名字为activity_my_schedule:
在 res文件夹下创建不同的 values文件夹,来指向同一布局文件
res/values/layout.xml
<resources>
    <item name="activity_my_schedule" type="layout">
                                                      @layout/activity_my_schedule_wide
    </item>
</resources>
res/values-sw600dp\layout.xml
<resources>
    <item name="activity_my_schedule" type="layout">
                                                          @layout/activity_my_schedule_wide
   </item>
</resources>

解决方案二
你可以只使用一个layout布局文件,在 res文件夹下创建不同的 values文件夹,来指向不同的局文件。
我们来看Google开源项目Iosched中的实际应用,在layout下面有两个布局文件,分别用于适配大小屏幕:
res/layout/activity_my_schedule_wide
res/layout/activity_my_schedule_narrow
创建不同的values文件夹的layout,layout用于小屏幕,values-sw600dp-land用于横屏的情况:
res/values/layout.xml
<resources>
    <item name="activity_my_schedule" type="layout">
                                          @layout/activity_my_schedule_narrow</item>
</resources>
res/values-sw600dp-land\layout.xml
<resources>
    <item name="activity_my_schedule" type="layout">
                          @layout/activity_my_schedule_wide</item>
</resources>
更复杂的需求,不同的情况选择不同的布局,只需要在res下面建立不同的values的layout,引用指定的布局名称即可,常见的values类型有:
res/values/layouts.xml:
res/values-sw600dp-land/layouts.xml:
res/values-sw600dp-port/layouts.xml:
res/values-xlarge-land/layouts.xml:
res/values-xlarge-port/layouts.xml:
  相关解决方案