对手机App的瀑布流效果一直有所耳闻,却从未自己亲自动手实践,趁着这几天还有些时间,做了些研究,也参考了网络上很多大神的博客,终于写出来自己的瀑布流效果了,先上一图。
正如图所示:瀑布流的原理很简单,就是自己重新写一个ScrollView,添加一个横向排布的LinearLayout,再向这个横向的LinearLayout中添加三个纵向排布的LinearLayout,接着我们就可以向每个一LinearLayout中依次添加图片。原理很容易理解,但实践起来也很困难,需要注意的问题也很多:
1.为了防止OOM,我们应当对那些不可见的图片进行回收,在这里我的思路是:如果以一个屏幕的高度为一页的话,只在当前的程序中缓存下来三页数量的图片,即当前页,前一页和后一页,这样可以提高用户体验。为了回收图片,我们就需要重写一个View来显示瀑布流中的每一图片,异步的去加载Bitmap和回收Bitmap,当item不在当前屏幕以及上下页中时,将Bitmap对象引用置空。
2.在ScrollView滑动的过程中监听图片可见性的变化,在这里用两个数组来记录三页中每一个LinearLayout的最上端和最低端的子View的id。
3.利用一个Lrucache来加快图片的响应时间,同时利用虚拟机本身的垃圾回收进行内存回收。
4.将Bitmap按照当前item的高和宽进行压缩,以减少内存。
下面是我的代码,如果各位大神发现错误,还请多多指教。
WaterFallView瀑布流显示整体布局类
package com.example.waterfalltest.widget;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Toast;
import com.example.waterfalltest.widget.WaterFallItem.LoadCompletedListener;
/**
*
* 需调用setup方法首先对WaterFallView进行配置初始化
* 根布局为一个横向的LinearLayout,然后根据设置的列数依次添加纵向的LinearLayout,每次将图片加进纵向LinearLayout中
* 如果以一个屏幕的高度为一页的话,只在当前的程序中缓存下来三页数量的图片
* @author acer
*
*/
public class WaterFallView extends ScrollView {
private static final String TAG = "WaterFallView";
private LinearLayout mContainerLayout;
private ArrayList<LinearLayout> mLayoutsList;
private final static int PAGE_COUNT = 20;
private int currentPage = 0;
private int colNum;
private int colWidth;
private int colHeight[];
private List<String> mImageUrl;
private int screenHeight;
private int[] topIndexArray;//记录三页中顶部Item在LinearLayout的Id
private int[] bottomIndexArray;//记录三页中底部Item在LinearLayout的Id
private int[] lastBottomIndexArray;//所有Item中的最低部
public WaterFallView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
public WaterFallView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
public WaterFallView(Context