Android瀑布流

应朋友之邀,临时改个demo,大体就这个样子,图片上层想加什么加什么,加载的是本地图片,不是网络的,但也可以拿来参考。因为不是本人现在项目用到的,改完了就不深究了,还有更重要的要忙。

Android瀑布流关键代码:

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);
						}
					}
				});
			}
		}
	}
}

源码:http://download.csdn.net/detail/djun100/6023043

你可能感兴趣的:(Android瀑布流)