适配,限定符入门

-sw<N>dp与-w<N>dp的区别

        两者都是资源限定符,但含义区别很大:

        android的手机屏幕都是长方形的,而长方形有两对边。其中一对比另一对长。我们把短的叫做A,长的一对叫做B。-sw<N>dp的意思就是:如果A的长度比N值大,就可能使用该资源,否则不能使用。-w<N>dp的意思是:如果手机的宽度比Ndp大,就可以使用该资源。

        要注意的是:手机的宽是变化的,并不一定总是最短的那对,它指的是手机横着的那一边。如手机的分辨率是960*540,当竖着是宽便是540,而横着时宽便是960。但是如果是什么时候sw都是540。

各种drawable-*dpi

        在android适配中,需要用到各种drawable-*dpi文件夹,具体后缀参考后继的限定符。

        drawable的后缀名是跟屏幕分辨率无关的,只跟屏幕密度有关。只要屏幕密度是320dpi,不管手机的分辨率是多少,都会选择drawable-xhdpi文件夹中的图片。其它类同。

        如果没有刚好合适的文件夹,那就选择最接近的大的文件夹。在默认情况下:系统会选择较大的图片去缩小,而不是选择较小的图片去放大。文档上的描述为:

If the qualifier in question is screen pixel density,Android selects the option that most closely matches the device screen density.In general, Android prefers scaling down a larger original image to scaling up a smalleroriginal image.

        如果在当前文件夹中没有找到该资源,就会在别的drawable中寻找,只不过在显示的时候会根据比例进行放大或者缩小。假如手机的屏幕密度是240dpi,图片被放到了xhdpi文件夹中,那么显示该图片时,图片会被缩小到原来的3/4。因为xhdpi是320dpi,而hdpi是240,由320变成240,就需要缩小到原来的3/4。如

    <ImageView
        android:id="@+id/iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/hello_world"
        android:src="@drawable/test" />
        test本身的大小为301*147,手机的屏幕密度是240dpi。

        如果将图片放到hdpi下,那么imageview的大小为301*147。

        如果放到xxhdpi下,imageview的大小为151*74。xxdpi缩到hdpi就需要缩小两倍,而原图片缩小两倍并按四舍五入取整后,就是151*74。

        如果放到xhpi下,那么imageview的大小为226*110。由320缩到240,需要缩小0.75倍,原图缩小0.75倍后就成了226*110。

res目录说明

        res文件夹中通常是用来存放资源的,如字符串、图片等。但是不能将资源直接放在res目录下,只能放在res目录下的某个子文件夹中。常用的子文件夹有:animator/存放属性动画。anim/存放tween动画、帧动画,虽然属性动画仍旧可以放在该目录下,但不建议这么做。xml/用来存放任意的xml文件的,在运行时可以通过Resources.getXml()获得相应的xml文件。raw/存放资源文件的,在运行时可通过Resources.openRawResource();将对应的资源转换成InputStream。除了上述四个之外,还有一些常用的如layout,menu,drawable,values等。

        除了系统指定的名字外,Android会忽略res目录下的其它文件。比如创建res/xxx,可能不会发生错误,但是Android不会使用旋转在其中的任何资源。而且,也不能在res/目录下创建多级目录。

限定符

定义与作用

        在res目录下的子文件夹,有些文件夹后面会带有-xxx(常见的如drawable-mdpi,values-en等),这后面附带的就是修饰符(限定符)。它的主要作用就是:限定能使用该资源的设备的配置,当设备配置满足修饰符时才能使用该资源,不满足时不能使用该资源。如values-en,表明只有当设备的语言是英语时才可使用该目录下的资源,不然不能使用该资源。

默认资源

       如果一个资源没有配置修饰符,该资源就称作默认资源默认资源是必不可少的。当android设备没有找到匹配修饰符的资源时,就会调用默认资源。此时如果没有默认资源,应用将有可能崩溃。因此正确的做法除默认资源外,额外的提供一些可选的资源。这时候就是需要使用不同的修饰符。

       除了上面的原因外,还有可能是有些修饰符要求的版本比运行的系统高,所以该系统会自动忽略这个可选资源。从而造成在某些情况找不到合适的资源。这个时候也需要默认资源。系统会忽略掉比他版本高的修饰符,同时忽略掉含有这些修饰符的资源

       但对于drawable资源来说,当minSdkVersion>=4时,不需要默认资源。在必要时,系统会自动从可选资源中找到合适的图片进行缩放显示。

配置修饰符

        一个资源可以添加多个修饰符,如:values-en-land,但是这些修饰符的的排列顺序有一定要求。只有排序正确的才有效,排序不正确的资源会被系统忽略。顺序如下:

适配,限定符入门_第1张图片

        其中屏幕尺寸中small指的最低尺寸是320dp*426dpnormal指的最低尺寸是320dp*470dplarge指的最低尺寸是480dp*640dpxlarge指的最低尺寸是720dp*960dp

可用资源的匹配

        当系统处于某一配置时,可能有多个资源满足条件。Android会基于上图顺序确定使用哪一个可用资源。筛选过程如下:

        当所有的资源都不含某一修饰符时,直接进行下一个修饰符的匹配;

        当有些资源含有该修饰符,而另一些不含时,将不含的资源全部淘汰.同时将那些与设备配置不匹配的资源也淘汰,剩余的资源再进行下一个修饰符的匹配。直到所有的修饰符匹配结束。

        所有的修饰符匹配结束后,如果没有可选资源存留,就会使用默认资源。

        但上述的规则并不适用于屏幕密度。假设当前的屏幕密度是hdpi,drawable-port-ldpi/xhdpi并不会因此被淘汰。如果有两个可选资源(两个资源离当初配置一样近),一般情况下会将两个资源都保留,在所有的条件筛选完毕后再选择密度较大的资源。

       同样也不适用于屏幕尺寸修饰符。假设可选资源中,没有资源能更好地匹配当前屏幕尺寸,系统将使用为比当前屏幕小的屏幕准备的资源(例如,一个大尺寸的屏幕将在必要时使用普通屏幕尺寸资源)。然而,如果可用的资源比当前屏幕大,系统将不使用它们(例如,如果所有的资源布局的标签为xlarge限定符,但设备是一个正常大小的屏幕,系统并不会使用该资源)。也就是说:比当前屏幕小的资源,有可能被使用;但是比当前屏幕大的资源一定不会被使用

示例

        假设本地的可选资源如下:

drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
        设备配置如下:
Locale = en-GB
Screen orientation = port
Screen pixel density = hdpi
Touchscreen type = notouch
Primary text input method = 12key

        那么最终存留的可选资源就是:drawable-en-port。当在匹配语言与地区时,会将第3,6,7淘汰掉。匹配屏幕方向时,会将2,5淘汰掉。再往后匹配时,存留的资源中都没有含有修饰符,因此,直到结束4仍旧存留。

       在注意的是:上图中修饰符的优先级要比正确匹配的修饰符的个数重要。从上面可以发现,7一共匹配了3个修饰符,而4只匹配了2个。但是由于4匹配的语言与地区的优先级比7中的高,所以7直接在语言与地区匹配时就被淘汰。

使用别名资源

        别名资源是一种特殊的资源,它指向了其他资源。按照约定,它是放在res/values目录下的refs.xml文件中的。示例如下:
<resources>

    <item name="test_main" type="drawable">@drawable/fengxian</item>

</resources>
        别名资源的type属性决定了该资源属于R文件中的哪个内部类。如上,type=drawable,那么即使别名资源在values目录中,但对它的引用仍旧是R.drawable或者@drawable。
        分别在values目录下,和values-land目录下放置一个refs.xml文件。其中values-land中的文件内容如上所示,而values目录下的内容为:
<resources>

    <item name="test_main" type="drawable">@drawable/furong</item>

</resources>
        对比上面两段xml文件可知,name属性的值是一样的,只有引用的资源名不一样。使用代码如下:
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="@drawable/test_main" />
        这里直接引用了test_main,而不fengxian或者furong。并且,当旋转屏幕时,可以发现imageview所显示的图片改变了。但是在实际中,fengxian和furong两张图片是放在同一个文件夹下的。
        从上面看出:别名资源是一种指向其他具体资源的特殊资源,它本身并不代表任何实际资源,它只是指向了实际资源。并且在不同的条件下,别名资源可以指向不同的实际资源。从而实现了在不同条件下资源的相互替代。
        

资源目标(res)目录说明

        res文件夹中通常是用来存放资源的,如字符串、图片等。但是不能将资源直接放在res目录下,只能放在res目录下的某个子文件夹中。常用的子文件夹有:animator/存放属性动画。anim/存放tween动画、帧动画,虽然属性动画仍旧可以放在该目录下,但不建议这么做。xml/用来存放任意的xml文件的,在运行时可以通过Resources.getXml()获得相应的xml文件。raw/存放资源文件的,在运行时可通过Resources.openRawResource();将对应的资源转换成InputStream。除了上述四个之外,还有一些常用的如layout,menu,drawable,values等。

        除了系统指定的名字外,Android会忽略res目录下的其它文件。比如创建res/xxx,可能不会发生错误,但是Android不会使用旋转在其中的任何资源。而且,也不能在res/目录下创建多级目录。

你可能感兴趣的:(适配,限定符入门)