美文网首页android开发杂识编程AndroidWorld
Android 屏幕适配:最全面的解决方案

Android 屏幕适配:最全面的解决方案

作者: Carson带你学安卓 | 来源:发表于2016-04-14 07:03 被阅读129891次

    前言

    Android的屏幕适配一直以来都在折磨着我们Android开发者,本文将结合:

    给你带来一种全新、全面而逻辑清晰的Android屏幕适配思路,只要你认真阅读,保证你能解决Android的屏幕适配问题!


    目录

    Android屏幕适配解决方案.png

    定义

    使得某一元素在Android不同尺寸、不同分辨率的手机上具备相同的显示效果


    相关重要概念

    屏幕尺寸

    • 含义:手机对角线的物理尺寸
    • 单位:英寸(inch),1英寸=2.54cm

    Android手机常见的尺寸有5寸、5.5寸、6寸等等

    屏幕分辨率

    • 含义:手机在横向、纵向上的像素点数总和
    1. 一般描述成屏幕的"宽x高”=AxB
    2. 含义:屏幕在横向方向(宽度)上有A个像素点,在纵向方向
      (高)有B个像素点
    3. 例子:1080x1920,即宽度方向上有1080个像素点,在高度方向上有1920个像素点
    • 单位:px(pixel),1px=1像素点

    UI设计师的设计图会以px作为统一的计量单位

    • Android手机常见的分辨率:320x480、480x800、720x1280、1080x1920

    屏幕像素密度

    • 含义:每英寸的像素点数
    • 单位:dpi(dots per ich)

    假设设备内每英寸有160个像素,那么该设备的屏幕像素密度=160dpi

    • 安卓手机对于每类手机屏幕大小都有一个相应的屏幕像素密度:

    | 密度类型 | 代表的分辨率(px) | 屏幕像素密度(dpi)|
    | ------------- |:-------------:|
    | 低密度(ldpi) | 240x320 | 120 |
    | 中密度(mdpi) | 320x480 | 160 |
    | 高密度(hdpi) | 480x800 | 240|
    | 超高密度(xhdpi) | 720x1280 | 320|
    | 超超高密度(xxhdpi) | 1080x1920 | 480 |

    屏幕尺寸、分辨率、像素密度三者关系

    一部手机的分辨率是宽x高,屏幕大小是以寸为单位,那么三者的关系是:

    三者关系示意图

    数学不太差的人应该能懂.....吧?

    不懂没关系,在这里举个例子
    假设一部手机的分辨率是1080x1920(px),屏幕大小是5寸,问密度是多少?
    解:请直接套公式

    解答过程

    密度无关像素

    • 含义:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关。
    • 单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果
    1. Android开发时用dp而不是px单位设置图片大小,是Android特有的单位
    2. 场景:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。
    • dp与px的转换
      因为ui设计师给你的设计图是以px为单位的,Android开发则是使用dp作为单位的,那么我们需要进行转换:

    | 密度类型 | 代表的分辨率(px) | 屏幕密度(dpi)|换算(px/dp) |比例|
    | ------------- |:-------------:| -------------:| -------------:|
    | 低密度(ldpi) | 240x320 | 120 |1dp=0.75px|3|
    | 中密度(mdpi) | 320x480 | 160 |1dp=1px|4|
    | 高密度(hdpi) | 480x800 | 240|1dp=1.5px|6|
    | 超高密度(xhdpi) | 720x1280 | 320|1dp=2px|8|
    | 超超高密度(xxhdpi) | 1080x1920 | 480 |1dp=3px|12|

    在Android中,规定以160dpi(即屏幕分辨率为320x480)为基准:1dp=1px

    独立比例像素

    • 含义:scale-independent pixel,叫sp或sip
    • 单位:sp
    1. Android开发时用此单位设置文字大小,可根据字体大小首选项进行缩放
    2. 推荐使用12sp、14sp、18sp、22sp作为字体设置的大小,不推荐使用奇数和小数,容易造成精度的丢失问题;小于12sp的字体会太小导致用户看不清

    请把上面的概念记住,因为下面讲解都会用到!


    为什么要进行Android屏幕适配

    由于Android系统的开放性,任何用户、开发者、OEM厂商、运营商都可以对Android进行定制,于是导致:

    • Android系统碎片化:小米定制的MIUI、魅族定制的flyme、华为定制的EMUI等等

    当然都是基于Google原生系统定制的

    • Android机型屏幕尺寸碎片化:5寸、5.5寸、6寸等等
    • Android屏幕分辨率碎片化:320x480、480x800、720x1280、1080x1920

    据友盟指数显示,统计至2015年12月,支持Android的设备共有27796种

    当Android系统、屏幕尺寸、屏幕密度出现碎片化的时候,就很容易出现同一元素在不同手机上显示不同的问题。

    试想一下这么一个场景:
    为4.3寸屏幕准备的UI设计图,运行在5.0寸的屏幕上,很可能在右侧和下侧存在大量的空白;而5.0寸的UI设计图运行到4.3寸的设备上,很可能显示不下。

    为了保证用户获得一致的用户体验效果:

    使得某一元素在Android不同尺寸、不同分辨率的手机上具备相同的显示效果

    于是,我们便需要对Android屏幕进行适配。


    屏幕适配问题的本质

    • 使得“布局”、“布局组件”、“图片资源”、“用户界面流程”匹配不同的屏幕尺寸

    使得布局、布局组件自适应屏幕尺寸;
    根据屏幕的配置来加载相应的UI布局、用户界面流程

    • 使得“图片资源”匹配不同的屏幕密度

    解决方案

    • 问题:如何进行屏幕尺寸匹配?
    • 答:
    屏幕尺寸适配解决方案.png

    “布局”匹配

    本质1:使得布局元素自适应屏幕尺寸

    • 做法
      使用相对布局(RelativeLayout),禁用绝对布局(AbsoluteLayout)

    开发中,我们使用的布局一般有:

    • 线性布局(Linearlayout)
    • 相对布局(RelativeLayout)
    • 帧布局(FrameLayout)
    • 绝对布局(AbsoluteLayout)

    由于绝对布局(AbsoluteLayout)适配性极差,所以极少使用。

    对于线性布局(Linearlayout)、相对布局(RelativeLayout)和帧布局(FrameLayout)需要根据需求进行选择,但要记住:

    • RelativeLayout
      布局的子控件之间使用相对位置的方式排列,因为RelativeLayout讲究的是相对位置,即使屏幕的大小改变,视图之前的相对位置都不会变化,与屏幕大小无关,灵活性很强
    • LinearLayout
      通过多层嵌套LinearLayout和组合使
      用"wrap_content"和"match_parent"已经可以构建出足够复杂的布局。但是LinearLayout无法准确地控制子视图之间的位置关系,只能简单的一个挨着一个地排列

    所以,对于屏幕适配来说,使用相对布局(RelativeLayout)将会是更好的解决方案

    本质2:根据屏幕的配置来加载相应的UI布局

    应用场景:需要为不同屏幕尺寸的设备设计不同的布局

    • 做法:使用限定符
    • 作用:通过配置限定符使得程序在运行时根据当前设备的配置(屏幕尺寸)自动加载合适的布局资源
    • 限定符类型:
    • 尺寸(size)限定符
    • 最小宽度(Smallest-width)限定符
    • 布局别名
    • 屏幕方向(Orientation)限定符

    尺寸(size)限定符

    • 使用场景:当一款应用显示的内容较多,希望进行以下设置:
    • 在平板电脑和电视的屏幕(>7英寸)上:实施“双面板”模式以同时显示更多内容
    • 在手机较小的屏幕上:使用单面板分别显示内容

    因此,我们可以使用尺寸限定符(layout-large)通过创建一个文件

    res/layout-large/main.xml
    

    来完成上述设定:

    • 让系统在屏幕尺寸>7英寸时采用适配平板的双面板布局
    • 反之(默认情况下)采用适配手机的单面板布局

    文件配置如下:

    • 适配手机的单面板(默认)布局: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>
    
    • 适配尺寸>7寸平板的双面板布局::res/layout-large/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>
    

    请注意:

    • 两个布局名称均为main.xml,只有布局的目录名不同:第一个布局的目录名为:layout,第二个布局的目录名为:layout-large,包含了尺寸限定符(large)
    • 被定义为大屏的设备(7寸以上的平板)会自动加载包含了large限定符目录的布局,而小屏设备会加载另一个默认的布局

    但要注意的是,这种方式只适合Android 3.2版本之前。

    最小宽度(Smallest-width)限定符

    • 背景:上述提到的限定符“large”具体是指多大呢?似乎没有一个定量的指标,这便意味着可能没办法准确地根据当前设备的配置(屏幕尺寸)自动加载合适的布局资源
    • 例子:比如说large同时包含着5寸和7寸,这意味着使用“large”限定符的话我没办法实现为5寸和7寸的平板电脑分别加载不同的布局

    于是,在Android 3.2及之后版本,引入了最小宽度(Smallest-width)限定符

    定义:通过指定某个最小宽度(以 dp 为单位)来精确定位屏幕从而加载不同的UI资源

    • 使用场景

    你需要为标准 7 英寸平板电脑匹配双面板布局(其最小宽度为 600 dp),在手机(较小的屏幕上)匹配单面板布局

    解决方案:您可以使用上文中所述的单面板和双面板这两种布局,但您应使用 sw600dp 指明双面板布局仅适用于最小宽度为 600 dp 的屏幕,而不是使用 large 尺寸限定符。

    • sw xxxdp,即small width的缩写,其不区分方向,即无论是宽度还是高度,只要大于 xxxdp,就采用次此布局
    • 例子:使用了layout-sw 600dp的最小宽度限定符,即无论是宽度还是高度,只要大于600dp,就采用layout-sw 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>
    
    • 适配尺寸>7寸平板的双面板布局: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>
    
    • 对于最小宽度≥ 600 dp 的设备
      系统会自动加载 layout-sw600dp/main.xml(双面板)布局,否则系统就会选择 layout/main.xml(单面板)布局
      (这个选择过程是Android系统自动选择的)

    使用布局别名

    设想这么一个场景

    当你需要同时为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内容是完全相同的,这会带来:文件名的重复从而带来一些列后期维护的问题

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

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

    • 适配手机的单面板(默认)布局:res/layout/main.xml
    • 适配尺寸>7寸平板的双面板布局:res/layout/main_twopanes.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>
    

    注:

    • 最后两个文件有着相同的内容,但是它们并没有真正去定义布局,它们仅仅只是将main设置成了@layout/main_twopanes的别名
    • 由于这些文件包含 large 和 sw600dp 选择器,因此,系统会将此文件匹配到不同版本的>7寸平板上:
      a. 版本低于 3.2 的平板会匹配 large的文件
      b. 版本高于 3.2 的平板会匹配 sw600dp的文件

    这样两个layout.xml都只是引用了@layout/main_twopanes,就避免了重复定义布局文件的情况

    屏幕方向(Orientation)限定符

    • 使用场景:根据屏幕方向进行布局的调整

    取以下为例子:

    • 小屏幕, 竖屏: 单面板
    • 小屏幕, 横屏: 单面板
    • 7 英寸平板电脑,纵向:单面板,带操作栏
    • 7 英寸平板电脑,横向:双面板,宽,带操作栏
    • 10 英寸平板电脑,纵向:双面板,窄,带操作栏
    • 10 英寸平板电脑,横向:双面板,宽,带操作栏
    • 电视,横向:双面板,宽,带操作栏

    方法是:

    • 先定义类别:单/双面板、是否带操作栏、宽/窄

    定义在 res/layout/ 目录下的某个 XML 文件中

    • 再进行相应的匹配:屏幕尺寸(小屏、7寸、10寸)、方向(横、纵)

    使用布局别名进行匹配

    1. 在 res/layout/ 目录下的某个 XML 文件中定义所需要的布局类别
      (单/双面板、是否带操作栏、宽/窄)
      res/layout/onepane.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/onepane_with_bar.xml:(单面板带操作栏)

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
        android:orientation="vertical"  
        android:layout_width="match_parent"  
        android:layout_height="match_parent">  
        <LinearLayout android:layout_width="match_parent"   
                      android:id="@+id/linearLayout1"    
                      android:gravity="center"  
                      android:layout_height="50dp">  
            <ImageView android:id="@+id/imageView1"   
                       android:layout_height="wrap_content"  
                       android:layout_width="wrap_content"  
                       android:src="@drawable/logo"  
                       android:paddingRight="30dp"  
                       android:layout_gravity="left"  
                       android:layout_weight="0" />  
            <View android:layout_height="wrap_content"   
                  android:id="@+id/view1"  
                  android:layout_width="wrap_content"  
                  android:layout_weight="1" />  
            <Button android:id="@+id/categorybutton"  
                    android:background="@drawable/button_bg"  
                    android:layout_height="match_parent"  
                    android:layout_weight="0"  
                    android:layout_width="120dp"  
                    style="@style/CategoryButtonStyle"/>  
        </LinearLayout>  
      
        <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/twopanes.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>
    

    res/layout/twopanes_narrow.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="200dp"
                  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>
    

    2.使用布局别名进行相应的匹配
    (屏幕尺寸(小屏、7寸、10寸)、方向(横、纵))
    res/values/layouts.xml:(默认布局)

    <resources>  
        <item name="main_layout" type="layout">@layout/onepane_with_bar</item>  
        <bool name="has_two_panes">false</bool>  
    </resources> 
    

    可为resources设置bool,通过获取其值来动态判断目前已处在哪个适配布局

    res/values-sw600dp-land/layouts.xml
    (大屏、横向、双面板、宽-Andorid 3.2版本后)

    <resources>
        <item name="main_layout" type="layout">@layout/twopanes</item>
        <bool name="has_two_panes">true</bool>
    </resources>
    

    res/values-sw600dp-port/layouts.xml
    (大屏、纵向、单面板带操作栏-Andorid 3.2版本后)

    <resources>
        <item name="main_layout" type="layout">@layout/onepane</item>
        <bool name="has_two_panes">false</bool>
    </resources>
    

    res/values-large-land/layouts.xml
    (大屏、横向、双面板、宽-Andorid 3.2版本前)

    <resources>
        <item name="main_layout" type="layout">@layout/twopanes</item>
        <bool name="has_two_panes">true</bool>
    </resources>
    

    res/values-large-port/layouts.xml
    (大屏、纵向、单面板带操作栏-Andorid 3.2版本前)

    <resources>
        <item name="main_layout" type="layout">@layout/onepane</item>
        <bool name="has_two_panes">false</bool>
    </resources>
    

    这里没有完全把全部尺寸匹配类型的代码贴出来,大家可以自己去尝试把其补充完整


    “布局组件”匹配

    本质:使得布局组件自适应屏幕尺寸

    • 做法
      使用"wrap_content"、"match_parent"和"weight“来控制视图组件的宽度和高度
    • "wrap_content"
      相应视图的宽和高就会被设定成所需的最小尺寸以适应视图中的内容
    • "match_parent"(在Android API 8之前叫作"fill_parent")
      视图的宽和高延伸至充满整个父布局
    • "weight"
      1.定义:是线性布局(Linelayout)的一个独特比例分配属性
      2.作用:使用此属性设置权重,然后按照比例对界面进行空间的分配,公式计算是:控件宽度=控件设置宽度+剩余空间所占百分比宽幅
      具体可以参考这篇文章,讲解得非常详细

    通过使用"wrap_content"、"match_parent"和"weight"来替代硬编码的方式定义视图大小&位置,你的视图要么仅仅使用了需要的那边一点空间,要么就会充满所有可用的空间,即按需占据空间大小,能让你的布局元素充分适应你的屏幕尺寸


    “图片资源”匹配

    本质:使得图片资源在不同屏幕密度上显示相同的像素效果

    • 做法:使用自动拉伸位图:Nine-Patch的图片类型
      假设需要匹配不同屏幕大小,你的图片资源也必须自动适应各种屏幕尺寸

    使用场景:一个按钮的背景图片必须能够随着按钮大小的改变而改变。
    使用普通的图片将无法实现上述功能,因为运行时会均匀地拉伸或压缩你的图片

    • 解决方案:使用自动拉伸位图(nine-patch图片),后缀名是.9.png,它是一种被特殊处理过的PNG图片,设计时可以指定图片的拉伸区域和非拉伸区域;使用时,系统就会根据控件的大小自动地拉伸你想要拉伸的部分

    1.必须要使用.9.png后缀名,因为系统就是根据这个来区别nine-patch图片和普通的PNG图片的;

    2.当你需要在一个控件中使用nine-patch图片时,如

    ```系统就会根据控件的大小自动地拉伸你想要拉伸的部分
    ***
    ###”用户界面流程“匹配
    >- 使用场景:我们会根据设备特点显示恰当的布局,但是这样做,会使得用户界面流程可能会有所不同。
    >- 例如,如果应用处于双面板模式下,点击左侧面板上的项即可直接在右侧面板上显示相关内容;而如果该应用处于单面板模式下,点击相关的内容应该跳转到另外一个Activity进行后续的处理。
    
    **本质:根据屏幕的配置来加载相应的用户界面流程**
    - 做法
    进行用户界面流程的自适应配置:
    
    
    1. 确定当前布局
    2. 根据当前布局做出响应
    3. 重复使用其他活动中的片段
    4. 处理屏幕配置变化
    
    
    
    
    
    
    - 步骤1:确定当前布局
    由于每种布局的实施都会稍有不同,因此我们需要先确定当前向用户显示的布局。例如,我们可以先了解用户所处的是“单面板”模式还是“双面板”模式。要做到这一点,可以通过查询指定视图是否存在以及是否已显示出来。
    

    public class NewsReaderActivity extends FragmentActivity {
    boolean mIsDualPane;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);
    
        View articleView = findViewById(R.id.article);
        mIsDualPane = articleView != null &&
                        articleView.getVisibility() == View.VISIBLE;
    }
    

    }

    >这段代码用于查询“报道”面板是否可用,与针对具体布局的硬编码查询相比,这段代码的灵活性要大得多。
    
    
    
    
    
    - 步骤2:根据当前布局做出响应
    有些操作可能会因当前的具体布局而产生不同的结果。
    >例如,在新闻阅读器示例中,如果用户界面处于双面板模式下,那么点击标题列表中的标题就会在右侧面板中打开相应报道;但如果用户界面处于单面板模式下,那么上述操作就会启动一个独立活动:
    

    @Override
    public void onHeadlineSelected(int index) {
    mArtIndex = index;
    if (mIsDualPane) {
    /* display article on the right pane /
    mArticleFragment.displayArticle(mCurrentCat.getArticle(index));
    } else {
    /
    start a separate activity */
    Intent intent = new Intent(this, ArticleActivity.class);
    intent.putExtra("catIndex", mCatIndex);
    intent.putExtra("artIndex", index);
    startActivity(intent);
    }
    }

    
    - 步骤3:重复使用其他活动中的片段
    多屏幕设计中的重复模式是指,对于某些屏幕配置,已实施界面的一部分会用作面板;但对于其他配置,这部分就会以独立活动的形式存在。
    >例如,在新闻阅读器示例中,对于较大的屏幕,新闻报道文本会显示在右侧面板中;但对于较小的屏幕,这些文本就会以独立活动的形式存在。
    
    在类似情况下,通常可以在多个活动中重复使用相同的 Fragment 子类以避免代码重复。例如,在双面板布局中使用了 ArticleFragment:
    

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

    然后又在小屏幕的Activity布局中重复使用了它 :
    

    ArticleFragment frag = new ArticleFragment();
    getSupportFragmentManager().beginTransaction().add(android.R.id.content, frag).commit();

    
    - 步骤3:处理屏幕配置变化
    如果我们使用独立Activity实施界面的独立部分,那么请注意,我们可能需要对特定配置变化(例如屏幕方向的变化)做出响应,以便保持界面的一致性。
    >例如,在运行 Android 3.0 或更高版本的标准 7 英寸平板电脑上,如果新闻阅读器示例应用运行在纵向模式下,就会在使用独立活动显示新闻报道;但如果该应用运行在横向模式下,就会使用双面板布局。
    
    也就是说,如果用户处于纵向模式下且屏幕上显示的是用于阅读报道的活动,那么就需要在检测到屏幕方向变化(变成横向模式)后执行相应操作,即停止上述活动并返回主活动,以便在双面板布局中显示相关内容:
    

    public class ArticleActivity extends FragmentActivity {
    int mCatIndex, mArtIndex;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCatIndex = getIntent().getExtras().getInt("catIndex", 0);
        mArtIndex = getIntent().getExtras().getInt("artIndex", 0);
    
        // If should be in two-pane mode, finish to return to main activity
        if (getResources().getBoolean(R.bool.has_two_panes)) {
            finish();
            return;
        }
        ...
    

    }

    
    通过上面一系列步骤,我们就完全可以建立一个可以根据用户界面配置进行自适应的应用程序App了。
    
    ***
    #总结
    经过上面的介绍,对于屏幕尺寸大小适配问题应该是不成问题了。
    ***
    #解决方案
    - 问题:如何进行屏幕密度匹配?
    - 答:
    
    
    
    ![屏幕密度匹配解决方案.png](https://img.haomeiwen.com/i944365/04e4124d0daf0a69.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ###“布局控件”匹配
    **本质:使得布局组件在不同屏幕密度上显示相同的像素效果**
    - 做法1:使用密度无关像素
    由于各种屏幕的像素密度都有所不同,因此相同数量的像素在不同设备上的实际大小也有所差异,这样使用像素(px)定义布局尺寸就会产生问题。
    因此,请务必使用**密度无关像素 dp** 或**独立比例像素 sp **单位指定尺寸。
    - 相关概念介绍
    **密度无关像素**
    - 含义:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关。
    - 单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果
    >1. Android开发时用dp而不是px单位设置图片大小,是Android特有的单位
    >2. 场景:假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度。
    
    - dp与px的转换
    因为ui给你的设计图是以px为单位的,Android开发则是使用dp作为单位的,那么该如何转换呢?
    
    |  密度类型  |  代表的分辨率(px) | 屏幕密度(dpi)|换算(px/dp) |比例|
    | ------------- |:-------------:| -------------:| -------------:| 
    | 低密度(ldpi)    | 240x320   | 120 |1dp=0.75px|3|
    | 中密度(mdpi)    | 320x480  | 160 |1dp=1px|4|
    | 高密度(hdpi)    | 480x800  | 240|1dp=1.5px|6|
    | 超高密度(xhdpi)    | 720x1280  | 320|1dp=2px|8|
    | 超超高密度(xxhdpi)    | 1080x1920  | 480 |1dp=3px|12|
    
    在Android中,规定以160dpi(即屏幕分辨率为320x480)为基准:1dp=1px
    
    
    
    **独立比例像素**
    - 含义:scale-independent pixel,叫sp或sip
    - 单位:sp
    >1. Android开发时用此单位设置文字大小,可根据用户的偏好文字大小/字体大小首选项进行缩放
    >2. 推荐使用12sp、14sp、18sp、22sp作为字体设置的大小,不推荐使用奇数和小数,容易造成精度的丢失问题;小于12sp的字体会太小导致用户看不清
    
    所以,为了能够进行不同屏幕像素密度的匹配,我们推荐:
    - 使用dp来代替px作为控件长度的统一度量单位
    - 使用sp作为文字的统一度量单位
    
    可是,请看以下一种场景:
    >Nexus5的总宽度为360dp,我们现在在水平方向上放置两个按钮,一个是150dp左对齐,另外一个是200dp右对齐,那么中间留有10dp间隔;但假如同样地设置在Nexus S(屏幕宽度是320dp),会发现,两个按钮会重叠,因为320dp<200+150dp
    
    从上面可以看出,由于Android屏幕设备的多样性,如果使用dp来作为度量单位,并不是所有的屏幕的宽度都具备相同的dp长度
    >再次明确,**屏幕宽度和像素密度没有任何关联关系**
    
    所以说,dp解决了同一数值在不同分辨率中展示相同尺寸大小的问题(即屏幕像素密度匹配问题),但却没有解决设备尺寸大小匹配的问题。(即屏幕尺寸匹配问题)
    
    >当然,我们一开始讨论的就是屏幕尺寸匹配问题,使用match_parent、wrap_content和weight,尽可能少用dp来指定控件的具体长宽,大部分的情况我们都是可以做到适配的。
    
    #那么该如何解决控件的屏幕尺寸和屏幕密度的适配问题呢?
    从上面可以看出:
    - 因为屏幕密度(分辨率)不一样,所以不能用固定的px
    - 因为屏幕宽度不一样,所以要小心的用dp
    
    因为本质上是希望使得布局组件在不同屏幕密度上显示相同的像素效果,那么,之前是绕了个弯使用dp解决这个问题,那么到底能不能直接用px解决呢?
    >即根据不同屏幕密度,控件选择对应的像素值大小
    
    接下来介绍一种方法:**百分比适配方法**,步骤如下:
    1. 以某一分辨率为基准,生成所有分辨率对应像素数列表
    2. 将生成像素数列表存放在res目录下对应的values文件下
    3. 根据UI设计师给出设计图上的尺寸,找到对应像素数的单位,然后设置给控件即可
    
    
    #步骤1:以某一分辨率为基准,生成所有分辨率对应像素数列表
    
    现在我们以320x480的分辨率为基准:
    - 将屏幕的宽度分为320份,取值为x1~x320
    - 将屏幕的高度分为480份,取值为y1~y480
    
    然后生成该分辨率对应像素数的列表,如下图:
    - lay_x.xml(宽)
    

    <?xml version="1.0" encoding="utf-8"?>
    <resources><dimen name="x1">1.0px</dimen>
    <dimen name="x2">2.0px</dimen>
    <dimen name="x3">3.0px</dimen>
    <dimen name="x4">4.0px</dimen>
    <dimen name="x5">5.0px</dimen>
    <dimen name="x6">6.0px</dimen>
    <dimen name="x7">7.0px</dimen>
    <dimen name="x8">8.0px</dimen>
    <dimen name="x9">9.0px</dimen>
    <dimen name="x10">10.0px</dimen>
    ...
    <dimen name="x300">300.0px</dimen>
    <dimen name="x301">301.0px</dimen>
    <dimen name="x302">302.0px</dimen>
    <dimen name="x303">303.0px</dimen>
    <dimen name="x304">304.0px</dimen>
    <dimen name="x305">305.0px</dimen>
    <dimen name="x306">306.0px</dimen>
    <dimen name="x307">307.0px</dimen>
    <dimen name="x308">308.0px</dimen>
    <dimen name="x309">309.0px</dimen>
    <dimen name="x310">310.0px</dimen>
    <dimen name="x311">311.0px</dimen>
    <dimen name="x312">312.0px</dimen>
    <dimen name="x313">313.0px</dimen>
    <dimen name="x314">314.0px</dimen>
    <dimen name="x315">315.0px</dimen>
    <dimen name="x316">316.0px</dimen>
    <dimen name="x317">317.0px</dimen>
    <dimen name="x318">318.0px</dimen>
    <dimen name="x319">319.0px</dimen>
    <dimen name="x320">320px</dimen>
    </resources>

    
    - lay_y.xml(高)
    

    <?xml version="1.0" encoding="utf-8"?>
    <resources><dimen name="y1">1.0px</dimen>
    <dimen name="y2">2.0px</dimen>
    <dimen name="y3">3.0px</dimen>
    <dimen name="y4">4.0px</dimen>
    ...
    <dimen name="y480">480px</dimen>
    </resources>

    
    
    找到基准后,是时候把其他分辨率补全了,现今以写1080x1920的分辨率为例:
    >因为基准是320x480,所以1080/320=3.375px,1920/480=4px,所以相应文件应该是
    
    - lay_x.xml
    

    <?xml version="1.0" encoding="utf-8"?>
    <resources><dimen name="x1">3.375px</dimen>
    <dimen name="x2">6.65px</dimen>
    <dimen name="x3">10.125px</dimen>
    ...
    <dimen name="x320">1080px</dimen>
    </resources>

    - lay_y.xml
    

    <?xml version="1.0" encoding="utf-8"?>
    <resources><dimen name="y1">4px</dimen>
    <dimen name="y2">8px</dimen>
    <dimen name="y3">12px</dimen>
    <dimen name="y4">16px</dimen>
    ...
    <dimen name="y480">1920px</dimen>
    </resources>

    
    用上面的方法把你需要适配的分辨率的像素列表补全吧~
    
    作为程序猿的我们当然不会做手写的这些蠢事!!!多谢 @鸿洋大神 提供了自动生成工具(内置了常用的分辨率),大家可以直接[点击这里](https://github.com/hongyangAndroid/Android_Blog_Demos/tree/master/blogcodes/src/main/java/com/zhy/blogcodes/genvalues)下载
    注:工具默认基准为400*320,当然对于特殊需求,通过命令行指定即可:
    

    java -jar 文件名.jar 基准宽 基准高 额外支持尺寸1的宽,额外支持尺寸1的高_额外支持尺寸2的宽,额外支持尺寸2的高:

    
    >例如:需要设置的基准是800x1280,额外支持尺寸:735x1152 ;3200x4500;
    

    java -jar 文件名.jar 800 1280 735,1152_3200,4500

    
    
    #步骤2:把生成的各像素数列表放到对应的资源文件
    将生成像素数列表(lay_x.xml和lay_y.xml)存放在res目录下对应的values文件(注意宽、高要对应),如下图:
    
    ![res目录下对应的values文件](https://img.haomeiwen.com/i944365/c583e1356f18e329.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    >注:
    - 分辨率为480x320的资源文件应放在res/values-480x320文件夹中;同理分辨率为1920x1080的资源文件应放在res/values-1920x1080文件夹中。(其中values-480x320是分辨率限定符)
    - 必须在默认values里面也创建对应默认lay_x.xml和lay_y.xml文件,如下图
    lay_x.xml
    

    <?xml version="1.0" encoding="utf-8">
    <resources>
    <dimen name="x1">1.0dp</dimen>
    <dimen name="x2">2.0dp</dimen>
    ...
    </resources>

    - 因为对于没有生成对应分辨率文件的手机,会使用默认values文件夹,如果默认values文件夹没有(即没有对应的分辨率、没有对应dimen)就会报错,从而无法进行屏幕适配。
    (**注意对应单位改为dp,而不同于上面的px。**因为不知道机型的分辨率,所以默认分辨率文件只好默认为x1=1dp以保证尽量兼容(又回到dp老方法了),**这也是这个解决方案的一个弊端**)
    
    
    #步骤3:根据UI设计师给出某一分辨率设计图上的尺寸,找到对应像素数的单位,然后设置给控件即可
    如下图:
    

    <FrameLayout >

    <Button
        android:layout_gravity="center"
        android:gravity="center"
        android:text="@string/hello_world"
        android:layout_width="@dimen/x160"
        android:layout_height="@dimen/y160"/>
    

    </FrameLayout>

    
    #总结
    使用上述的适配方式,应该能进行90%的适配了,但其缺点还是很明显:
    - 由于实际上还是使用px作为长度的度量单位,所以和google的要求使用dp作为度量单位会有所背离
    - 必须尽可能多的包含所有分辨率,因为这个是使用这个方案的基础,如果有某个分辨率缺少,将无法完成该屏幕的适配
    - 过多的分辨率像素描述xml文件会增加软件包的大小和维护的难度
    
    ***
    ###“图片资源”匹配
    **本质:使得图片资源在不同屏幕密度上显示相同的像素效果**
    - 做法:提供备用位图(符合屏幕尺寸的图片资源)
    由于 Android 可在各种屏幕密度的设备上运行,因此我们提供的位图资源应该始终可以满足各类密度的要求:
    
    |  密度类型  |  代表的分辨率(px) | 系统密度(dpi)|
    | ------------- |:-------------:| 
    | 低密度(ldpi)    | 240x320   | 120 |
    | 中密度(mdpi)    | 320x480  | 160 |
    | 高密度(hdpi)    | 480x800  | 240|
    | 超高密度(xhdpi)    | 720x1280  | 320|
    | 超超高密度(xxhdpi)    | 1080x1920  | 480 |
    
    - 步骤1:根据以下尺寸范围针对各密度生成相应的图片。
    >比如说,如果我们为 xhdpi 设备生成了 200x200 px尺寸的图片,就应该按照相应比例地为 hdpi、mdpi 和 ldpi 设备分别生成 150x150、100x100 和 75x75 尺寸的图片
    
    **即一套分辨率=一套位图资源**(这个当然是Ui设计师做了)
    
    - 步骤2:将生成的图片文件放在 res/ 下的相应子目录中(mdpi、hdpi、xhdpi、xxhdpi),系统就会根据运行您应用的设备的屏幕密度自动选择合适的图片
    - 步骤3:通过引用 @drawable/id,系统都能根据相应屏幕的 屏幕密度(dpi)自动选取合适的位图。
    
    >注:
    - 如果是.9图或者是不需要多个分辨率的图片,放在drawable文件夹即可
    - 对应分辨率的图片要正确的放在合适的文件夹,否则会造成图片拉伸等问题。
    
    #更好地方案解决“图片资源”适配问题
    上述方案是常见的一种方案,这固然是一种解决办法,但缺点在于:
    - 每套分辨率出一套图,为美工或者设计增加了许多工作量
    - 对Android工程文件的apk包变的很大
    
    
    那么,有没有一种方法:
    - 保证屏幕密度适配
    - 可以最小占用设计资源
    - 使得apk包不变大(只使用一套分辨率的图片资源)
    
    下面我们就来介绍**这个方法**:
    - 只需选择唯一一套分辨率规格的图片资源
    
    #方法介绍
    
    **1. 先来理解下Android 加载资源过程**
    Android SDK会根据屏幕密度自动选择对应的资源文件进行渲染加载(自动渲染)
    >比如说,SDK检测到你手机的分辨率是320x480(dpi=160),会优先到drawable-mdpi文件夹下找对应的图片资源;但假设你只在xhpdi文件夹下有对应的图片资源文件(mdpi文件夹是空的),那么SDK会去xhpdi文件夹找到相应的图片资源文件,然后将原有大像素的图片自动缩放成小像素的图片,于是大像素的图片照样可以在小像素分辨率的手机上正常显示。
    >具体请看http://blog.csdn.net/xiebudong/article/details/37040263
    **所以理论上来说只需要提供一种分辨率规格的图片资源就可以了**。
    那么应该提供哪种分辨率规格呢?
    >如果只提供ldpi规格的图片,对于大分辨率(xdpi、xxdpi)的手机如果把图片放大就会不清晰
    
    所以需要提供一套你需要支持的最大dpi分辨率规格的图片资源,这样即使用户的手机分辨率很小,这样图片缩小依然很清晰。那么这一套最大dpi分辨率规格应该是哪种呢?是现在市面手机分辨率最大可达到1080X1920的分辨率(dpi=xxdpi=480)吗?
    
    **2. xhdpi应该是首选**
    
    原因如下:
    - xhdpi分辨率以内的手机需求量最旺盛
    目前市面上最普遍的高端机的分辨率还多集中在720X1080范围内(xhdpi),所以目前来看xhpdi规格的图片资源成为了首选
    - 节省设计资源&工作量
    在现在的App开发中(iOS和Android版本),有些设计师为了保持App不同版本的体验交互一致,可能会以iPhone手机为基础进行设计,包括后期的切图之类的。
    设计师们一般都会用最新的iPhone6和iPhone5s(5s和5的尺寸以及分辨率都一样)来做原型设计,所有参数请看下图
    
    |机型|   分辨率(px)  |  屏幕尺寸(inch) | 系统密度(dpi)|
    | ------------- |:-------------:| -------------:| 
    |iPhone 5s| 640X1164     |  4 | 332 |
    |iPhone 6| 1334x750     |  4.7 | 326 |
    | iPhone 6 Plus    | 1080x1920  |5| 400 |
    
    iPhone主流的屏幕dpi约等于320, 刚好属于xhdpi,所以选择xhdpi作为唯一一套dpi图片资源,可以让设计师不用专门为Android端切图,直接把iPhone的那一套切好的图片资源放入drawable-xhdpi文件夹里就好,这样大大减少的设计师的工作量!
    
    #额外小tips
    - ImageView的ScaleType属性
    设置不同的ScaleType会得到不同的显示效果,一般情况下,设置为centerCrop能获得较好的适配效果。
    
    - 动态设置
    >使用场景:有些情况下,我们需要动态的设置控件大小或者是位置,比如说popwindow的显示位置和偏移量等
    
    这时我们可以动态获取当前的屏幕属性,然后设置合适的数值
    

    public class ScreenSizeUtil {
    public static int getScreenWidth(Activity activity) {
    return activity.getWindowManager().getDefaultDisplay().getWidth();
    }
    public static int getScreenHeight(Activity activity) {
    return activity.getWindowManager().getDefaultDisplay().getHeight();
    }
    }

    
    
    ###总结
    本文根据现今主流Android的适配方法,以逻辑清晰的方式进行了主流Android适配方法的全面整理,接下来我会介绍继续介绍Android开发中的相关知识,有兴趣可以继续关注[Carson_Ho的安卓开发笔记](http://www.jianshu.com/users/383970bef0a0/latest_articles)
    #请点赞!因为你们的鼓励是我写作的最大动力!
    >**相关文章阅读**
    [Android开发:ListView、AdapterView、RecyclerView全面解析](http://www.jianshu.com/p/4e8e4fd13cf7)
    [Android开发:史上最全的Android消息推送解决方案](http://www.jianshu.com/p/b61a49e0279f)
    [Android开发:最全面、最易懂的Webview详解](http://www.jianshu.com/p/3c94ae673e2a)
    [Android四大组件:Service服务史上最全面解析](http://www.jianshu.com/p/d963c55c3ab9)
    [Android四大组件:BroadcastReceiver史上最全面解析](http://www.jianshu.com/p/ca3d87a4cdf3)
    [Android开发:JSON简介及最全面解析方法!](http://www.jianshu.com/p/b87fee2f7a23)
    [Android开发:XML简介及DOM、SAX、PULL解析对比](http://www.jianshu.com/p/e636f4f8487b)
    
    ***
    ###欢迎关注[Carson_Ho](http://www.jianshu.com/users/383970bef0a0/latest_articles)的简书!
    不定期分享关于**安卓开发**的干货,追求**短、平、快**,但**却不缺深度**。
    
    
    ![](https://img.haomeiwen.com/i944365/9b76fa3c52d478a7.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

    相关文章

      网友评论

      • yoUrzEromAx:博主,提个建议,您的博客总结的很全面,知识点覆盖也很广,但是作为读者,同一个知识,会优先看别人的博客来解决问题。您的博客描述语言太生硬,不形象。当然是由于个人自身技术原因,不好理解。建议多增加一些形象的描述。。。。其实这篇文章我看了过后还是不知道怎么去适配,基础知识都懂,提出了问题所在,但没提出如何解决。
      • lynch0571:已收录《千赞专题》,欢迎关注:http://www.jianshu.com/collection/032a478c3dbf
      • Veneto_2022:谢谢分享
      • 我可梦:能转载不
      • zhang_pan:写了半天 我也没看见 你怎么去适配的
        erki_stwee:@zhang_pan 你可以写个demo感受哈,映像深刻点
        zhang_pan:@UartAnd7c 听起来很高深的感觉
        erki_stwee:作者写的是思想,从尺寸跟密度适配入手。你要根据你实际情况去选择适合你的适配
      • developerYk:你好,博主 这篇文章写的很用心 先在这里谢谢你的贡献。我有一个问题是 Android 默认以 320×480 为基准的,那么设计师以 1080 P 给我切的图 那我是不是就以 1920×1080 为基准来生成对应的 layout 文件 谢谢!
      • javaBoy_hw:在《密度无关像素》一节,dp与px的转换表中,比例什么意思?好像也不是dp/px的比例啊。
      • xiayuexingkong:博主你好!很感谢您的技术分享。我在用鸿阳大神的autolayout.jar生成“不同分辨率下的像素列表”的时候遇到一个问题,-------使用“java -jar autolayout.jar”命令生成了一个res目录,该目录下有各个分辨率对应的lay_x.xml和lay_y.xml。然后我发现在"values-480x320"目录下的lay_y.xml文件有问题 其中“<dimen name="y1">1.2px</dimen>”,这里不应该是1.0px的么?即应该是<dimen name="y1">1.0px</dimen>。--------
        故此,请教博主有没有遇到该问题?如果遇到的话,该如何解决的呢?
        xiayuexingkong:我回头看了下原来 默认基准的分辨率为“400*320”的哈,,:smile:
      • Dynamic_2018:把markdown都贴出来了 哈哈
      • 徘徊0_:翻看博主博客的时候,突然看到这个文章了。想问,现在博主 怎么适配屏幕的?
        zhang_pan:我表示也想问 博主写了很多 我是没看见他项目中怎么适配的
      • 谢尔顿:又出了约束布局
      • aa924a4fced0:看完了很多疑问 篇幅过长我也是耐着性子往下看。但我最后觉得归根结底的适配思路还是多套xml文件 根据不同分辨率的手机来具体选择dimen文件中的px值。是这样么?还是说你的思路精髓我还是没有领会到。如果单单是多个xml文件进行适配这个思路的话,我觉得还是有很多弊端,首先xml文件要多套,编写起来也不是很容易 对app体量也会有所影响
      • ccbeb2ce36e7:放在超大屏上就是个悲剧
      • 冯家二少:我去,史上最详细的屏幕适配方案,顶一个!
        ixinrun:@冯家二少 史上最简单高效的可以看看这篇http://www.jianshu.com/p/4baa82130a9f
      • 好好看好好学_392e:在实际的项目中,大部分使用的是哪种适配呢?
        后来Memory:个人非常同意鸿洋大神说的dp已经几乎 适配市面上的绝大部分机型了,公司和鸿洋大神差不多我们做了六个项目都没有刻意的去做适配,我们只需要针对绝大数的用户! 所以至今我们也没刻意去做适配!
      • 9d13dac0b326:我是第1001个喜欢
      • 烤乳猪工作室:百分比这个可以的。布局适配用的多
      • 隋胖胖LoveFat:亲,最后的格式乱掉了==
      • Kaaaaai:楼主我在5英寸的pixel xl模拟器上试过没问题,但放在同样尺寸的乐视pro1和5.5英寸的米5上就发生了同样的位移,请问这是为什么?
      • woshilwz:太赞了
      • Vander丶:您好博主,读完您的博客 有个问题:

        假设 我自定义的分辨率 是 720 *1166 的我定义完Values的文件

        实际在我使用时, 我量超过320的宽度的 控件 像素大小是 450,

        这时候我还按当前的比例大小,计算出450对应的大小,然后设置么.
        Kaaaaai:@Vander丶 怎么设置基准分辨率
        Vander丶:我明白了.昨天又看了一遍,需要设置基准分辨率.
      • very_mrq:文件名的重复从而带来一些列后期维护的问题:fearful: 是什么问题????求解
      • CrazyJasonX:有虚拟按键的还要弄一套减去高度的布局吗,有什么好的解决方法,华为2个手机都是1920*1080的,都有虚拟按键,当是一只可以适配一只不能适配。
      • 孤傲的南方人:墙都不扶就服你!能看出作者很用心,文章说的很详细,有些写博客都是抄别人的过来的,看得心很累。。
      • a1b06a0e672a:你好,我想问下sw-600dp这个600dp是怎么计算得到的,举个例子,比如是三星S7edge,分辨率:2560x1440像素,5.5inch,像素密度534dpi。最小宽度为:1440/(534/160)=431。但是我用了sw-430dp的限定符,发现并不使用这个布局。
      • 点点文学:默认values 怎么生成??
      • 9d03161ce41e:大哥啊,我用夜神模拟器1920分辨率适配完事后,用真机1920的查看结果差的挺多,基本不算适配。请问为什么啊
        Kaaaaai:解决了吗?我遇到同样的问题
      • 12ec1d19f17e:看了 郭霖,鸿洋等大神的几篇文章,在回头看这篇。真的号很多
      • bfdb40eabfab:生成分辨率对应文件的做法是完全错误的,适配就得使用dp,如果美工出图720p,就除以2得到dp值,1080p就除以3。竖向适配主要采取滚动来做,横向主要考虑主流分辨率,目前是360dp,适当考虑320dp。
        其实新手最好的学习适配方法是github看大牛的开源软件的适配,或者反编译大公司的软件查看!
        Carson带你学安卓:@MRnew 同学,请参考更多的文章 & 细心阅读本文~适配是不一定要用dp的哦,本质还是px,dp只是谷歌给出一种适配的方式而已。
      • 37d5fc52de9e:请问大哥,ios提供的有2倍图,和3倍图,我是应该用几倍的呢?求解答.
      • 凯哥在此:楼主你好,写资源文件的方法一般情况下是很实用的,但是华为机子上就会出现一些问题,界面有一些压缩,你是怎么解决的
        乐哉乐哉:@凯哥在此 将1920-1080layout像素文件复制一份到1720-1080即可适配
        凯哥在此:@Carson_Ho 我之前也是减去了,下面的导航长度是144减去之后,上面的布局还是有一些问题,最后我还是全部换成了dp,才没有压缩的情况
        Carson带你学安卓: @凯哥在此 这个需要手动减去底部那个导航的长度
      • 0832b1ebfbc6:楼主,你的第一张目录的图是用什么画的啊
        Carson带你学安卓: @freshyang xmind
      • 超级软件:请问大神每个项目都要做平板适配和像素数列表适配吗,还是因项目而异呢?
        Carson带你学安卓: @我爱学习321 看产品需求和场景
      • 114519501905:楼主棒棒哒
        :relaxed:
      • 7c20bdeaae48:博主你好,“百分比适配方法”貌似在有NavigationBar的机型上不能正常适配,比如我在1080*1920带有NavigationBar的模拟器上调试发现,屏幕竖直方向实际可用像素为1794像素(NavigationBar占用的126像素),导致控件被“压扁”,有没有什么办法解决呢?
        Carson带你学安卓: @罗杰儿 这个就需要手动加入减去bat长度的资源文件了
      • d738d59c00a8:google官方🈶️推出了一个百分比支持库,布局全部是使用的weight来自适应的。但是好像实际项目中没什么人使用
        heukeith:@待到春花烂漫 文章有没有链接
        65d806d07564: @pgy2600 对于程序员来说,过时的就是垃圾,现在还用eclipse写android的大有人在
        12ec1d19f17e:鸿洋 大神,已经出文章专门说这件事了。
      • AJI大侠:通常情况下都是一套图片的会比较多,美工其实也是很懒的
      • ecc91d5512cb:大神还在关注这边文章么?请教一个问题:如果app横屏的时候自动生成的那些尺寸资源文件还能识别吗?
      • m曲终杯盏凉:“Nexus5的总宽度为360dp”,请问你这个360dp是怎么算出来的呢?是 1080 / 3 = 360吗?
        按这个逻辑我算出三星C7Pro(1920*1080,5.7’)的总宽度也是360dp,但在xml代码中设置控件宽度360dp(android:layout_width="360dp"),然而并没有得到占满屏幕宽的效果,而是有一节空白。
        甚至设置180dp也没有达到屏幕宽的一半。
        是我理解错了么,望指教。
        ting说你跳:DP值 = Px值 / 屏幕对角线长度,
        经过计算,实际上三星C7Pro的DP值为386dp。
        但是系统计算浓度的时候是根据标准的几个DP值取的近似值,把386dp看成了320dp,
        计算出的浓度为2。
        这样的话你设置的控件长度为360dp,实际上是720px,是小于1080px的,所以占不满。
      • 带心情去旅行:你里面说的一个方案:**以某一分辨率为基准,生成所有分辨率对应像素数列表**
        这东西早年可能还适用,不过现在我不推荐使用。我15年在项目中用过,由于Android屏幕实在是太多,各种奇葩屏幕。永远有你考虑不到的分辨率,导致布局在一些手机上根本没法看。
        因为用了这个,用户反馈各种问题。大坑啊~~最后只能选择弃用。
        Carson带你学安卓: @2605072201 就是按照需求场景,然后根据这篇文章去适配的
        422df8d57f4a:能告诉一下你现在是怎么适配的吗?
        Carson带你学安卓: @带心情去旅行 所以只能适配最常用的,其余就用默认的代替,默认里是用dp为单位的,也是能进行适配,但没有百分比那么精准而已
      • 50905fcc2280:工具怎么用啊?、不会用,求指点
        Carson带你学安卓:下载后,在命令行输入java -jar 文件名.jar 基准宽 基准高 额外支持尺寸1的宽,额外支持尺寸1的高_额外支持尺寸2的宽,额外支持尺寸2的高:
      • 夜枫_郎:很好
      • 一盘好书:sw限定符,不应该是最短屏幕可用宽度吗?应该是宽度或者高度中较小的那个还要大于这个最小宽度才能匹配成功吧?
        Carson带你学安卓: @轩涯凝荫 是的
        50905fcc2280:我也看出这个问题了,
      • LulPerer:好文,要好好学学,谢谢楼主分享:smile:
      • 老郭种树:大佬 还在关注这里吗急救。有三个问题问下,1.字体sp如果也采用这样,使用x文件的还是y文件de。2.华为适配不了,这怎么办,进都进不去。3.默认的values中x和dp有什么快捷办法写没,要写到多少去额
        老郭种树:@Carson_Ho ok
        Carson带你学安卓:@探花so 已私信
      • 培根炒蛋:大牛,请收下我的膝盖,能总结成这样简直是不能再强.....牛逼啊...请问大牛哪个公司工作?
      • Chauncey_Chen:感谢作者~
      • 头发很乱2:请问那个Google的密度表分别对应的屏幕尺寸是多大?
        Carson带你学安卓:具体请看文章
      • 心田祭思:美工切图很快的
        Carson带你学安卓:不是在于他的工作量,关键是会导致APP的安装包很大
      • 936149dc89d5:请问,你默认的values应该写到什么尺寸呢?
        Carson带你学安卓:文章有写,主要是用dp
      • 558cdd6fd482:很全面!!
      • Jaycee88:非常全面,收藏了,谢谢!
      • 85667e91bb85:写的易懂
      • JZ_Daemon:受教!!!
      • ppyy一号:以某一分辨率为准的方法,如果手机有虚拟按键(例如nexus 5x) 就适配不到1920x1080的,后来我手动生成了一套1794x1080的values文件夹才解决,这种情况楼主有遇到过么?
        Carson带你学安卓:对于有下巴的,确实需要特别适配
      • Lee_J:现在正好用
      • 产品小贤:关于最后图片适配那一点有些疑问,既然选择xhdpi一套图就可以适配,那为什么现实中很多app都会提供两三套图呢?是不是只提供xhdpi会导致一定的性能问题?
        拉丨登:是的。系统帮忙缩放图片也是要耗内存的,,,特别是差异大的时候
      • 86e153868414:大神,字体大小适配有什么好的建议吗?
        Carson带你学安卓: @东坡先生_1992 一样的啊,用百分比
        cc07e99cee9c:@ppyy一号 +1
        ppyy一号:@东坡先生_1992 同问
      • b795ba14cf12:刚好赶上项目要适配
      • 凤鸣游子:大哥, 实际开发中你们一般是怎么干的?
        Carson带你学安卓:@阿水哥哥 具体你看下我写的另外一篇文章http://www.jianshu.com/p/ed9e15eff47a
        凤鸣游子:@Carson_Ho 我有一个疑惑想请教一下. 对于Handler造成的泄露, 如果没有Looper那边对它的引用, 不是还有Activity对它有引用吗? 这样Activity和Handler互相持有引用, 会不会造成内存泄露呢? 因为他们谁也释放不掉啊.(内容和本文不想关, 但是我比较困惑就问下高手吧)
        Carson带你学安卓: @阿水哥哥 就这样干啊
      • 皮卡丘520:有源码吗?
      • 独一妩二丶:洪洋大哥的生成工具怎么没法下载?
      • 雩航:1024*600 但不同的dpi 160 240 可以写成values-land-hdpi-1024x600 values-land-mdpi-1024x600
      • 47287ba8b36e:.9图应该是多套的吧,参考一下这个网站生成的点9图http://romannurik.github.io/AndroidAssetStudio/nine-patches.html
      • Avalon1: :sweat: 不知道为啥。用模拟器试了下。。。好像还是不行
      • llyofdream:总结的很好,Mark了,后面会去实践的,只有实践才能真正知道效果—16/6/5
      • a51419380514:点赞~
      • ldlywt:最喜欢这种适应初学者的文章了
      • 3ee6e9ef0293:还可以多一个,根据代码动态的获取设备的长宽根据一定的比例来做适配
        Carson带你学安卓:文章有提到,请耐心查看
      • 材才才:写得很好啊,收藏了。
      • dukecui:太牛逼了
      • 07bcab0a846c:好好好 谢谢
      • MeloDev:很不错,收藏了

      本文标题:Android 屏幕适配:最全面的解决方案

      本文链接:https://www.haomeiwen.com/subject/eadulttx.html