Android

Android 屏幕适配

2019-08-27  本文已影响0人  西小瓜

1.关于 Android 屏幕适配

1.1 什么是 Android 屏幕适配

使得一些元素在 Android 不同尺寸,不同分辨率的手机上具备相同且合适的显示效果。

1.2 为什么要进行 Android 屏幕适配

2.相关重要概念

2.1 屏幕尺寸

指屏幕的对角线的长度

单位是英寸,1英寸=2.54厘米,常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等

2.2 屏幕分辨率

指在横纵向上的像素点数

单位是px,1px=1个像素点。一般以纵向像素* 横向像素,如1960*1080

2.3 屏幕像素密度

指每英寸上的像素点数

单位是dpi,即“dot per inch”的缩写。屏幕像素密度与屏幕尺寸和屏幕分辨率有关,在单一变化条件下,屏幕尺寸越小、分辨率越高,像素密度越大,反之越小。

2.3 dp,dip,dpi,sp,px

ui设计师给我们的设计图是以px为单位的,Android开发则是使用dp作为单位的,那么我们需要进行转换,在Android中,规定以160dpi为基准,1dip=1px,如果密度是320dpi,则1px=2dp,具体如下表:

密度类型 代表的分辨率(px) 屏幕密度(dpi) 换算(px/dp) 比例
低密度(ldpi) 240x320 120 1px=0.75dp 3
中密度(mdpi) 320x480 160 1px=1dp 4
高密度(hdpi) 480x800 240 1px=1.5dp 6
超高密度(xhdpi) 720x1280 320 1px=2dp 8
超超高密度(xxhdpi) 1080x1920 480 1px=3dp 12
转换过程 转换公式 示例
dp单位转换成px单位 px = dp* (devicePixelRatio)= dp*(density/160) 假如density(像素密度)为320,把360dp转换成px,那么最终像素=360dp*(320/160)=720px
px单位转换成dp单位 dp = px * (devicePixelRatio)=px * (density/160) 假如density(像素密度)为320,把640dp转换成px,那么最终像素=640dp*(320/160)=1280px
2.4 mdpi,hdpi,xdpi,xxdpi

用来修饰Android中的drawable文件夹及values文件夹,以区分不同像素密度下的图片和dimen值。

在进行开发的时候,我们需要把合适大小的图片放在合适的文件夹里面

名称 像素密度范围
mdpi 120dpi~160dpi
hdpi 160dpi~240dpi
xhdpi 240dpi~320dpi
xxhdpi 320dpi~480dpi
xxxhdpi 480dpi~640dpi
名称 图标尺寸
mdpi 48x48px
hdpi 72x72px
xhdpi 96x96px
xxhdpi 144x144px
xxxhdpi 192x192px

3.解决方案:(如何适配)

3.1 支持各种屏幕尺寸
3.1.1 使用 wrap_content,match_parent,weight
3.1.2 使用相对布局,禁用绝对布局(绝对布局适配性差)
3.1.3 使用限定符

通过布局拉伸组件内外的空间以适应各种屏幕,但它们不一定能为每种屏幕都提供最佳的用户体验,应该应针对各种屏幕配置提供一些备用布局,故使用限定符,在运行时根据当前的设备配置自动选择合适的资源了,例如根据各种屏幕尺寸选择不同的布局。

a 使用尺寸限定符
  • 在平板电脑和电视的屏幕(>7英寸)上:实施“双面板”模式以同时显示更多内容
  • 在手机较小的屏幕上:使用单面板分别显示内容

因此,我们可以使用尺寸限定符(layout-large)通过创建一个文件来完成上述设定:

res/layout-large/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>
<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>
  • 两个布局名称均为main.xml,只有布局的目录名不同:第一个布局的目录名为:layout,第二个布局的目录名为:layout-large,包含了尺寸限定符(large)
  • 被定义为大屏的设备(7寸以上的平板)会自动加载包含了large限定符目录的布局,而小屏设备会加载另一个默认的布局
b. 最小宽度(Smallest-width)限定符
  • 背景:上述提到的限定符“large”具体是指多大呢?似乎没有一个定量的指标,这便意味着可能没办法准确地根据当前设备的配置(屏幕尺寸)自动加载合适的布局资源
  • 例子:比如说large同时包含着5寸和7寸,这意味着使用“large”限定符的话我没办法实现为5寸和7寸的平板电脑分别加载不同的布局

最小宽度限定符可让您通过指定某个最小宽度(以 dp 为单位)来定位屏幕。例如,标准 7 英寸平板电脑的最小宽度为 600 dp,因此如果您要在此类屏幕上的用户界面中使用双面板(但在较小的屏幕上只显示列表),您可以使用上文中所述的单面板和双面板这两种布局,但您应使用 sw600dp 指明双面板布局仅适用于最小宽度为 600 dp 的屏幕,而不是使用 large 尺寸限定符。

<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>
<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>

也就是说,对于最小宽度大于等于 600 dp 的设备,系统会选择 layout-sw600dp/main.xml(双面板)布局,否则系统就会选择 layout/main.xml(单面板)布局。

Android 版本低于 3.2 的设备不支持此技术,原因是这些设备无法将 sw600dp 识别为尺寸限定符,因此我们仍需使用 large 限定符

3.1.4 使用布局别名

当你需要同时为Android 3.2版本前和Android 3.2版本后的手机进行屏幕尺寸适配的时候,由于尺寸限定符仅用于Android 3.2版本前,最小宽度限定符仅用于Android 3.2版本后,所以这会带来一个问题,为了很好地进行屏幕尺寸的适配,你需要同时维护layout-sw600dp和layout-large的两套main.xml平板布局,如下:

适配手机的单面板(默认)布局:res/layout/main.xml

适配尺寸>7寸平板的双面板布局(Android 3.2前):res/layout-large/main.xml

适配尺寸>7寸平板的双面板布局(Android 3.2后)res/layout-sw600dp/main.xml

最后的两个文件的xml内容是完全相同的,这会带来:文件名的重复从而带来一些列后期维护的问题

于是为了要解决这种重复问题,我们引入了“布局别名”

还是上面的例子,你可以定义以下布局:

然后加入以下两个文件,以便进行Android 3.2前和Android 3.2后的版本双面板布局适配:

  1. res/values-large/layout.xml(Android 3.2之前的双面板布局)
<resources>
    <item name="main" type="layout">@layout/main_twopanes</item>
</resources>
  1. res/values-sw600dp/layout.xml(Android 3.2及之后的双面板布局)
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
3.1.5 .使用自动拉伸位图

图片资源能够适应各种尺寸

参考链接

上一篇 下一篇

猜你喜欢

热点阅读