Adnroid应用屏幕适配

问题

Android 设备各种屏幕尺寸和形状,如何做好适配?

你还在为开发中频繁切换环境打包而烦恼吗?快来试试 Environment Switcher 吧!使用它可以在app运行时一键切换环境,而且还支持其他贴心小功能,有了它妈妈再也不用担心频繁环境切换了。https://github.com/CodeXiaoMai/EnvironmentSwitcher

解决思路和办法

  • Android 系统定义了两种常规属性对设备屏幕进行分类:大小和密度。
  • 为了优化应用程序的外观,以适应不同的屏幕尺寸和密度,可以添加一些替代资源(布局和图片)。

因此对不同屏幕尺寸、形状以及密度的适配,其实就是对布局和图片的适配。

布局适配

要优化不同屏幕尺寸的用户体验,应该为要支持的每个屏幕尺寸创建一个独特的布局XML文件。每个布局应该保存到相应的资源目录中,命名为 - <screen_size>后缀。

Android 3.2 之前和之后的方案是不一样的。

Android 3.2 -

系统定义了四种常用大小:small, normal, large, xlarge

和四种常用密度:low (ldpi), medium (mdpi 默认), high (hdpi), extra high (xhdpi)

就像适配不同的语言一样,要声明用于不同屏幕的布局和位图,必须将这些替代资源放在不同的目录中。

还要注意,屏幕方向(横向或纵向)也被认为是屏幕尺寸的变化,所以许多应用程序应该修改布局,以优化每个方向的用户体验。

例如,大型屏幕的独特布局应该保存在 res/layout-large/ 下。

Android会自动缩放布局,以适应屏幕。因此,不同屏幕尺寸的布局不需要担心UI元素的绝对大小,而需要重点关注的是影响用户体验的布局结构(例如相对于兄弟视图的重要视图的大小或位置)。

例如,在项目中创建 默认布局支持大屏幕 的替代布局。

MyProject/
    res/
        layout/
            main.xml
        layout-large/
            main.xml

如上面代码所示,文件名必须完全相同,但内容不同,才能为相应的屏幕尺寸提供优化的UI。

系统会根据运行应用程序的设备的屏幕大小从相应的布局目录加载布局文件。有关Android选择适当资源的更多信息,请参阅“提供资源”指南。

如果应用支持横竖屏切换,还应提供横屏的布局,这里是一个具有用于横向定向的替代布局的项目

MyProject/
    res/
        layout/
            main.xml
        layout-land/
            main.xml

默认情况下,layout/main.xml 文件用于纵向。

如果你想提供一个支持 大屏幕横屏 的特殊布局,你需要同时使用 largeland 限定词:

MyProject/
    res/
        layout/              # default (portrait)
            main.xml
        layout-land/         # landscape
            main.xml
        layout-large/        # large (portrait)
            main.xml
        layout-large-land/   # large landscape
            main.xml

Android 3.2 +

在Android 3.2 之前,其中一个困难是“庞大”的屏幕尺寸容器,其中囊括了 Dell Streak、原版 Galaxy Tab 以及常规 7 英寸平板电脑。 不过,尽管这些设备都被视为“大”屏设备,许多应用可能仍需要为此类别中的不同设备(如为 5 英寸和 7 英寸设备)显示不同的布局。 正因如此,Android 在 Android 3.2 中引入了“最小宽度”限定符。

最小宽度 限定符允许您将目标锁定在具有特定最小宽度(单位:dp)的屏幕。 例如,典型的 7 英寸平板电脑最小宽度为 600dp,因此,如果您希望您的 UI 在这些屏幕上显示两个窗格(但在较小屏幕上显示单个列表),您同样可以为单窗格布局和双窗格布局使用两种布局,但不使用 large 尺寸限定符,而是使用 sw600dp 为最小宽度是 600dp 的屏幕指定双窗格布局:

  • res/layout/main.xml,单窗格(默认)布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="match_parent" />
</LinearLayout>
  • res/layout-sw600dp/main.xml,双窗格布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">
    <fragment android:id="@+id/headlines"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.HeadlinesFragment"
              android:layout_width="400dp"
              android:layout_marginRight="10dp"/>
    <fragment android:id="@+id/article"
              android:layout_height="fill_parent"
              android:name="com.example.android.newsreader.ArticleFragment"
              android:layout_width="fill_parent" />
</LinearLayout>

这意味着,最小宽度大于或等于 600dp 的设备将选择 layout-sw600dp/main.xml(双窗格)布局,而屏幕较小的设备将选择 layout/main.xml(单窗格)布局。

不过,这种方法在低于 3.2 版本的设备上不太奏效,因为它们无法将 sw600dp 识别为尺寸限定符,所以您仍需使用 large 限定符。因此,您应该建立一个与 res/layout-sw600dp/main.xml 完全相同的、名为 res/layout-large/main.xml 的文件。下文介绍的技巧可让您避免因此而产生重复的布局文件。

使用布局别名

如果您的应用的 minSdkVersion 大于等于 3.2,可以跳过此部分。

最小宽度限定符仅在 Android 3.2 及更高版本上提供。因此,您仍应使用兼容早期版本的抽象尺寸容器(小、正常、大和超大)。 例如,如果您想让自己设计的 UI 在手机上显示单窗格 UI,但在 7 英寸平板电脑、TV 及其他大屏设备上显示多窗格 UI,则需要提供下列文件:

  • res/layout/main.xml: 单窗格布局
  • res/layout-large: 多窗格布局
  • res/layout-sw600dp: 多窗格布局

后两个文件虽然名字不同,但内容完全相同,因为其中一个将由 Android 3.2 + 设备匹配,另一个是为了照顾使用早期版本 Android 的平板电脑和 TV 的需要。

为避免为平板电脑和 TV 产生相同的重复文件(以及由此带来的维护难题),您可以使用别名文件。 例如,您可以定义下列布局:

  • res/layout/main.xml,单窗格布局
  • res/layout/main_twopanes.xml,双窗格布局

并添加以下两个文件:

  • res/values-large/layout.xml:
<resources>
    <item name="main" type="layout">@layout/main_twopanes</item>
</resources>
  • res/values-sw600dp/layout.xml:
<resources>
    <item name="main" type="layout">@layout/main_twopanes</item>
</resources>

后两个文件内容完全相同,但它们实际上并未定义布局, 而只是将 main 设置为 main_twopanes 的别名。由于这些文件具有 large 和 sw600dp 选择器,因此它们适用于任何 Android 版本的平板电脑和电视(低于 3.2 版本的平板电脑和电视匹配 large,高于 3.2 版本者将匹配 sw600dp)。

创建不同的位图

我们应该始终提供适当缩放到每个通用密度设备的位图资源:低,中,高和超高密度。这有助于App在所有屏幕密度上实现良好的图形质量和性能。

要生成这些图像,应该以矢量格式从原始资源开始,并使用以下尺寸比例为每个密度生成图片:

  • xhdpi: 2.0
  • hdpi: 1.5
  • mdpi: 1.0 (baseline)
  • ldpi: 0.75

例如:如果为xhdpi设备生成200x200图片,则应为hdpi生成150x150,mdpi为100x100,ldpi 为75x75的的相同资源。

然后,将文件放在适当的drawable资源目录中:

MyProject/
    res/
        drawable-xhdpi/
            awesomeimage.png
        drawable-hdpi/
            awesomeimage.png
        drawable-mdpi/
            awesomeimage.png
        drawable-ldpi/
            awesomeimage.png

当在代码中引用@drawable/awesomeimage时,系统会根据当前设备的屏幕密度选择适当的位图。

低密度(ldpi)资源并不总是必需的。如果提供了hdpi资源时,系统将其缩小一半以适应ldpi屏幕。

使用九宫格位图

支持不同屏幕尺寸通常意味着您的图像资源也必须能够适应不同的尺寸。 例如,按钮背景必须能够适应其所应用到的任何一种按钮形状。

如果您在可能改变尺寸的组件上使用简单图像,您很快会发现效果有些差强人意,因为运行组件会均匀地拉伸或缩小您的图像。 解决方案是使用九宫格位图,这种特殊格式的 PNG 文件会指示哪些区域可以拉伸,哪些区域不可以拉伸。

因此,在设计将用于尺寸可变组件的位图时,请一律使用九宫格位图。

参考文章

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容