DodoWaterFall实现了类似于迷尚android和蘑菇街android的瀑布流布局。
项目如图:
效果如图:
项目总共五个目标文件!~
LazyScrollView类:可以上下滚动的视图。
MainActivity类:主界面类。
FlowTag类:图片信息标识。
FlowView类:图片视图 ,可以使用线程加载图片或ImageLoaderTask加载图片。
ImageLoaderTask类:同步任务方式加载图片。
主要成员:
//上下滚动的视图
private LazyScrollView waterfall_scroll;
//容器
private LinearLayout waterfall_container;
//包含容器的队列
private ArrayList<LinearLayout> waterfall_items;
//图片视图对应的哈希表
private HashMap<Integer, FlowView> iviews;
实现关键代码:
//初始化布局 把循环加入图片,然后加入到容器、最后加入到容器队列
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(int l, int t, int oldl, int oldt)
{
// Log.d("MainActivity",
// String.format("%d %d %d %d", l, t, oldl, oldt));
// Log.d("MainActivity", "range:" + range);
// Log.d("MainActivity", "range-t:" + (range - t));
scroll_height = waterfall_scroll.getMeasuredHeight();
Log.d("MainActivity", "scroll_height:" + scroll_height);
if (t > oldt)
{// 向下滚动
if (t > 2 * scroll_height)
{// 超过两屏幕后
for (int k = 0; k < column_count; k++)
{
LinearLayout localLinearLayout = waterfall_items
.get(k);
if (pin_mark[k].get(Math.min(bottomIndex[k] + 1,
lineIndex[k])) <= t + 3 * scroll_height)
{// 最底部的图片位置小于当前t+3*屏幕高度
((FlowView) waterfall_items.get(k).getChildAt(
Math.min(1 + bottomIndex[k],
lineIndex[k]))).Reload();
bottomIndex[k] = Math.min(1 + bottomIndex[k],
lineIndex[k]);
}
Log.d("MainActivity",
"headIndex:" + topIndex[k] + " footIndex:"
+ bottomIndex[k] + " headHeight:"
+ pin_mark[k].get(topIndex[k]));
if (pin_mark[k].get(topIndex[k]) < t - 2
* scroll_height)
{// 未回收图片的最高位置<t-两倍屏幕高度
int i1 = topIndex[k];
topIndex[k]++;
((FlowView) localLinearLayout.getChildAt(i1))
.recycle();
Log.d("MainActivity", "recycle,k:" + k
+ " headindex:" + topIndex[k]);
}
}
}
} else
{// 向上滚动
if (t > 2 * scroll_height)
{// 超过两屏幕后
for (int k = 0; k < column_count; k++)
{
LinearLayout localLinearLayout = waterfall_items
.get(k);
if (pin_mark[k].get(bottomIndex[k]) > t + 3
* scroll_height)
{
((FlowView) localLinearLayout
.getChildAt(bottomIndex[k])).recycle();
bottomIndex[k]--;
}
if (pin_mark[k].get(Math.max(topIndex[k] - 1, 0)) >= t
- 2 * scroll_height)
{
((FlowView) localLinearLayout.getChildAt(Math
.max(-1 + topIndex[k], 0))).Reload();
topIndex[k] = Math.max(topIndex[k] - 1, 0);
}
}
}
}
}
});
waterfall_container = (LinearLayout) this
.findViewById(R.id.waterfall_container);
handler = new Handler()
{
@Override
public void dispatchMessage(Message msg)
{
super.dispatchMessage(msg);
}
@Override
public void handleMessage(Message msg)
{
// super.handleMessage(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);
waterfall_items.get(columnIndex).addView(v);
lineIndex[columnIndex]++;
pin_mark[columnIndex].put(lineIndex[columnIndex],
column_height[columnIndex]);
bottomIndex[columnIndex] = lineIndex[columnIndex];
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 imagecount = 10000;// image_filenames.size();
for (int i = currentIndex; i < pagecount * (pageindex + 1)
&& i < imagecount; i++)
{
loaded_count++;
Random rand = new Random();
int r = rand.nextInt(image_filenames.size());
AddImage(image_filenames.get(r),
(int) Math.ceil(loaded_count / (double) column_count),
loaded_count);
}
}
//加入图片
private void AddImage(String filename, int rowIndex, int id)
{
FlowView item = new FlowView(context);
// 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);
}
项目文件不多,易懂!适合学习!
学习的目标是成熟!~~