多屏幕最佳实践

一、概览

Android支持不同屏幕尺寸和密度,系统会将界面调整为适合的屏幕尺寸,同时也可以针对特定的屏幕进行支持。但是为了有更好的用户体验,开发者应当针对不同尺寸和密度进行优化。

1.相关概念

屏幕尺寸:屏幕对角测量的实际物理尺寸。方便起见,Android将所有屏幕尺寸分为4种通用尺寸:小、正常、大和超大;

屏幕密度:屏幕物理区域中的像素量,通常称为dpi(每英寸点数)。分为6种通用密度:ldpi(低)、mdpi(中)、hdpi(高)、xhdpi(超高)、xxhdpi(超超高)和xxxhdpi(超超超高);

方向:即横屏还是竖屏;

分辨率:屏幕物理像素总数;一般应用不会直接使用分辨率,只关注屏幕尺寸和密度;

密度无关像素(dp):UI布局时推荐使用的虚拟像素单位,用于以密度无关方式布局。dp等于160dpi屏幕上一个物理像素,即以中密度屏幕假设的基线密度。系统会根据使用的屏幕密度来对dp做缩放。dp转px:px = dp * (dpi / 160)。如,240dpi,1dp=1.5px;推荐UI布局时使用dp,确保不同密度的屏幕上正常显示UI。

2.支持的屏幕范围

四种尺寸:小、正常、大和超大;6种通用密度:ldpi(低)~120dpi、mdpi(中)~160dpi、hdpi(高)~240dpi、xhdpi(超高)~320dpi、xxhdpi(超超高)~480dpi和xxxhdpi(超超超高)~640dpi;通用尺寸和密度按照基线配置(正常尺寸和mdpi密度)排列。该基线是第一代Android设备的屏幕配置,采用HVGA屏幕。

设备的实际屏幕尺寸和密度一般都不是按照标准的,都略有差异。为不同的尺寸设计UI时,每种设计都需要最小空间。通用的4中尺寸,分别为:超大屏至少960dp×720dp、大屏至少640dp×480dp、正常屏至少470dp×320dp、小屏至少为426dp×320dp。

针对不同屏幕尺寸和密度优化UI,要为不同尺寸和密度提供备用资源,通常要为不同尺寸提供替代布局,为不同密度提供提供替代位图图像。运行时,系统会自动选择当前尺寸和密度对应的资源。不需要为尺寸和密度的组合提供备用资源,因为定义通用屏幕尺寸和密度的特性相互独立。

3.密度独立性

简单来说,就是在密度不同的屏幕上,用户看同一内容都是一样的大小。否则,UI在低密度上看起来就会比较大,高密度就会很小。系统提供两种方式实现密度独立性:

1)系统根据当前屏幕密度扩展dp单位数,这个不用说了;

2)系统会根据当前屏幕密度将可绘制对象资源扩展到适当大小,这个可以看shape等drawable资源。

二、支持多屏幕

1.总览

1)在清单中声明应用支持哪些屏幕尺寸,<supports-screen>;

2)为不同屏幕尺寸提供不同的布局,系统会默认调整应用布局大小以使用当前屏幕;

3)为不同屏幕密度提供不同的位图可绘制对象,默认情况下,系统会缩放位图(png等)和.9.png对象以适配当前物理尺寸。

正常开发中,我们一般只提供一份资源,如尺寸只提供一份布局,密度只提供xhdpi资源,大部分的适配工作都可以完成。

运行时,系统为了确保最佳的显示效果,会进行如下操作:系统首先选择使用适当的匹配备用资源,如果没有匹配的,会使用默认资源。

2.配置限定符

这点请参考另一篇文章:Android资源分组及匹配详解

3.设计替代布局和可绘制对象

1)替代布局

根据需求创建备用资源。通常,使用尺寸和方向限定符提供替代布局资源,并且使用密度限定符提供替代位图可绘制对象资源。比如小屏幕中按钮排列可能无法完全显示,大屏上可能又会有不足,横屏竖屏时也不一样。因此可能需要针对的替换布局。

2)替代可绘制对象

只需要为位图(png等)以及.9.png文件提供密度特定的可绘制对象。其他的如形状、颜色等其他可绘制对象资源,只需要在drawable中提供一份即可。

要为不同密度创建替代位图可绘制对象,遵循6种通用密度间的缩放比,l:m:h:xh:xxh:xxxh为3:4:6:8:12:16。如,中等密度用100*100的图,则高密度提供150*150的。

三、最佳实践

1.支持不同屏幕尺寸:

1)XML布局中使用wrap_content、match_parent,替代硬编码;

2)多用RelativeLayout,可实现很多复杂布局,以及LinearLayout,用于实现直线排列的布局,不要用绝对布局;

3)使用尺寸限定符,即,res/latyout/main.xml,单窗格布局(默认,手机屏幕),res/layout-large/main.xml,双窗格布局(7英寸以及更大尺寸的平板电脑)。类似于Fragment在手机和平板上的方式。

4)使用最小宽度限定符(Android3.2);典型的7英寸平板电脑最小宽度为600dp,res/layout-sw600dp/main.xml,即最小宽度为600dp的屏幕使用该布局;

5)使用别名,最小宽度限定符仅在3.2以上提供支持,加载布局时,才指定main布局,比如大屏或sw600dp等都使用main_twopanes布局:

res/values-large/layout.xml:// 大屏

<resources>
    <item name="main" type="layout">@layout/main_twopanes</item>
</resources>
res/values-sw600dp/layout.xml:// 最小600dp宽屏幕

<resources>
    <item name="main" type="layout">@layout/main_twopanes</item>
</resources>

6)使用屏幕方向限定符:

布局文件:

res/layout/onepane.xml,
res/layout/onepane_with_bar.xml,
res/layout/twopanes.xml,
res/layout/twopanes_narrow.xml。

限定符:

res/values/layouts.xml:// 普通

<resources>
    <item name="main_layout" type="layout">@layout/onepane_with_bar</item>
    <bool name="has_two_panes">false</bool>
</resources>
res/values-sw600dp-land/layouts.xml:// 最低宽600dp横屏

<resources>
    <item name="main_layout" type="layout">@layout/twopanes</item>
    <bool name="has_two_panes">true</bool>
</resources>
res/values-sw600dp-port/layouts.xml:// 最低宽600dp竖屏

<resources>
    <item name="main_layout" type="layout">@layout/onepane</item>
    <bool name="has_two_panes">false</bool>
</resources>
res/values-large-land/layouts.xml:// 大屏横屏
<resources>
    <item name="main_layout" type="layout">@layout/twopanes</item>
    <bool name="has_two_panes">true</bool>
</resources>
res/values-large-port/layouts.xml:// 大屏竖屏
<resources>
    <item name="main_layout" type="layout">@layout/twopanes_narrow</item>
    <bool name="has_two_panes">true</bool>
</resources>
7)使用.9.png;

2.支持不同密度

1)使用密度无关像素,dp,sp,不要用px;

2)提供备用位图:xhdpi(2.0),hdpi(1.5),mdpi(1.0,基准),例:xhdpi中文件为200*200,则hdpi为150*150,mdpi为100*100,ldpi为75*75;启动图标要放在res/mipmaps-[density]/文件夹而非drawable/文件夹内,以确保启动图标使用最佳分辨率。

3.自适应UI流

1)确定当前布局;

2)findViewById之后(对于多布局适配)判断View是否存在,存在则可操作,不存在则忽略;

3)根据当前布局做出反应。例如,在手机上,点击item则打开新Activity,而平板上,则在右侧打开详细,一般是使用fragment;

4)复用fragment;

5)处理屏幕配置变更。

四、其他注意事项

1.资源预缩放

根据当前密度系统会使用应用提供的任何尺寸和密度的资源,且不加缩放。如果没有匹配的资源,会选择默认资源,并按需向上或向下扩展。默认资源系统会假设其针对mdpi设计。系统会缩放位图使满足当前屏幕密度。如,mdpi中50*50位图会扩展至75*75在hdpi中。如果不希望预缩放,则将资源放在nodpi限定符的目录中,此文件夹中文件使用时不会根据当前密度缩放。

2.像素尺寸和坐标的自动缩放

应用可在清单中设置android:anyDensity=false或inScaled设为false对bitmap编程来停用预缩放。此时系统在绘制时会自动缩放任何绝对的像素坐标和像素尺寸。缩放的目的是确保像素定义的屏幕元素仍然以其在mdpi下大致的物理尺寸显示。但通常不应停用缩放。

3.缩放运行时创建的位图对象

要控制是否缩放运行时创建的Bitmap使用setDensity()指定位图密度,从DisplayMetrics传递密度常量,如DESITY_HIGH或DENSITY_LOW。

使用BitmapFactory创建Bitmap,使用BitmapFactory.options定义位图属性,确定系统是否要缩放或者如何缩放。

4.dp转换为px

// dp
private static final float GESTURE_THRESHOLD_DP = 16.0f;

// 获取屏幕 density 缩放系数
final float scale = getResources().getDisplayMetrics().density;
// 将dp转换成px
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);

// Use mGestureThreshold as a distance in pixels...

Display.density是根据当前密度将dp转换为px的缩放系数,mdpi上为1.0,hdpi为1.5依次类推。dp*缩放系数就是px,最后加上0.5,将数字四舍五入到最接近的整数。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值