文档章节

UI界面布局容器与布局策略概述

炽火
 炽火
发布于 2017/09/02 09:16
字数 2967
阅读 88
收藏 0

本文描述了UI界面的容器与布局策略。主要从理论角度论述原理和实现思路,并包含一些容器的样例贴图。

本文写于2016年2月,现发布于博客和大家分享。原文是工作需要做的研究,博客基于原始草稿,并做了一定删减和增补。

UI界面的基本组成单位是UI元素,容器是用于容纳多个子元素的组件。布局实际上是一种算法策略,用于计算子元素在容器中的位置排列。

布局管理器用于管理容器布局策略,有两种实现方式:

  • 每种布局策略实现特定容器
  • 容器可以指定不同的布局策略(例如Swing)

一种常用的设计是每种布局对应一个容器,好处就是入门门槛低,容易上手,但容易造成仅仅为了布局的容器堆叠。而让容器可以指定不同布局策略是一种灵活的实现方式,但是使用起来比较繁琐。对于一个成熟产品来说,同时提供可以自由指定布局策略的容器,同时提供常用的布局容器,是一种比较好的方案。

对于复杂界面来说,容器嵌套层次太多容易造成冗余的布局调用,随着嵌套层次的增加而减低布局效率。扁平化容器层级能够提高界面布局效率。如何减少容器组合的嵌套层级?可以考虑将一些常用的嵌套方案,封装为一个固定的组合布局容器。

布局策略 Layout Policy

布局策略可以抽象为5种基本类型:

  • Coordinate Based 基于坐标
  • Constraint Based 基于约束
  • Linear 线性
  • Layered 分层
  • Grid 网格

基于坐标的布局策略 Coordinate–Based

这是最基本的布局策略,子元素可以用Bounds(Location和Size)来决定在容器中的显示边界(Boundary)。

基于约束的布局策略 Constraint-Based

这是一种相对定位的布局策略,对子元素设置约束条件,当容器变化时,子元素的边界遵循约束发生变化。

  • Relative Positioning 相对定位 设置元素的left, top, right, bottom相对父容器的位置。例如Java的SpringLayout。

  • Anchor Points 锚点 一个界面元素具有9个锚点:上、下、左、右、中心、左上、右上、右下、左下。当设置了元素的Bound边界后,元素可以定位在容器中。此时,可以指定一个或多个锚点,则当容器边界变化时,元素的锚点保持相对位置不变,单个锚点可以让元素跟随容器平移,多个锚点可以让元素跟随容器的改变而平移+缩放。

  • Dock 停靠 元素可以停靠在容器的指定位置上,共有上下左右中五个位置。Dock和Anchor是WinFrom的基本布局策略。Dock布局是Anchor的一种简化。在Java里也称为BorderLayout,采用东南西北中来描述五个方位。

  • Guide Lines 参考线。 例如BaseLine、Constraint Row, Constraint Column。同时设置元素的边界相对参考线的位置

线性布局策略 Linear

所有元素沿着一个方向延展。可以派生出横向、纵向、以及可以折行的流式布局等。

这种布局策略简单有效,是界面布局中最常用的布局策略。通过组合可以实现大多数常用的界面布局。

以下容器属于线性布局策略:

  • HBox
  • VBox
  • FlowLayout
  • SpitContainer

在不同的实现中有一些扩展属性,例如flex属性可以指定某个元素自适应,还有指定对齐方式的属性等。

Flow Layout流式布局也是非常常用,在某个方向如果元素抵达边界则自动换行,从而可以多行展示。

分层布局策略 Layered

容器被切分成多个层,每层可以容纳一个或多个元素。有两种分支:

  • Stacking 叠放 每次显示一层,可以在层之间切换,每层的元素大小相同,一般为最大的元素大小。例如CardBox卡片盒容器。

  • Overlapping Overlays 覆盖 同时显示所有层,不同层的元素之间相互覆盖。注意这种覆盖布局,只有顶层元素可以交互,而非顶层元素虽然未被顶层元素遮盖的部分可见,但不响应事件。

以下容器属于此类布局策略类型:

  • CardBox
  • TabNavigator
  • Accordion

卡片盒的行为就像是不带标签页的TabNavigator,当然实现思路有一些差异。

而手风琴则更为特殊一些,老式Windows控制面板有类似例子,后来也是经久不衰,有很多演变。

网格布局策略 Grid

将容器按照行(Row)、列(Column)交叉分割为单元格(Cell),所有元素限制在单元格内,相对单元格对齐。

  • Grid 表格 表格按照Row和Column切分,每个格子大小可以不同,由行来决定高度,由列来决定宽度。元素可以占用一个或多个Cell单元格,通过单元格的RowSpan和ColSpan来定义。

  • Tile 平铺 所有的格子总是大小相同,元素可以占用一个或多个格子。如果元素大小小于单元格,则按照定义对齐(一般是左上角对齐)单元格。平铺策略的单元格大小一般是固定或是自适应的,按照可见视图的所有元素计算出单元格大小,所有单元格保持一致大小。单元格大小确定后,元素再按照对齐定义在单元格内对齐。

容器 Containers

通用容器列表

  • Box (HBox, VBox) 线性布局,横向、纵向
  • DockPanel 停靠布局,上下左右中
  • SplitContainer 分割容器
  • CardBox 卡片盒布局,单页显示
  • Accordion 手风琴布局,单项展开
  • Grid 表格布局
  • ToolBox, ToolBar 工具盒,工具条
  • Absolute 绝对定位
  • Relative 相对定位布局
  • TileLayout 格子布局
  • Scroller 滚动条
  • SideBar 侧边栏,可以折叠
  • Disclosure / Expander (Collapsible Panel) 扩展器,点击展开、收缩的扩展区域
  • Ribbon 带子(参见Office)
  • MenuButton 菜单按钮,点击展开浮动面板

HBox & VBox - Linear 线性布局

线性布局是最常用的布局容器,横向布局使用HBox,纵向布局使用VBox。原理并不复杂,只有几条简单的规则。一个盒子可以将元素布置在两个方向之一,水平或垂直。水平盒子将它的元素进行水平排列,而垂直盒子将它的元素进行垂直排列。

代码示例

<hbox>
  <!-- horizontal elements -->
</hbox>

<vbox>
  <!-- vertical elements -->
</vbox>

<box orient="vertical">

下面例子展示怎么垂直放置三个按钮。示例代码是XUL的布局格式。

纵向并列三个按钮

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>

<window id="vbox example" title="Example"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<vbox>
  <button id="yes" label="Yes"/>
  <button id="no" label="No"/>
  <button id="maybe" label="Maybe"/>
</vbox>

</window>

CSS新的FlexBox - 流式布局

CSS新标准中的FlexBox弹性容器是流式布局的一种完备实现。

输入图片说明

输入图片说明

分割容器 SplitContainer / DividedBox

一般使用一个独立的容器SplitContainer,作为一个预定义的带有分隔条的容器。其中包含两个子元素,并可以指定分隔条的方向。分隔条可以通过鼠标拖拽改变被分隔的两个区域的大小。

BoxSplitter分隔条可以放置在HBox或VBox中,自然显示为一个分隔条。 但要注意,由于线性布局可以放置多个串行元素,如果一个分隔条之后有多个元素,那么必须指定当Splitter调整位置时,哪个元素的大小将自动改变。

卡片盒 CardBox - 层叠容器

  • CardBox 每层称为Card
  • ViewStack 每层称为Frame,
  • PanelManager 每层称为Panel,

层叠容器的典型案例就是向导Wizard,点击下一步、上一步时,内容区域页面切换,同一时间只有一个页面显示。

用CardBox命名比较形象,就像一个名片盒,里面放置一张张名片,放在最上面的卡片可见。Stack原本的含义就是叠放,就像编程语言中的栈集合或栈内存,只能看到最外的一层,里面的所有层次都是在黑盒内不可见。

CardBox使用SelectedItem或SelectedIndex来访问或切换当前展示的卡片。

输入图片说明

典型案例,打印机安装向导。使用上一步、下一步来切换卡片。

输入图片说明

CardBox可以链接到Tab或一组按钮(例如RadioButton Group),点击时一对一直接切换到对应的卡片页面。

输入图片说明

表格布局 Grids / Table

基于行、列的表格布局,可以将元素按格放置。元素也可以跨行、跨列。元素根据跨行、跨列的定义决定占用的边界,在边界内根据对齐和留白的配置决定位置。

Table.Columns.Add(Column column); 
Table.Rows.Add(Row row);

表格单元格,及跨列放置按钮示意图。

输入图片说明

平铺布局 Tile Layout

下图是Flex4的TileLayout示意图。

输入图片说明

下图是一种较为复杂的网格布局,在平铺布局的基础上有所变化,类似Win8开始菜单出现的磁贴(Tiles)布局。

输入图片说明

工具盒 Toolbox, 工具条 Toolbar, 工具按钮ToolButton

一个工具盒可以容纳多个工具条,每个工具条容纳多个工具按钮

输入图片说明

锚点 Anchor Point - 相对布局 RelativeLayout

锚点布局,如图中的红色方块,设置了锚点后,当窗体大小改变时,被锚定的点会跟随拉伸。

输入图片说明

输入图片说明

停靠面板 DockPanel & 边框布局 Border Layout

两种命名方式下的五个区域名称:

  • DockPanel: Top, Right, Bottom, Left, Fill
  • BorderLayout: North, East, South, West, Center

其中,DockPanel与WinForm完美兼容。可以直接使用。

算法:用添加顺序来决定遮盖方向(每次添加时,在剩余区域内切割一块)

输入图片说明

输入图片说明

手风琴 Accordion

属于分层布局策略,每个层有横向页签展示,相互互斥,一次只展示激活的一层。

输入图片说明

带子 Ribbon

这是现代的新的页签复合样式,适合文档型程序。

输入图片说明

侧边栏 SideBar

侧边栏展示页签,高大上。

输入图片说明

扩展器 Disclosure (Expander)

可以展开折叠的区域,折叠后显示标题文本,展开时可以显示一个扩展面板。

输入图片说明

菜单按钮 MenuButton

MenuButton常见与手机界面,一个面包片按钮代表菜单,当点击时滑出菜单。

输入图片说明

圣杯布局 Holy Grail - 组合布局

圣杯布局是一种组合式布局,是扁平化的经典例子。圣杯布局首先是在网页设计上提出的。

输入图片说明

圣杯布局在不同设备(屏幕和手机)上的变化:

输入图片说明

群组容器 Grouping Container

群组容器用于逻辑上聚集一组UI元素,这些UI元素成为群组容器的子,将随着父容器改变位置、随着父容器隐藏显示改变可用性等。

群组容器其实是一个抽象容器,适合作为容器的基类。从抽象意义上来说,大部分容器都是群组容器的具象。但实际上,我们习惯将一种实线矩形框起来的容器称为群组容器。

在Windows中叫做GroupBox分组框控件。

输入图片说明

GroupBox也有很多扩展实现,包括可复选的标题、可折叠的标题等等。从这个意义上来说,手风琴控件可以看作GroupBox的一个派生类。

© 著作权归作者所有

共有 人打赏支持
炽火
粉丝 8
博文 8
码字总数 8893
作品 0
朝阳
高级程序员
私信 提问
【android基础学习之八】——页面布局

声明:学习的书籍《Android应用开发揭秘》,这里记录学习该书籍的日志,引用的相关代码与总结描述,没有商业的用途,完全是自我学习的一个记录,刚刚学习不可避免会出现很多问题,若是有错误...

晨曦之光
2012/03/08
834
0
Android--UI布局

概述   布局(Layout)的概念是针对Activity的,Activity就是布满整个Android设备的窗口或者悬浮于其他窗口上的交互界面。在一个应用程序中通常由多个Activity构成,每个需要显示的Activit...

analogous_love
01/07
0
0
NGUI全面实践教程(大学霸内部资料)

NGUI全面实践教程(大学霸内部资料) 试读文档下载地址:链接:http://pan.baidu.com/s/1jGosC9g 密码:8jq5 介绍:NGUI全面实践教程(大学霸内部资料)本书是国内NGUI最新教程,以全新的3.8...

大学霸
2015/03/31
0
0
2.1 View与ViewGroup的概念

2.1 View与ViewGroup的概念 分类 Android 基础入门教程 本节引言 告别了第一章,迎来第二章——Android中的UI(User Interface)组件的详解, 而本节我们要学习的是所有控件的父类View和Vie...

微笑的江豚
2016/03/21
5
0
Android学习笔记(二) 布局方式的介绍

Android应用的开发的一项内容就是用户界面开发了。Android提供了大量功能丰富的UI组件。Android的界面是由布局和组件协同完成的。 Android所有UI组件都继承了View类,View类有一个重要的子类...

半夏alvin
2014/03/05
0
0

没有更多内容

加载失败,请刷新页面

加载更多

React和Redux的连接react-redux

通过Redux文档来了解react-redux,在一段时间的实践后准备翻一翻源代码,顺便做些相关的总结。我看的代码的npm版本为v4.0.0,也就是说使用的React版本是0.14.x。 react-redux提供两个关键模块...

前端攻城老湿
23分钟前
0
0
1、Mybatis连接池Context.xml配置

注意: (1)mybatis 3.2 之前 通过 set get 方法 获取相关属性。之后通过属性姓名获取相关关联。 (2)mybatis 映射 优先为 sql 语句中的别名与实体类的属性进行映射。 (3)jndi Java用于调...

KingFightingAn
39分钟前
0
0
Android 界面漩涡扭曲动效实现

背景:之前偶然看到优酷有类似的页面切换动画效果。于是自己也打算来实现下这样的效果。 动效说明:点击界面中的任意位置,界面以点击位置作为中心点,开始以漩涡状态,扭曲,收缩。直到消失...

Carlyle_Lee
49分钟前
2
0
聊聊我怎么系统学习Linux技能并快速提高的

聊聊我怎么系统学习Linux技能并快速提高的 随着电子信息科技时代的发展,学会使用计算机在我们的生活中成为了必不可少的一项技能。而作为计算机中的三大操作系统之一的Linux更是饱受计算机爱...

linuxCool
今天
4
0
Android/Java 获取一个byte[]的真实编码,用于解决乱码问题

来源地址:https://blog.csdn.net/qq_31384551/article/details/81627840 一个byte数组,byte[] buf,是由一个字符串转换来的,如何判断字符串使用的是什么编码? Mozilla的一个组件提供了相应...

她叫我小渝
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部