书接上回,我们已经了解了一些关于适配的一些相关概念,接下来我们会了解一下,在设置布局时我们应该注意的地方。
尽量不去设定具体的尺寸值。
为了确保布局适应各种尺寸的屏幕,在保证功能实现的前提下,最好不要写死一些尺寸,这样的硬编码,我们最好使用“match_parent”,”wrap_content”,”weight”这些不用指定具体的尺寸值的参数,这样视图就会根据自身需要的空间去充填。这样就可以让布局去适应各种屏幕的尺寸,当屏幕有旋转时也不会受到影响。
这里我们重点说一下“weight”,用过LiearLayout的同学应该都知道这个是什么意思,它是LinearLayout独有的属性,我们可以使用这个属性对界面成比例的分配,当我们的布局对比例有要求时,我们就可以使用这个属性进行设置。
既然是成比例,肯定会有的一个比例的计算规则。为了缩短篇幅,我们直接给出计算公式(我们只给出横向的,竖向类似):
控件宽度 = 控件的原有宽度 +((LinearLayout宽度 - (所有子控件宽度总和))/ 所有子控件的weight总和) × 控件的weight值
控件的宽度=控件的原有宽度+(LinearLayout的宽度-(所有子控件的宽度和)÷所有子控件的weight总和))×控件的weight值
比如我们现在有个的屏幕是 320x480,根布局为LinearLayout,狂傲为”match_parent”,方向为横向,其中有两个Button ,A和B,且A,B的android:layout_width属性为”match_parent”,weight属性值为1,那么根据公式,我们计算一下A的宽度:
A=320+((320-(320+320))/2)*1 =320+(-160) *1 = 160
即整个布局的一半;关于这个这里不再细讲,感兴趣的同学可以去大神赵凯强的博客去看一下。
千万不要使用绝对布局
绝对布局里东西都是限定死的,对我们适配极为不利,我们不要使用它,我们优先使用 RelativeLayout,LinearLayout。
其中 RelativeLayout中的控件位置都是相对的,我们可以根据不同需求调整控件的位置,而LinearLayout 它其中的控件的方向都是线性的,对着这方面有要求的可以优先使用。
考虑Fragment的使用
关于这个可以参看我之前写的,关于Fragment的内容希望会对大家有帮助
使用尺寸限定符
在Fragment里已经介绍过尺寸限定符了,这里再具体说一下。
为什么要使用尺寸限定符
大家都知道,手机跟平板的尺寸差别很大,有的平板是手机的两倍大小,当我们的应用需要在手机或者平板上运行时,同一个界面 在手机上显示很好,但是到了平板就会奇丑无比,所以有时候我们会设计两款布局,分别在手机和平板显示,但是我们又不想去写两个Activity,怎么办?这样我就会用到尺寸限定符。
默认的 我们的布局是放到 layout这个文件夹下,我们的应用运行时,只会从这个文件夹下加载布局。 当我们希望不同大小的手机或者平板加载不同的布局时,我们就会创建一些其它的文件来放置布局。一般的我们会使用尺寸限定符来命名这些文件夹,这些限定会跟在layout后面,并以“—”间隔,当然这写限定符不仅适用于layout,也同样适用于values,下面列举两种:
限定符
功能介绍
large
系统会在属于较大屏幕(例如 7 英寸或更大的平板电脑)的设备上选择此布局。系统会在较小的屏幕上选择layout下的布局。
sw600dp
布局仅适用于最小宽度为 600 dp 的屏幕, 但 Android 版本低于 3.2 的设备不支持此技术,原因是这些设备无法将 sw600dp 识别为尺寸限定符,因此您仍需使用 large 限定符
比如我们现在有一款新闻app,当在小屏幕上时,只显示新闻列表的单面板布局,在大屏幕上时,在屏幕的左边显示列表,在屏幕的右边显示选中的新闻的具体内容 的双面板布局,如下:
res/layout/main.xml: 单面板布局
res/layout-large/main: 多面板布局
res/layout-sw600dp/main: 多面板布局
其中后两个文件是一样的,只是第二个是为了适配Android 3.2设备,第三个是为了适配版本较低的Android设备的。为了避免这种重复出现的布局文件,影响我们的维护,我们可以使用别名文件,例如:
res/layout/main.xml,单面板布局
res/layout/main_twopanes.xml,双面板布局
我们同时在layout下创建两个布局。如果有些经验的Androider,应该知道我们一半引用不同分辨率的资源,都会在不同values文件夹下,例如:values-hdpi;那么这里我们也会用类似的方法来饮用不同的布局。
首先我们引用普通的布局,也就第一个单面板布局。
在res/values/下创建layouts.xml
@layout/onepane
然后我们引用大屏的布局
在res下创建values-sw600dp文件夹,然后在该文件夹下创建layouts.xml:
@layout/main_twopanes
类似的我们创建values-large/layout.xml
@layout/main_twopanes
后两个文件内容相同,我们只是给main在不同的分辨率下的布局设置了一个别名。只要我们在引用布局的时候引用的是 “main”,设备就会动态的根据屏幕的分辨率去加载不同的布局。
屏幕方向限定符
上面我们只是限定了屏幕的大小,但是我们手机的横竖屏显示的内容也千差万别,如何限制在不同分辨率下的横竖屏的显示布局呢?Android给我们提供了屏幕方向限定符:
限定符
功能介绍
land
横屏,它可以跟尺寸限定符一起使用,例如 values-sw600dp-land
port
竖屏,它可以跟尺寸限定符一起使用,例如 values-sw600dp-port
类似的我们创建以下文件:
res/values/layouts.xml:
@layout/onepane_with_bar
false
res/values-sw600dp-land/layouts.xml:
@layout/twopanes
true
res/values-sw600dp-port/layouts.xml:
@layout/onepane
false
res/values-large-land/layouts.xml:
@layout/twopanes
true
res/values-large-port/layouts.xml:
@layout/twopanes_narrow
true
当我需要显示两个面板的时候,我们在Activity 的onCreate方法中,就可以去判断
““java
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 (getResources().getBoolean(R.bool.has_two_panes)) {
finish();
return;
}
...
}
““
它的使用跟尺寸限定符类似,如果想细究请参看支持各种屏幕尺寸
使用 9Patch
相信很多人都会多少知道这个工具,它会将png的某些部分进行拉伸,这样我们可以使用小一些的图片拉伸以实现大图片实现的效果。
这个工具在/SDK 安装目录/sdk/tools/ 目录下,全名叫做:draw9patch。只要双击既可以启动,我们把需要拉伸的图片直接拖进去就OK,就像下图:
左边为原图,右侧为拉伸后的显示效果;而左边图上的黑线是用来指示我们拉伸区域。虽然我们看来那些在图片边界的上的黑线很粗,其实它们只有1px,我们看到的是放大后的结果,在我们应用中,我们是看不到的。下面我们说一下,黑色色条的作用。
黑线位置
作用
左边和上边
代表拉伸的区域
右边和下边
代表padding区域,如果这张图作为控件的背景,如果控件需要显示文字等内容,则都是在右边和下边黑线标出的交叉区域,它的功能就是控件的padding属性
下图是对应的拉伸区域, 左侧是拉伸和padding区域,右侧为显示效果:
这里指示简单做个示例,有什么不明白的可以去问度娘或谷歌。
另外附上常见的尺寸限定符:
屏幕配置
限定符值
介绍说明
smllestWidth(最小宽度)
swdp:中间的N代表最小的宽度值,例如我们上面写过的sw600dp,其它例子:layout-sw700dp,vaues-sw800dp
当屏幕的最小尺寸为我们设置的N时,系统就会去加载带有该后缀的文件夹下的相关的文件资源。例如:我们上面设置的layout-sw600dp,如果这个文件夹下的布局要显示到屏幕上,那么我们的屏幕的最小尺寸在任何时候都至少是600dp,不管这个600dp是屏幕的宽还是高。也就是说 当你所有屏幕的最小宽度都大于600dp时,屏幕就会自动到带sw600dp后缀的资源文件里去寻找相关资源文件
可用屏幕宽度
wdp:类似上面的swdp.例如:layout-w600,values-w800
它的功能跟上面的相似。 带这样后缀的资源文件的资源文件制定了屏幕宽度的大于Ndp的情况下使用该资源文件,但它和swdp不同的是,当屏幕横向纵向切换时,屏幕的宽度是变化的,以变化后的宽度来与N相比,看是否使用此资源文件下的资源。
可用的屏幕高度
hdp:类似上面的wdp.例如:layout-h600,values-h800
这个后缀的使用方式和wdp一样,随着屏幕横纵向的变化,屏幕高度也会变化,根据变化后的高度值来判断是否使用hdp ,但这种方式很少使用,因为屏幕在纵向上通常能够滚动导致长度变化,不像宽度那样基本固定,因为这个方法灵活性不是很好,google官方文档建议尽量少使用这种方式。
本文参考以下文章:
Android官方文档:适配多种屏幕