Android开发

您所在的位置:网站首页 ui设计图片排版 Android开发

Android开发

2024-03-01 07:22| 来源: 网络整理| 查看: 265

介绍 效果展示

单张图片 两张图片 9张图片

说明

上面的图片排版 - 实现了动态布局,针对不同图片的数量展示不同的排版布局。效果类似微信朋友圈的图片排版,效果略有不同。 - 正方形的图片控件,高度会随着宽度一起变化。

实现这样的布局有很多种思路,只是什么样的方式更优雅。本文提供一种相对优雅的方式供大家参考。

思路 首先,优雅的方式肯定不是定义多种的布局,然后根据图片数量,判断显示那种布局。这样的代码不优雅。其次,也没有必要得到屏幕宽度或者父控件宽度,根据数量计算图片的宽高,然后代码调整子控件宽高。

针对上文提到的两个方面,分别的应对是:

动态代码生成控件填充。父控件宽度固定高度动态,然后子控件宽度根据Weight权重进行均分。 代码 GridLayout

Android系统控件中,GridLayout(网格布局)能够轻松的实现上文的功能需求。

先上代码:

代码说明:

这里为了向下兼容使用的是v7support包中的GridLayout,所以使用到有关的参数配置是app:开头的。排版的关键在与app:columnCount="列数"定义了列数,这样子控件就会自动换行到下一行。(行数 app:rowCount=”行数”这里没有使用到)最关键的在于子控件的 app:layout_columnWeight="1",设置在列(水平方向上)上的权重。每个子控件都是1,这样就会当子控件数量为1时占满父控件,当数量为2时二等分,数量为3时三等分,3以上时占据下一行的三分之一。 特别说明:0dp

GridLayout的权重分配策略和LinearLayout是一样的。所以这就涉及到LinearLayout设置layout_weight时,使用layout_width(或者layout_height)的设置问题和相关的LinearLayout绘制性能问题,具体原因就自行google。 直接给出结论:

Use a layout_width (layout_height)of 0dip instead of match_parent(wrap_content) for better performance 翻译:使用0dp会有更好的性能。(而且这样权重才是正真的,子控件weight值 / 父控件LinearLayout内所有控件的weight值的和)

所以上面的xml布局文件中:所有的子控件应该这写:

正方形控件

前文提到:

正方形的图片控件,高度会随着宽度一起变化

刚才的 app:layout_columnWeight="1"已经能得到动态的控件宽度。想要正方形的图片控件,相信大家很容易就想到类似的代码:

imageView.getLayoutParams().height=imageView.getLayoutParams().height;

直接把宽赋值给高。 其实这是也是一个大坑。如果直接运行上面代码,结果不会如你所愿。 stackoverflow上有一个很好的问题 getWidth() and getHeight() of View returns 0会告诉你答案。

反正从stackoverflow上得知,你想要得到已经配置好的View控件宽度。需要写上一些繁琐但是很有必要的代码。 比如这样:

final View view=//smth; ... view.post(new Runnable() { @Override public void run() { view.getHeight(); //height is ready } });

其实如果只是需要正方形,我有更好的解决方案:重写控件onMeasure()方法

/** * Created by 李可乐 on 2016/10/16 0016. * 正方形ImageView * 重写onMeasure方法 传入widthMeasureSpec宽作为heightMeasureSpec高 */ public class SquareImageView extends ImageView { public SquareImageView(Context context) { super(context); } public SquareImageView(Context context, AttributeSet attrs) { super(context, attrs); } public SquareImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //高度就是宽度值 super.onMeasure(widthMeasureSpec, widthMeasureSpec); } }

代码虽然多,但是很思路简单,很容易理解。不再赘述。

最终XML布局

通过上文各种说明,所以最终xml布局文件应该这样写:

这样的固定xml布局已经实现了本文的基本思路。哪说好的动态添加。

动态添加

在xml布局文件中其实GridLayout已经帮我们安排好了子控件排版顺序。如果是动态添加的,就需要我们自己控制子控件的排版顺序。以及刚才说明的0dp问题。

/** * 动态添加控件 * * @param imageModels 图片集合 */ public void updateViewGroup(ArrayList imageModels) { gridlayoutPost.removeAllViews();//清空子视图 防止原有的子视图影响 int columnCount=gridlayoutPost.getColumnCount();//得到列数 int marginSize = PixelUtils.dp2px(mContext, 4);//得到经过dp转化的margin值 //遍历集合 动态添加 for (int i = 0, size = imageModels.size(); i < size; i++) { GridLayout.Spec rowSpec = GridLayout.spec(i / columnCount);//行数 GridLayout.Spec columnSpec = GridLayout.spec(i % columnCount, 1.0f);//列数 列宽的比例 weight=1 ImageView imageView = new SquareImageView(mContext); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); //由于宽(即列)已经定义权重比例 宽设置为0 保证均分 GridLayout.LayoutParams layoutParams = new GridLayout.LayoutParams(new ViewGroup.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT)); layoutParams.rowSpec=rowSpec; layoutParams.columnSpec=columnSpec; layoutParams.setMargins(marginSize, marginSize, marginSize, marginSize); gridlayoutPost.addView(imageView, layoutParams); } }

说明:

columnCount列数,其实可以根据图片集合的数量,再动态设置,如果为2的倍数时,gridlayoutPost.setColumnCount(2),就可以实现类似微信的效果,4图为2行2列。rowSpec/columnSpec 分别是行/列配置对象,这里调用的时静态方法得到对象,其实源码中有很多的参数配置。这里分别用(除/模)得到子控件的(行/列)索引值,简单的数学就不用再说什么了。

关于Java代码动态添加View的性能 起初感觉相比Xml文件就定义好的视图树关系,我们手动的addView构造视图树可能会增加消耗。但是从LayoutInflater核心视图加载类来看,xml视图文件最终形成View对象和视图树关键还是: 1:反射得到View对象(内部维护构造函数的缓存) 2:addView把View对象添加到父ViewGroup中,也是一次次的add添加。 所以可以放心大胆的使用Java代码添加View对象。

总结 本文旨在合理的使用系统控件GridLayout搭配简单的自定义控件,优雅的实现动态图片排版。思路简单清晰,代码优雅简洁。类似的网格形式布局google推出FlexboxLayout流式布局控件也同样可以实现。本文各链接地址需自备梯子。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3