您的位置:首页 > 移动开发 > Android开发

Android屏幕适配之布局设置(二)

2016-07-23 17:24 316 查看
书接上回,我们已经了解了一些关于适配的一些相关概念,接下来我们会了解一下,在设置布局时我们应该注意的地方。

尽量不去设定具体的尺寸值。

为了确保布局适应各种尺寸的屏幕,在保证功能实现的前提下,最好不要写死一些尺寸,这样的硬编码,我们最好使用“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的介绍和使用(一)

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

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


然后我们引用大屏的布局

res
下创建
values-sw600dp
文件夹,然后在该文件夹下创建
layouts.xml
:

<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>


类似的我们创建
values-large/layout.xml


<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>


后两个文件内容相同,我们只是给main在不同的分辨率下的布局设置了一个别名。只要我们在引用布局的时候引用的是 “main”,设备就会动态的根据屏幕的分辨率去加载不同的布局。

屏幕方向限定符

上面我们只是限定了屏幕的大小,但是我们手机的横竖屏显示的内容也千差万别,如何限制在不同分辨率下的横竖屏的显示布局呢?Android给我们提供了屏幕方向限定符:

限定符功能介绍
land横屏,它可以跟尺寸限定符一起使用,例如 values-sw600dp-land
port竖屏,它可以跟尺寸限定符一起使用,例如 values-sw600dp-port
类似的我们创建以下文件:

res/values/layouts.xml
:

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


res/values-sw600dp-land/layouts.xml
:

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


res/values-sw600dp-port/layouts.xml
:

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


res/values-large-land/layouts.xml
:

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


res/values-large-port/layouts.xml
:

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


当我需要显示两个面板的时候,我们在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;
}
...


}

““

它的使用跟尺寸限定符类似,如果想细究请参看支持各种屏幕尺寸

demo下载

使用 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官方文档:适配多种屏幕

Android屏幕适配小技巧swdp
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  布局 适配