开源项目之瀑布流DodoWaterFall

DodoWaterFall实现了类似于迷尚android和蘑菇街android的瀑布流布局。

  项目如图:

开源项目之瀑布流DodoWaterFall_第1张图片

效果如图:

开源项目之瀑布流DodoWaterFall_第2张图片

项目总共五个目标文件!~

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

	}

项目文件不多,易懂!适合学习!

学习的目标是成熟!~~


你可能感兴趣的:(开源项目之瀑布流DodoWaterFall)