Android详解4种基本布局

新建UILayoutTest项目,并让Android Studio自动帮我们创建好活动,活动名和布局都使用默认值

线性布局

LinearLayout又称线性布局,是一种非常常用的布局

android:orientation属性用来指定线性布局的排列方式,有2个可选值:horizontalvertical ,分别表示水平排列和垂直排列,若不指定,则默认是horizontal

下面我们来实践一下,修改activity_main.xml中的代码,如下所示

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="horizontal">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 1"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 2"/>

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button 2"/>

</LinearLayout>

需要注意的是如果 LinearLayout 的排列方式是horizontal,则内部控件的宽度layout_width就不能指定为match_parent,因为这样的话控件会占满屏幕,其它控件就没有位置可以放下了。同样的,如果排列方式是vertical,则内部控件的高度 layout_height 不能指定为match_parent

运行效果如下图所示

image

下面来学习android:layout_gravity属性,这个跟android:gravity很相似,它们的区别是:android:gravity是指文本在控件中的对齐方式,android:layout_gravity是控件在布局中的对齐方式。

android:layout_gravity的可选值和android:gravity差不多,但是需要注意的是LinearLayout排列方式是horizontal时,只有垂直方向上的对齐方式才会生效,因为此时水平方向上的长度是不固定的,每添加或减少一个控件,水平方向上的长度都会改变,因而无法指定水平方向上的对齐方式。同理,当LinearLayout的排列方式vertical时,只有水平方向上的对齐方式才会有效

修改activity_main.xml中的代码,如下所示

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="horizontal">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:text="Button 1"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:text="Button 2"/>

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:text="Button 2"/>

</LinearLayout>

因为此时LinearLayout的排列方向是horizontal,所以里面的Button控件只能指定垂直方向上的排列方向,重新运行程序,效果如下所示

image

接下来我们来学习android:layout_weight,这个属性允许我们以比例的方式来指定控件的大小,在手机屏幕的适配方面起到了非常重要的作用。

修改activity_main.xml中的代码,如下所示

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="horizontal">

    <EditText
        android:id="@+id/input_message"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        />

    <Button
        android:id="@+id/send"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Send"/>

</LinearLayout>

这里android:layout_width都指定成了0dp,那么文本编辑框和按钮还能显示出来吗?答案是肯定的,因为我们这里使用了android:layout_weight属性,这时的控件宽度将不再由android:layout_width决定,这里指定成android:layout_width="0dp" 是一种比较规范的写法。另外dp是Android中用来作为控件大小、间距等属性的单位。

我们这里EditText和Button元素中的 android:layout_weight 都指定为1,意思是EditText和Button平分屏幕的水平宽度。

控件所占的比例是这么算出来的:系统会将LinearLayout下的所有控件的 android:layout_weight 值相加得到一个总值,每个控件所占的比例就是该控件的android:layout_weight值除以这个总值得到的

我们还可以通过指定部分控件的android:layout_weight值来实现更好的效果,修改activity_main.xml中代码,如下所示

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="horizontal">

    <EditText
        android:id="@+id/input_message"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:hint="Type something"
        />

    <Button
        android:id="@+id/send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Send"/>
    
</LinearLayout>

这里仅指定了EditText的android:layout_weight属性,Button的android:layout_width改为了wrap_content,这时Button的宽度仍然是按照wrap_content来计算,而EditText则会占满屏幕所剩余的空间。这种编程方式,不仅在各种屏幕的适配方面非常好,而且看起来也更加舒服。

重新运行程序,效果如下所示

image

相对布局

RelativeLayout又称相对布局,也是一种非常常用的布局。

我们直接来体验一下,修改activity_main.xml中的代码,如下所示

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="Button1"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:text="Button2"/>

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Button3"/>

    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:text="Button4"/>

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:text="Button5"/>

</RelativeLayout>

以上代码不需要过多的解释,因为它们实在太好理解了。android:layout_alignParentLeftandroid:layout_alignParentTopandroid:layout_alignParentRightandroid:layout_centerInParentandroid:layout_alignParentBottom这几个属性我们之前没有接触过,但是它们的名字已经完全说明了它们的作用。

重新运行程序,效果如图所示

image

上面的例子是控件相对于布局定位的,那么控件能否相对于控件进行定位呢?当然是可以的。下面我们就来实践一下,修改activity_main.xml中的代码,如下所示

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="Button3"/>

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/button3"
        android:layout_toLeftOf="@id/button3"
        android:text="Button1"/>

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/button3"
        android:layout_toRightOf="@id/button3"
        android:text="Button2"/>
    <Button
        android:id="@+id/button4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/button3"
        android:layout_toLeftOf="@id/button3"
        android:text="Button4"/>

    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/button3"
        android:layout_toRightOf="@id/button3"
        android:text="Button5"/>
    
</RelativeLayout>

android:layout_above属性可以让一个控件位于另一个控件的上方,需要为这个属性指定相对控件id的引用,这里我们填入@id/button3,表示该控件位于Button3的上方。android:layout_below属性则是让一个控件位于另一个控件的下方。android:layout_toLeftOfandroid:layout_toRightOf 则分别表示让一个控件位于另一个控件的左侧和右侧

当一个控件去引用另一个控件的id时,该控件一定要定义在引用控件的后面,否则会出现找不到id的情况。重新运行程序,效果如图

image

帧布局

FrameLayout又称作帧布局,它比前面两种布局就简单太多了,应用场景也比较少。没有方便的定位方式,所有的控件默认放在布局的左上角。

下面我们通过例子来看看吧,修改activity_main.xml中的代码,如下所示

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

<TextView
    android:id="@+id/text_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="This is TextView"
    />

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"
        />
    
</FrameLayout>

FrameLayout中只放置了TextView和ImageView,需要注意的是,当前项目中我们并没有准备任何图片,所以这里ImageView直接使用了@mipmap来访问ic_launcher这张图,虽然这种用法的场景很少,但是却是完全可行的。重新运行程序,效果如图所示

可以看到,文字和图片都是位于布局的左上角,因为ImageView是在TextView之后添加的,所以图片压在了文字上面。我们可以通过 android:layout_gravity 来指定控件在布局中的对齐方式

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

<TextView
    android:id="@+id/text_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="This is TextView"
    android:layout_gravity="left"
    />

    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_launcher"
        android:layout_gravity="right"
        />
    
</FrameLayout>

我们指定了TextView左对齐,ImageView右对齐。重新运行程序,效果如下图所示

image

百分比布局

百分比布局可以直接指定控件在布局所占的百分比。由于LinearLayout本身已经支持按比例指定控件的大小了,因此百分比布局只对FrameLayout和RelativeLayout这两个布局进行了功能扩展,提供了 PercentFrameLayoutPercentRelativeLayout 这两个全新的布局

下面我们直接来实践一下吧,因为百分比布局属于新增布局,所以我们需要在项目的build.gradle中添加百分比布局库的依赖。

打开app/build.gradle文件,在dependencies闭包中添加如下内容:

    implementation 'androidx.percentlayout:percentlayout:1.0.0'

需要注意的是,每当修改了任何的gradle文件,Android Studio都会有如下图所示的提示

image

这个提示告诉我们,gradle自上次同步以后又发生了变化,需要再次同步才能让项目正常工作。这里只需要点击Sync Now就可以了,然后gradle会开始同步,把我们新添加的百分比布局库引入到项目当中。

接下来修改activity_main.xml中的代码,如下所示

<?xml version="1.0" encoding="utf-8"?>
<androidx.percentlayout.widget.PercentFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

  <Button
      android:id="@+id/button1"
      android:text="Button 1"
      android:layout_gravity="left|top"
      app:layout_widthPercent="50%"
      app:layout_heightPercent="50%"
      />

    <Button
        android:id="@+id/button2"
        android:text="Button 2"
        android:layout_gravity="right|top"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />

    <Button
        android:id="@+id/button3"
        android:text="Button 3"
        android:layout_gravity="left|bottom"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />

    <Button
        android:id="@+id/button4"
        android:text="Button 4"
        android:layout_gravity="right|bottom"
        app:layout_widthPercent="50%"
        app:layout_heightPercent="50%"
        />
</androidx.percentlayout.widget.PercentFrameLayout>

最外层我们使用了PercentFrameLayout,由于百分比布局并不是内置在系统SDK当中的,所示需要把完整的包路径写出来。然后必须定义一个app的命名空间,这样我们才能使用百分比布局的自定义属性。

使用 app:layout_widthPercent 属性将各按钮的宽度指定为布局的50%,使用 app:layout_heightPercent 属性将各按钮的高度指定为布局的50%。这里之所以能使用app前缀是因为我们刚才定义了app的命名空间,这跟我们一直能使用android前缀是一样的道理。

不过PercentFrameLayout还是继承了FrameLayout的特性,即所有的控件默认摆放在布局的左上角,为了让控件不重叠。我们这里借助了android:layout_gravity属性来分别把这4个按钮放在了左上,右上,左下,右下4个位置。

重新运行程序,效果如下图所示

image

PercentFrameLayout的用法就介绍到这里,另外一个 RelativeFrameLayout 的用法也是非常的相似,它继承了RelativeLayout的所有属性,也可以使用 app:layout_widthPercentapp:layout_heightPercent 来指定控件的宽高。相信聪明的你一定可以举一反三,这里就不再做详细的介绍了。当然Android的布局不止这些,由于应用的比较少,所以就不再一一举例了,如果你感兴趣的话可以自行去了解。

内容参考自《第一行代码》

github代码

码云代码

个人网站:www.panbingwen.cn

公众号.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,511评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,495评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,595评论 0 225
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,558评论 0 190
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,715评论 3 270
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,672评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,112评论 2 291
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,837评论 0 181
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,417评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,928评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,316评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,773评论 2 234
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,253评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,827评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,440评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,523评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,583评论 2 249

推荐阅读更多精彩内容

  • 001自打93年父母创建了我,便日夜辛苦的想将我培养成为一个硬盘。各种软件、文件,也不管什么兼容性,通通的复制过来...
    赤耳113阅读 384评论 0 0
  • 今天是小儿横穿中国的第四天了,已经走过三个省份,每天看着他们来自前方的播报,看着他们开心的玩着、学习着真是高兴。 ...
    走读生日志阅读 470评论 0 14
  • 有些人在我生命中留下足迹,却转身离去。 那年春天,我因为看多了书而近视,父母转遍了整个城市为我寻找治愈近视的方式,...
    墨雨无声阅读 130评论 0 0
  • 总有个人,他或她就像是一首唱到沙哑的,却依旧偏爱的歌,让人。。。。。。 1. 是啊,你Wifi在线了,应该是起床了...
    陌人陌言JShu阅读 1,329评论 1 0
  • 再次奔波。终于初步完成基本的手续。这才是刚开始。真没有想到会是这样的麻烦!好在各处都还顺利,各个部门并未一丁点为难...
    彧之阅读 748评论 1 1