之前在做一个Android项目时遇到了这样一个需求,要求屏幕上的内容是基于2*4动态排版的,其中相连的小块可以随机合并或不合并,用户每次打开这个界面时看到的界面布局都不一样,大概类此下面这样的草图:
一开始的想法是按照传统的方式,为该页面准备多个布局,在程序运行时随机选择一个布局文件,可是掐指一算,这种2*4的布局可以衍生出来的版面有好几十种,显然这种思路不太靠谱。所以,考虑在程序中用代码来实现动态排版。
现在要解决的问题是,图中的每一小块都代表着一个ViewGroup对象,这些ViewGroup对象中又包括文字图片等信息,那么这些ViewGroup如何像上面那样填充在父容器中呢?没错,只要知道了每一个ViewGroup对象的坐标和尺寸,就可以将它“摆”到窗口上,所以问题回到了如何确定每一个ViewGroup的坐标和尺寸的问题上了。
为了确定每一个ViewGroup的坐标和尺寸我们可以通过算法来“切割”屏幕,为了简化我们的操作,在这里借助一个自定义的抽象“屏幕”类:Screen,它封装了坐标和尺寸信息,这个类的结构如下:
public class Screen {
private int x; // 所对应的屏幕小块左上角的X轴坐标
private int y; // 所对应的屏幕小块左上角的Y轴坐标
private int width; // 所对应的屏幕小块的宽度
private int height; // 所对应的屏幕小块的高度
public Screen() {
super();
}
public Screen(int x, int y, int width, int height) {
super();
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
这样我们把整个屏幕抽象成一个Screen,我们只要根据需求,通过算法来“切割”这个Screen对象即可,这样会比直接操作ViewGroup更直观,更简洁,通过算法“切割”出来每一小块也是一个Screen,里面都封装好了坐标和尺寸信息,把这些Screen对象保存到一个集合中,每一个Screen都对应了一个ViewGroup,我们在构造ViewGroup对象时可以通过对应的Screen对象来指定它的长宽信息,它居左和居上的距离则由Screen的坐标来决定,这样就可以固定它在屏幕上的位置了。当所有的ViewGroup构造完成并添加到父容器中时就会得到类似上图所示的效果。
以上思路的核心是:不是直接操作屏幕的容器对象,而是以抽象的Screen为中介,先将屏幕“切割”为我们需要的小块,再以这些小块封装的信息为基础构造ViewGroup。