应朋友之邀,临时改个demo,大体就这个样子,图片上层想加什么加什么,加载的是本地图片,不是网络的,但也可以拿来参考。因为不是本人现在项目用到的,改完了就不深究了,还有更重要的要忙。
package com.dodowaterfall;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.AssetManager;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import com.dodowaterfall.LazyScrollView.OnScrollListener;
import com.dodowaterfall.widget.FlowTag;
import com.dodowaterfall.widget.FlowView;
import com.dodowaterfall.widget.ImageLoaderTask;
public class MainActivity extends Activity {
private LazyScrollView waterfall_scroll;
private LinearLayout waterfall_container;
private ArrayList<LinearLayout> waterfall_items;
private Display display;
private AssetManager asset_manager;
private List<String> image_filenames;
private final String image_path = "images";
private Handler handler;
private int item_width;
private int column_count = 3;// 显示列数
private int page_count = 6;// 每次加载15张图片
private int current_page = 0;// 当前页数
private int[] column_height;// 每列的高度
private HashMap<Integer, String> pins;
private int loaded_count = 0;// 已加载数量
private HashMap<Integer, Integer>[] pin_mark = null;
private Context context;
private HashMap<Integer, FlowView> iviews;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
display = this.getWindowManager().getDefaultDisplay();
item_width = display.getWidth() / column_count;// 根据屏幕大小计算每列大小
asset_manager = this.getAssets();
column_height = new int[column_count];
context = this.getApplicationContext();
iviews = new HashMap<Integer, FlowView>();
pins = new HashMap<Integer, String>();
pin_mark = new HashMap[column_count];
InitLayout();
}
private void InitLayout() {
waterfall_scroll = (LazyScrollView) findViewById(R.id.waterfall_scroll);
waterfall_scroll.getView();
waterfall_scroll.setOnScrollListener(new OnScrollListener() {
@Override
public void onTop() {
// 滚动到最顶端
Log.d("LazyScroll", "Scroll to top");
}
@Override
public void onScroll() {
}
@Override
public void onBottom() {
// 滚动到最低端
AddItemToContainer(++current_page, page_count);
}
@Override
public void onAutoScroll() {
// 暂时解决,需重写
// 自动滚动
Rect bounds = new Rect();
Rect scrollBounds = new Rect(waterfall_scroll.getScrollX(),
waterfall_scroll.getScrollY(), waterfall_scroll
.getScrollX() + waterfall_scroll.getWidth(),
waterfall_scroll.getScrollY()
+ waterfall_scroll.getHeight());
for (int i = 1; i < loaded_count; i++) {
FlowView v = iviews.get(i);
if (v != null) {
v.getHitRect(bounds);
if (Rect.intersects(scrollBounds, bounds)) {
if (v.bitmap == null) {
v.Reload();
}
} else {
v.recycle();
}
}
}
}
});
waterfall_container = (LinearLayout) this
.findViewById(R.id.waterfall_container);
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
FlowView v = (FlowView) msg.obj;
int w = msg.arg1;
int h = msg.arg2;
Log.d("MainActivity",
String.format(
"获取实际View高度:%d,ID:%d,columnIndex:%d,rowIndex:%d,filename:%s",
v.getHeight(), v.getId(), v
.getColumnIndex(), v.getRowIndex(),
v.getFlowTag().getFileName()));
String f = v.getFlowTag().getFileName();
// 此处计算列值
int columnIndex = GetMinValue(column_height);
v.setColumnIndex(columnIndex);
column_height[columnIndex] += h;
pins.put(v.getId(), f);
iviews.put(v.getId(), v);
break;
}
}
@Override
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
return super.sendMessageAtTime(msg, uptimeMillis);
}
};
waterfall_items = new ArrayList<LinearLayout>();
for (int i = 0; i < column_count; i++) {
LinearLayout itemLayout = new LinearLayout(this);
LinearLayout.LayoutParams itemParam = new LinearLayout.LayoutParams(
item_width, LayoutParams.WRAP_CONTENT);
itemLayout.setPadding(2, 2, 2, 2);
itemLayout.setOrientation(LinearLayout.VERTICAL);
itemLayout.setLayoutParams(itemParam);
waterfall_items.add(itemLayout);
waterfall_container.addView(itemLayout);
}
// 加载所有图片路径
try {
image_filenames = Arrays.asList(asset_manager.list(image_path));
} catch (IOException e) {
e.printStackTrace();
}
// 第一次加载
AddItemToContainer(current_page, page_count);
}
private void AddItemToContainer(int pageindex, int pagecount) {
int currentIndex = pageindex * pagecount;
// 将废弃:按照顺序排列图片,发现问题,如果图片不均匀则会出现有的列过长有的列短的情况
// 将采用根据高度最小的那列添加图片的方式
int j = currentIndex % column_count;
int imagecount = image_filenames.size();
for (int i = currentIndex; i < pagecount * (pageindex + 1)
&& i < imagecount; i++) {
loaded_count++;
j = j >= column_count ? j = 0 : j;
AddImage(image_filenames.get(i), j++,
(int) Math.ceil(loaded_count / (double) column_count),
loaded_count);
}
}
private void AddImage(String filename, int columnIndex, int rowIndex, int id) {
View v= LayoutInflater.from(this).inflate(R.layout.waterfallitem, null);
/* FlowView item = (FlowView) LayoutInflater.from(this).inflate(
R.layout.waterfallitem, null);*/
FlowView item= (FlowView)v.findViewById(R.id.waterfall_image);
item.setColumnIndex(columnIndex);
item.setRowIndex(rowIndex);
item.setId(id);
item.setViewHandler(this.handler);
// 多线程参数
FlowTag param = new FlowTag();
param.setFlowId(id);
param.setAssetManager(asset_manager);
param.setFileName(image_path + "/" + filename);
param.setItemWidth(item_width);
item.setFlowTag(param);
item.LoadImage();
// waterfall_items.get(columnIndex).addView(item);
waterfall_items.get(columnIndex).addView(v);
ImageLoaderTask task = new ImageLoaderTask(item);
item.setTag(filename);
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, sActivity.class);
Bundle b = new Bundle();
b.putString("fileName", (String) v.getTag());
intent.putExtras(b);
startActivity(intent);
}
});
task.execute(param);
}
private int GetMinValue(int[] array) {
int m = 0;
int length = array.length;
for (int i = 0; i < length; ++i) {
if (array[i] < array[m]) {
m = i;
}
}
return m;
}
}
package com.dodowaterfall.widget;
import java.io.BufferedInputStream;
import java.io.IOException;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.AnimationDrawable;
import android.widget.ImageView;
import android.widget.ScrollView;
import android.widget.Toast;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
public class FlowView extends ImageView implements View.OnClickListener,
View.OnLongClickListener {
private AnimationDrawable loadingAnimation;
private FlowTag flowTag;
private Context context;
public Bitmap bitmap;
private ImageLoaderTask task;
private int columnIndex;// 图片属于第几列
private int rowIndex;// 图片属于第几行
private Handler viewHandler;
public FlowView(Context c, AttributeSet attrs, int defStyle) {
super(c, attrs, defStyle);
this.context = c;
Init();
}
public FlowView(Context c, AttributeSet attrs) {
super(c, attrs);
this.context = c;
Init();
}
public FlowView(Context c) {
super(c);
this.context = c;
Init();
}
private void Init() {
setOnClickListener(this);
this.setOnLongClickListener(this);
setAdjustViewBounds(true);
}
@Override
public boolean onLongClick(View v) {
Log.d("FlowView", "LongClick");
Toast.makeText(context, "长按:" + this.flowTag.getFlowId(),
Toast.LENGTH_SHORT).show();
return true;
}
@Override
public void onClick(View v) {
Log.d("FlowView", "Click");
Toast.makeText(context, "单击:" + this.flowTag.getFlowId(),
Toast.LENGTH_SHORT).show();
}
/**
* 加载图片
*/
public void LoadImage() {
if (getFlowTag() != null) {
new LoadImageThread().start();
}
}
/**
* 重新加载图片
*/
public void Reload() {
if (this.bitmap == null && getFlowTag() != null) {
new LoadImageThread().start();
}
}
/**
* 回收内存
*/
public void recycle() {
setImageBitmap(null);
if ((this.bitmap == null) || (this.bitmap.isRecycled()))
return;
this.bitmap.recycle();
this.bitmap = null;
}
public FlowTag getFlowTag() {
return flowTag;
}
public void setFlowTag(FlowTag flowTag) {
this.flowTag = flowTag;
}
public int getColumnIndex() {
return columnIndex;
}
public void setColumnIndex(int columnIndex) {
this.columnIndex = columnIndex;
}
public int getRowIndex() {
return rowIndex;
}
public void setRowIndex(int rowIndex) {
this.rowIndex = rowIndex;
}
public Handler getViewHandler() {
return viewHandler;
}
public FlowView setViewHandler(Handler viewHandler) {
this.viewHandler = viewHandler;
return this;
}
class LoadImageThread extends Thread {
LoadImageThread() {
}
public void run() {
if (flowTag != null) {
BufferedInputStream buf;
try {
buf = new BufferedInputStream(flowTag.getAssetManager()
.open(flowTag.getFileName()));
bitmap = BitmapFactory.decodeStream(buf);
} catch (IOException e) {
e.printStackTrace();
}
// 此处不能直接更新UI,否则会发生异常:
// CalledFromWrongThreadException: Only the original thread that
// created a view hierarchy can touch its views.
// 也可以使用Handler或者Looper发送Message解决这个问题
((Activity) context).runOnUiThread(new Runnable() {
public void run() {
if (bitmap != null){// 此处在线程过多时可能为null
int width = bitmap.getWidth();// 获取真实宽高
int height = bitmap.getHeight();
LayoutParams lp = getLayoutParams();
lp.height = (height * flowTag.getItemWidth())
/ width;// 调整高度
setLayoutParams(lp);
setImageBitmap(bitmap);// 将引用指定到同一个对象,方便销毁
Handler h = getViewHandler();
Message m = h.obtainMessage(flowTag.what, width,
height, FlowView.this);
h.sendMessage(m);
}
}
});
}
}
}
}