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

书接上回,我们已经了解了一些关于适配的一些相关概念,接下来我们会了解一下,在设置布局时我们应该注意的地方。

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

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

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。

艺术般的波浪点击反馈效果 - 2016-07-24 17:07:27

Material Design之Rippledrawable 使用与简单封装(向下兼容至selector) 前言 Android 5.0问世以来,谷歌所推崇的Material Design得到业界的一致好评,其良好的UI规范与交互确实让界面交互友好和漂亮了不少,Rippledrawable便是其中之一,本博客今天着重讲如何将它运用到我们自己的项目中,并且封装得简单易用。 我们都知道,我们在之前做按钮或者布局的反馈效果,一般都用selector来实现,分别指定按下或正常状态的两种颜色即可,我们点击的效果也本
ubuntu环境 首先确定是否安装了Git管理工具 sudo apt-get install git 我选择SSH方式,比较安全方便,只需一次配置 1- 使用ssh命令连接github.com的SSH服务,登录名为git@github.com(所有GitHub用户共享此SSH用户名)。 wangxiong @Dell :~/Public/GitHubRepository/PaPaPlayer $ ssh - T git @github .com The authenticity of host 'gith
         每次看到iOS的远程消息推送,总是感觉很头大,即便后来项目都做完了,还是觉得摸不着远程推送的脉门,网上介绍的资料虽多,但不是写的太简单了,就是写的太详细了,不能一下抓住要点,今天终于能够抽出点时间,来扒一扒这其中究竟有怎样的奥秘。     根据苹果掌控一切的习惯,消息推送也当然不能例外,不论你在哪里推送,也不论你用什么方式推送,都必须首先把消息发给苹果的消息推送服务器APNs(Apple Push Notification Service),然后再由APNs发给指定的设备,也就是说消息推
Day02 Html、Css实战和WebView实现手机显示网页 1.html与css实战 1.1 程序猿小网页 先来看一下效果图 编程用图如下 实现代码如下 !DOCTYPE htmlhtml head meta charset="utf-8" title/title style #pic{ position: relative; float: left; } #text{ width: 400; height: 200; position: relative; float: left; font-si
前言 或许你知道了jni的简单调用,其实不算什么百度谷歌一大把,虽然这些jni绝大多数情况下都不会让我们安卓工程师来弄,毕竟还是有点难,但是我们还是得打破砂锅知道为什么这样干吧,至少也让我们知道调用流程和数据类型以及处理方法,或许你会有不一样的发现。 其实总的来说从java的角度来看.h文件就是java中的interface(插座),然后.c/.cpp文件呢就是实现类罢了,然后数据类型和java还是有点出入我们还是得了解下(妈蛋,天气真热不适合生存了)。 今天也给出一个JNI动态注册native方法的例子

Android渐变标题栏的实现 - 2016-07-24 14:07:56

Android4.4以上推出了Toolbar,改变程序的style属性就可以给手机的标题栏填充颜色,可以是你设置好的系统的主题色,也可以是自己填充的颜色,其实这个效果在iOS早就有了,但在Android中还是很少见的。在iOS中,最常见的Navigationbar的效果就是一个转场动画(多出现于两个界面切换的时候),一个就是随着手势滑动背景渐变(多出现于详情页)。今天我们就来实现下大多出现于详情页的这个渐变效果的标题栏。 具体效果见: 点击打开链接 接下来我们就来实现这个效果。 首先,我们要先把手机上面的
这一篇,承接地八话。使用高效的方式备份短信——xml序列化器。 存储短信,要以对象的方式存储。首先创建javabean: package com.itydl.createxml.domain;public class Message {private String body;private String date;private String address;private String type;public String getBody() {return body;}public void setB

android独特的天气预报 - 2016-07-24 14:07:50

android独特的天气预报 package com.dchan.myweather;import java.io.UnsupportedEncodingException;import java.net.URLEncoder;import java.security.PublicKey;import java.util.ArrayList;import java.util.Calendar;import java.util.Collection;import java.util.HashMap;impo

cocoapods的安装和使用 总结 - 2016-07-24 14:07:48

一、CocoaPods 是什么? CocoaPods 是开发 OS X 和 iOS 应用程序的一个第三方库的依赖管理工具。利用CocoaPods,可以定义自己的依赖关系 (称作 pods),并且随着时间的变化,以及在整个开发环境中对第三方库的版本管理非常方便。 CocoaPods 背后的理念主要体现在两个方面。首先,在工程中引入第三方代码会涉及到许多内容。针对 Objective-C 初级开发者来说,工程文件的配置会让人很沮丧。在配置buildphases和linker flags过程中,会引起许多人为因
最近有一段时间没写博客了,一方面是工作比较忙,一方面也着实本人水平有限,没有太多能与大家分享的东西,也就是在最近公司要做一个抢红包的功能,老板发话了咋们就开干呗,本人就开始在网上收集资料,经过整理和实践,总算完美实现了功能,这里拿出本人一点微薄的成就与大家分享。 首先界面是这样的 开启自动抢红包只需点击相应的选项即可,下面我们进入正题,实现自动抢红包的原理,其实是借助android下的一个辅助服务AccessibilityService,这个服务是google公司为许多Android使用者因为各种情况导致