一、布局介绍
这里我们了解下Android的基本视图和布局,Android中的布局和视图都是直接或间接继承类View。所以下面我们从顶层开始介绍。
二、View的基本属性
由于View类是所有布局和视图的基本视图,所以View类具有的属性和方法在控件和布局上都是适用的。
我们找到Android API中的res文件夹下的values文件下下的attrs.xml文件,在该文件中找到<declare-styleable name="View">
该节点,在这个节点下面显示了View可以使用的属性有哪些(这里显示了常用的属性,其他属性在使用时查看):
xml
<!-- 可以使用View的属性或它的任何子类 -->
<declare-styleable name="View">
<!-- 给视图提供一个通用的标识符名称,为后续检索使用,用法有View.findViewById()或者Activity.findViewById(),必须使用资源引用的方式来命名;通常为@+语法创建ID资源;例如android:id="@+id/my_id",后面我们就可以使用findViewById(R.id.my_id)来找到该视图 -->
<attr name="id" format="reference" />
<!-- 和id类似,通过View.getTag()或View.findViewWithTag()检索;建议使用id,因为id更快并且允许编译时的类型检查 -->
<attr name="tag" format="string" />
<!-- 初始水平滚动偏移量,以像素为单位-->
<attr name="scrollX" format="dimension" />
<!-- 初始垂直滚动偏移量,以像素为单位. -->
<attr name="scrollY" format="dimension" />
<!-- 视图背景,可以是资源引用(png图像|9-patch|XML状态列表描述等)或者纯色(#FF000000[黑色]) -->
<attr name="background" format="reference|color" />
<!-- 视图边缘与视图中内容的上右下左之间的距离 以像素为单位;优先于任何与边缘相关的值(paddingLeft,paddingTop, paddinggright, paddingBottom, paddingHorizontal和paddingVertical),不会覆盖paddingStart或paddingEnd。视图的大小包含了内边距,若设置了background则也包含在内 -->
<attr name="padding" format="dimension" />
<!-- 设置左右内边距 以像素为单位 优先于paddingLeft和paddingRight,而不是paddingStart或paddingEnd(如果设置了) -->
<attr name="paddingHorizontal" format="dimension" />
<!-- 设置顶部和底部内边距(以像素为单位) 优先于paddingTop和paddingBottom。 -->
<attr name="paddingVertical" format="dimension" />
<!-- 左内边距 以像素为单位 -->
<attr name="paddingLeft" format="dimension" />
<!-- 顶部内边距 -->
<attr name="paddingTop" format="dimension" />
<!-- 右内边距 -->
<attr name="paddingRight" format="dimension" />
<!-- 底部内边距 -->
<attr name="paddingBottom" format="dimension" />
<!-- 设置起始边缘的填充(以像素为单位) -->
<attr name="paddingStart" format="dimension" />
<!-- 设置结束边缘的填充(以像素为单位) -->
<attr name="paddingEnd" format="dimension" />
......
<!-- 控制视图的初始可见性 -->
<attr name="visibility">
<!-- 在屏幕上可见的;默认值 -->
<enum name="visible" value="0" />
<!-- 不显示,但占用空间 -->
<enum name="invisible" value="1" />
<!-- 完全隐藏 即不显示不占空间 -->
<enum name="gone" value="2" />
</attr>
<!-- 布尔内部属性,用于根据系统窗口(如状态栏)调整视图布局。如果为true,则调整此视图的填充以为系统窗口留出空间。将仅在此视图位于非嵌入活动中时生效 -->
<attr name="fitsSystemWindows" format="boolean" />
<!-- 定义滚动时应该显示哪些滚动条或不显示哪些滚动条 -->
<attr name="scrollbars">
<!-- 不显示滚动条 -->
<flag name="none" value="0x00000000" />
<!-- 仅显示水平滚动条 -->
<flag name="horizontal" value="0x00000100" />
<!-- 仅显示垂直滚动条 -->
<flag name="vertical" value="0x00000200" />
</attr>
<!-- 控制滚动条的样式和位置 -->
<attr name="scrollbarStyle">
<!-- 内部填充和覆盖 -->
<enum name="insideOverlay" value="0x0" />
<!-- 在padding和inset里面 -->
<enum name="insideInset" value="0x01000000" />
<!-- 视图的边缘和覆盖 -->
<enum name="outsideOverlay" value="0x02000000" />
<!-- 视图的边缘和插入 -->
<enum name="outsideInset" value="0x03000000" />
</attr>
<!-- 如果视图将用作滚动容器,则设置此选项 -->
<attr name="isScrollContainer" format="boolean" />
<!-- 定义滚动条不使用时是否淡出滚动条 -->
<attr name="fadeScrollbars" format="boolean" />
<!-- 定义滚动条淡出所需的延迟(以毫秒为单位) -->
<attr name="scrollbarFadeDuration" format="integer" />
<!-- 定义滚动条在淡出之前等待的延迟(以毫秒为单位) -->
<attr name="scrollbarDefaultDelayBeforeFade" format="integer" />
<!-- 设置垂直滚动条的宽度和水平滚动条的高度 -->
<attr name="scrollbarSize" format="dimension" />
<!-- 定义可绘制的水平滚动条 -->
<attr name="scrollbarThumbHorizontal" format="reference" />
<!-- 定义可绘制的垂直滚动条 -->
<attr name="scrollbarThumbVertical" format="reference" />
<!-- 定义可绘制的水平滚动条轨道 -->
<attr name="scrollbarTrackHorizontal" format="reference" />
<!-- 定义可绘制的垂直滚动条轨道 -->
<attr name="scrollbarTrackVertical" format="reference" />
<!-- 定义是否应该始终绘制水平滚动条轨道 -->
<attr name="scrollbarAlwaysDrawHorizontalTrack" format="boolean" />
<!-- 定义是否应该始终绘制垂直滚动条轨道 -->
<attr name="scrollbarAlwaysDrawVerticalTrack" format="boolean" />
......
<!-- 定义此视图是否对单击事件作出反应 -->
<attr name="clickable" format="boolean" />
<!-- 定义此视图是否对长单击事件作出反应 -->
<attr name="longClickable" format="boolean" />
<!-- 定义此视图是否对上下文单击事件作出反应 -->
<attr name="contextClickable" format="boolean" />
......
<!-- 定义视图的最小高度 不能保证视图能够达到这个最小高度(例如:如果它的父布局用更少的可用高度限制它) -->
<attr name="minHeight" />
<!-- 定义视图的最小宽度 不能保证视图能够达到这个最小宽度(例如:如果它的父布局用较小的可用宽度限制它) -->
<attr name="minWidth" />
......
<!-- 在视图的上下文中 当单击视图时要调用的方法的名称 此名称必须对应于一个公共方法 该方法只接受View类型的一个参数 -->
<attr name="onClick" format="string" />
<!-- 定义过度滚动行为。此属性仅在视图可滚动时使用 -->
<attr name="overScrollMode">
<!-- 始终显示超滚动效果 即使内容完全适合可用空间 -->
<enum name="always" value="0" />
<!-- 只有当内容大到足以有意义地滚动时,才显示过度滚动效果 -->
<enum name="ifContentScrolls" value="1" />
<!-- 永远不要显示过度滚动的效果 -->
<enum name="never" value="2" />
</attr>
<!-- 视图的Alpha属性,作为0(完全透明)和1(完全不透明的)之间的值 -->
<attr name="alpha" format="float" />
<!-- 视图的基z深度 -->
<attr name="elevation" format="dimension" />
<!-- 视图x的平移 -->
<attr name="translationX" format="dimension" />
<!-- 视图y的平移 -->
<attr name="translationY" format="dimension" />
<!-- 视图在z上的平移。这个值被添加到它的标高 -->
<attr name="translationZ" format="dimension" />
<!-- 视图将围绕其旋转和缩放的轴心点的X位置 这个xml属性设置视图的pivotX属性 -->
<attr name="transformPivotX" format="dimension" />
<!-- 视图将围绕其旋转和缩放的枢轴点的Y位置 这个xml属性设置视图的pivotY属性 -->
<attr name="transformPivotY" format="dimension" />
<!-- 视图的旋转,以度为单位 -->
<attr name="rotation" format="float" />
<!-- 视图绕x轴旋转,以度为单位 -->
<attr name="rotationX" format="float" />
<!-- 视图绕y轴旋转,以度为单位 -->
<attr name="rotationY" format="float" />
<!-- 视图在x方向上的比例 -->
<attr name="scaleX" format="float" />
<!-- 视图在y方向上的比例 -->
<attr name="scaleY" format="float" />
......
<!-- 定义布局绘图的方向 -->
<attr name="layoutDirection">
<!-- 从左到右 -->
<enum name="ltr" value="0" />
<!-- 从右到左 -->
<enum name="rtl" value="1" />
<!-- 从父母那里继承 -->
<enum name="inherit" value="2" />
<!-- 根据语言环境 -->
<enum name="locale" value="3" />
</attr>
......
<!-- 定义文本的对齐方式 -->
<attr name="textAlignment" format="integer">
<!-- 默认值 -->
<enum name="inherit" value="0" />
<!-- 默认为根视图 -->
<enum name="gravity" value="1" />
<!-- 与段落的开头对齐 -->
<enum name="textStart" value="2" />
<!-- 与段落的末尾对齐 -->
<enum name="textEnd" value="3" />
<!-- 将段落居中 -->
<enum name="center" value="4" />
<!-- 对齐到视图的开始 -->
<enum name="viewStart" value="5" />
<!-- 对齐到视图的末尾 -->
<enum name="viewEnd" value="6" />
</attr>
......
<!-- 主题 -->
<attr name="theme" />
......
</declare-styleable>
三、线性布局
线性布局LinearLayout
是最常用的布局,其中的视图要么从上到下或者从左到右这样线性的排列。我们查看该布局对应的类LinearLayout
其直接继承ViewGroup
,间接的继承View
。类ViewGroup
是一种特殊的视图,可以包含其他视图 (称为子视图)。视图组是布局和视图容器的基类。这个类还定义了ViewGroup.LayoutParams
类,用作布局参数的基类。
线性布局是将其他视图水平排列在单个列中或垂直排列在单个行中的布局。下面的代码段显示了如何在布局XML文件中包含线性布局:
ini
<LinearLavout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:orientation="horizontal"
android:gravity="center">
<!-- 在这里包括其他小部件或布局标签。这些被认为是线性布局的"子视图"或"孩子" -->
</LinearLayout>
线性布局除了通用的属性还具有自己特有的一些属性:
属性名 | 属性值 | 属性说明 |
---|---|---|
android:orientation | horiontal / vertical | 指定线性布局的方向 |
android:gravity | left / right / top / bottom / center / center_horizontal / center_vertical | 指定布局内部视图与本该线性布局的对齐方式 |
android:layout_weight | 浮点数 | 指定当前布局的宽高占用上级线性布局的权重 若设置了权重需要将具体哪个方向的layout_height / layout_width设置为0dp |
四、案例实战
线性布局的默认效果。我们使用不同的背景色来观察布局效果。
1、默认效果,布局占用整个屏幕: 布局宽高继承父布局,根节点的父即为屏幕,背景设置为黑色
ini
<?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"
android:background="#ff000000"
tools:context=".MainActivity">
</LinearLayout>
2、在默认布局下放三个视图:发现水平方向放置,即默认为水平显示
ini
<View
android:layout_height="100dp"
android:layout_width="100dp"
android:background="#FF0000"/>
<View
android:layout_height="100dp"
android:layout_width="100dp"
android:background="#00FF00"/>
<View
android:layout_height="100dp"
android:layout_width="100dp"
android:background="#0000FF"/>
3、将内部视图改为垂直放置:在线性布局上设置android:orientation="vertical"
内部的视图垂直显示
ini
<?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"
android:background="#ff000000"
android:orientation="vertical"
tools:context=".MainActivity">
......
</LinearLayout>
4、设置第一个View不显示但占用空间:
ini
<View
android:layout_height="100dp"
android:layout_width="100dp"
android:background="#FF0000"
android:visibility="invisible"/>
<View
android:layout_height="100dp"
android:layout_width="100dp"
android:background="#00FF00"/>
<View
android:layout_height="100dp"
android:layout_width="100dp"
android:background="#0000FF"/>
4、设置第一个View不显示且不占用空间:
ini
<View
android:layout_height="100dp"
android:layout_width="100dp"
android:background="#FF0000"
android:visibility="gone"/>
<View
android:layout_height="100dp"
android:layout_width="100dp"
android:background="#00FF00"/>
<View
android:layout_height="100dp"
android:layout_width="100dp"
android:background="#0000FF"/>
5、layout_margin / padding的效果
ini
<?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"
android:background="#ff000000"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
android:layout_margin="30dp"
android:padding="30dp"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0000ff"
/>
</LinearLayout>
</LinearLayout>
更多的属性可自行测试。
五、拼多多首页布局
我们先看下拼多多的首页右哪些内容:
界面整体是垂直显示,所以跟节点我们使用垂直布局。在垂直上我们可以将其划分为6大区域块:搜索输入区域、顶部菜单、活动区域、多多买菜及百亿补贴区域、推荐区域、底部菜单。其中顶部菜单可以左右滑动。推荐区域是可以上下滑动的。
我们这里不实现功能只使用现有界面的布局。这里嵌套比较多,在实际开发中并不推荐使用,本案例只为熟悉线性布局和相关属性
ini
<?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"
android:background="#F4F4F4"
android:orientation="vertical"
tools:context=".PinDuoDuoActivity">
<!--这里是顶部搜索区域-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:background="#FFFFFF"></LinearLayout>
<!--顶部菜单区域-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#3A9A8B">
<!--水平方向滚动-->
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#FF8080" />
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#FFFF80" />
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#80FF80" />
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#80FFFF" />
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#0080FF" />
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#FF80C0" />
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#FF80C0" />
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#008080" />
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:background="#004000" />
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3"
android:background="#ABCDEF"></LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4"
android:background="#FEDCBA"></LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="12">
<!--垂直方向滚动-->
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:background="#FF8080" />
<View
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:background="#FFFF80" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:background="#80FF80" />
<View
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:background="#80FFFF" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:background="#0080FF" />
<View
android:layout_width="0dp"
android:layout_height="200dp"
android:layout_weight="1"
android:background="#FF80C0" />
</LinearLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="2"
android:orientation="horizontal">
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#FF0000"/>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#AABBCC"/>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#0000FF"/>
<View
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#CCDDEE"/>
</LinearLayout>
</LinearLayout>