介绍

效果展示

说明

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

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

思路

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

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

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

代码

GridLayout

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

先上代码:

 <android.support.v7.widget.GridLayoutandroid:id="@+id/gridlayout_post"android:layout_width="match_parent"android:layout_height="wrap_content"app:columnCount="3"><ImageViewandroid:layout_height="200dp"app:layout_columnWeight="1"tools:src="@android:color/dim_foreground_dark" /><ImageViewandroid:layout_height="200dp"app:layout_columnWeight="1"tools:src="@android:color/dim_foreground_dark" /></android.support.v7.widget.GridLayout>

代码说明:

  1. 这里为了向下兼容使用的是v7support包中的GridLayout,所以使用到有关的参数配置是app:开头的。
  2. 排版的关键在与app:columnCount="列数"定义了列数,这样子控件就会自动换行到下一行。(行数 app:rowCount=”行数”这里没有使用到)
  3. 最关键的在于子控件的 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布局文件中:所有的子控件应该这写:

   <ImageViewandroid:layout_height="200dp"android:layout_width="0dp"//很关键的设置!app:layout_columnWeight="1"tools:src="@android:color/dim_foreground_dark" />

正方形控件

前文提到:

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

刚才的 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() {@Overridepublic 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);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//高度就是宽度值super.onMeasure(widthMeasureSpec, widthMeasureSpec);}
}

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

最终XML布局

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

 <android.support.v7.widget.GridLayoutandroid:id="@+id/gridlayout_post"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="12dp"android:paddingLeft="-4.5dp"android:paddingRight="-4.5dp"app:columnCount="3"><com.zaofeng.ui.SquareImageViewandroid:layout_width="0dp"android:layout_margin="4dp"android:scaleType="centerCrop"app:layout_columnWeight="1"tools:src="@android:color/black" /><com.zaofeng.ui.SquareImageViewandroid:layout_width="0dp"android:layout_margin="4dp"android:scaleType="centerCrop"app:layout_columnWeight="1"tools:src="@android:color/black" /><com.zaofeng.ui.SquareImageViewandroid:layout_width="0dp"android:layout_margin="4dp"android:scaleType="centerCrop"app:layout_columnWeight="1"tools:src="@android:color/black"/></android.support.v7.widget.GridLayout>

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

动态添加

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

 /*** 动态添加控件** @param imageModels 图片集合*/public void updateViewGroup(ArrayList<ImageModel> 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=1ImageView 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);}}

说明:

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

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

总结

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

Android开发-优雅的实现动态图片排版(类似微信图片展示效果)相关推荐

  1. Android开发之调用相机拍照与本地图库选择图片

    引用链接 Android开发之调用相机拍照与本地图库选择图片 Android调用相机实现拍照功能 部分截图 引言 小项目有一个访问相册的需求,在网上查找得到两位大神博客指点,但博客发布时间过旧,难免因 ...

  2. 给 UITextField 添加左侧指示图片(类似微信登录框)

    2019独角兽企业重金招聘Python工程师标准>>> 给 UITextField 添加左侧指示图片(类似微信登录框) 微信登录界面的密码输入框左侧有一个小图标: 这种效果该如何实现 ...

  3. 小红书图片剪裁框架+微信图片选择器+超高清大图预览+图片自定义比例剪裁,支持 UI 自定义、支持跨进程回调

    YImagePicker 项目地址:yangpeixing/YImagePicker 简介: 小红书图片剪裁框架+微信图片选择器+超高清大图预览+图片自定义比例剪裁,支持 UI 自定义.支持跨进程回调 ...

  4. android开发小技巧:实现listview异步加载图片

    2019独角兽企业重金招聘Python工程师标准>>> 针对listview异步加载图片这个问题,麦子学院android开发老师讲了一种非常实用的方法,麦子学院android开发老师 ...

  5. Android开发笔记(一百五十)自动识别验证码图片

    若问目前IT领域最炙手可热的技术方向,必属人工智能(简称AI)无疑.前有谷歌的阿法狗完胜围棋世界冠军柯洁,后有微软小冰出版了诗集<阳光失了玻璃窗>,一时间沸沸扬扬,似乎人工智能无所不能,从 ...

  6. android 仿微信选取相册_Android类似微信图片选择器

    很多项目要用到图片选择控件,每次都要写一大堆逻辑.于是基于图片选择组件(PhotoPicker)封装了一个控件PhotoUploadView.方便简易,一键集成,几句代码就可以添加类似微信的图片选择控 ...

  7. h5 数字变化_前端/h5 D3.js实现根据数据动态更新图形/类似进度实时变化效果

    最近接到一个需求,在满足规则下,实现类似这种展示效果,其实就是用图形反映数据(NK,一种干扰值) 运行后,它其实是不断在动的,每格都可能显示灰色或者彩色 这里一共是10个格子,每格代表一个范围边界,说 ...

  8. 破解微信图片防盗链 微信图片不显示怎么办?

    在页面头部加入: <meta name="referrer" content="never"> <meta name="referr ...

  9. 【Android开发】范例1-实现带描边的圆角图片

    利用学过的BitmapShader渲染类,我们来实现一个带描边的圆角图片. 具体实现: 用来显示自定义的绘图类的布局文件 res/layout/main.xml: <?xml version=& ...

最新文章

  1. OpenCV3.3中支持向量机(Support Vector Machines, SVM)实现简介及使用
  2. 基于邮件通道的WCF通信系统
  3. Navicat Monitor v1.7的新功能说明
  4. 详解@Autowired、@Qualifier和@Required
  5. UE4学习-场景介绍、基本操作、快捷键
  6. 利用Vagrant and VirtualBox搭建core os环境
  7. 并不能一蹴而就的s9t9
  8. kafka Centos7.2 单机集群搭建
  9. 为什么自动挡的挡位顺序都是P、R、N、D?
  10. GetCurrentTime(),GetLocalTime(),GetSystemTime()之间的区别
  11. 学python lesson2
  12. 寻找节点d=n的节点算法
  13. 分布式本质论:高吞吐、高可用、可扩展 (1)
  14. 华为路由器命令行PPPOE拨号案例
  15. WordPress 简约主题 NDNAV 网址导航网站模版
  16. 光环PMP一模知识点解析
  17. c语言程序设计课设简单,北京工业大学C语言程序设计课设报告.docx
  18. 如何在Excel中创建组合图
  19. 【随笔记】Deepin20 Linux 下安装编译NGINX
  20. 每日必读DZone News—Java中的随机数生成

热门文章

  1. 申万一级行业日指数_12月5日申万一级行业指数表现
  2. Double保留指定小数位数的五种方法
  3. uni-app搜索功能
  4. 谁能成为Leader,大Leader该做什么
  5. Flash3D学习计划(三)——学习VB,IB相关,理解三角形顶点顺序;在屏幕上显示2D矩形,并实现缩放,平移,旋转...
  6. 电感 温升电流和饱和电流 MAX小于TYPE值
  7. svn更新 can‘t open file 处理
  8. 阿里云 云监控插件安装参考
  9. Erlang和Golang区别
  10. NW(New World)快速开发平台介绍(完整的中小型管理系统解决方案)