在一个简单的例子讲讲在Android开发中构建布局建造者一文中我们说到了使用建造者模式对一系列预定的布局视图进行线性布局的填充,但是这里面有一个问题:在这个例子中,我们只是处理了文本,而不适合嵌套布局。这种其实并不是一个泛用性特别大的动态填充布局,而要使动态填充布局真正有用,就需要一个能在布局层次结构的任意级别上添加任意类型的小部件或者视图,也就是应用到了我们这次要讲的组合模式构建布局。
简单说来就是,之前的建造者模式构建布局是以一种线性的方式工作,一次添加一个对象,而我们这次要用的组合模式既可以添加对象组,也可以添加单个对象,并且客户端可以使用完全相同的代码去添加单个布局或者一组布局。
来看一下我们最终需要完成的效果,如下图所示:
这里简单做个分解,最上面的题图和Headline文字为一组,中间的三张图片和背景色为一组,下面的fate/stay night和购物车图片为一组,按照这个思路我们来进行这个界面的动态布局填充开发。
①创建一个接口,这个接口既可以代表单个组件,也可以代表一组组件。
interface Component {
fun add(component: Component)
fun setContent(id:Int)
fun inflate(layout:ViewGroup)
}
②创建接口的实现类。
a.第一组含有题图和Headline文字,所以需要创建ImageView分支和TextView分支。因为是单个组件,所以add方法不用管它,放着就行了。在setContent()方法中来控制组件外观,之所以选择资源ID而不是其他作为参数传入,是因为这样在图像和文本我们都可以使用相同的int参数,并且可以达到解耦的作用。
class ImageLeaf(private var imageView: ImageView, id: Int):Component {
init {
setContent(id)
}
override fun add(component: Component) {
}
override fun setContent(id: Int) {
imageView.scaleType = ImageView.ScaleType.FIT_CENTER
imageView.layoutParams = ViewGroup.LayoutParams(dp(137),dp(110))
imageView.setPadding(5,5,5,5)
imageView.setImageResource(id)
}
override fun inflate(layout: ViewGroup) {
layout.addView(imageView)
}
//将px转换为dp
private fun dp(px:Int):Int{
val scale = imageView.resources.displayMetrics.density
return (px*scale+0.5f).toInt()
}
}
class TextLeaf(private var textView: TextView, id: Int) :Component{
init {
setContent(id)
}
override fun add(component: