效果图:

瀑流流实现涉及的知识点

1.ScrollView滚动视图,我们这里用的是自定义ScrollView

/**
* Created by Spring on 2015/11/2.
* 自定义ScrollView
*/
public class CustomScrollView extends ScrollView { public CustomScrollView(Context context) {
super(context);
} public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
} public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
} /**
* 获得由垂直方向滚动条代表的所有垂直范围,缺省的范围是当前视图的画图高度。
*/
public int getComputeVerticalScrollRange() {
//滚动视图的可滚动范围是所有子元素的高度。
return super.computeVerticalScrollRange();
} /**
* 获得滚动条的滑块垂直方向的偏移。
*/
public int getComputeVerticalScrollOffSet() {
//计算垂直方向滚动条的滑块的偏移。此值用来计算滚动条轨迹的滑块的位置。
return super.computeVerticalScrollOffset();
} /**
*
* getScrollY()获得ScrollView滑动的距离
* getHeight是获得控件的显示的大小,如果控件大小超出的屏幕,那他的大小就是屏幕的大小。
* 详情见:http://www.cnblogs.com/qinghuaideren/p/3186990.html
*/
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) { if (t + getHeight() >= computeVerticalScrollRange()) {
//ScrollView滑动到底部了
onScrollListener.onBottom(); } else if (getScrollY() == 0) {
//ScrollView滑动到顶部了
onScrollListener.onTop();
} else {
//ScrollView滑动中
onScrollListener.onScroll();
} } /**
* 定义接口
*
* @author admin
*/
public interface OnScrollListener {
void onBottom(); void onTop(); void onScroll();
} private OnScrollListener onScrollListener; public void setOnScrollListener(OnScrollListener onScrollListener) {
this.onScrollListener = onScrollListener;
}
}

2.AsyncTask,异步加载图片

package com.jingling.practice.waterfall;

import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.os.AsyncTask;
import android.util.Log;
import android.view.ViewGroup;
import android.widget.ImageView; import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference; /**
* Created by Spring on 2015/11/4.
* 图片异步加载任务
*/
public class ImageLoaderTask extends AsyncTask<TaskParam, Void, Bitmap> {
private TaskParam param;
private final WeakReference<ImageView> imageViewReference; // 防止内存溢出 public ImageLoaderTask(ImageView imageView) {
imageViewReference = new WeakReference<ImageView>(imageView); } /**
* 完成实际的下载任务
* @param params
* @return
*/
@Override
protected Bitmap doInBackground(TaskParam... params) {
param = params[0];
return loadImageFile(param.getFilename(),param.getAssetManager());
} private Bitmap loadImageFile(final String filename, final AssetManager assetManager) {
InputStream is = null;
try {
Bitmap bmp = BitmapCache.getInstance().getBitmap(filename,
param.getAssetManager());
return bmp;
} catch (Exception e) {
Log.e(this.getClass().getSimpleName(), "fetchDrawable failed", e);
} finally {
try {
if (is != null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null; } /**
* 当下载完成后,显示出下载的图片
* @param bitmap
*/
@Override
protected void onPostExecute(Bitmap bitmap) {
if (isCancelled()) {
bitmap = null;
}
if (imageViewReference != null) {
ImageView imageView = imageViewReference.get();
if (imageView != null) {
if (bitmap != null) {
int width = bitmap.getWidth();// 获取真实宽高
int height = bitmap.getHeight();
ViewGroup.LayoutParams lp = imageView.getLayoutParams();
lp.height = (height * param.getItemWidth()) / width;// 调整高度
imageView.setLayoutParams(lp); imageView.setImageBitmap(bitmap); } }
}
} }

3.MainActivity

package com.jingling.practice.waterfall;

import android.app.Activity;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; public class MainActivity extends Activity {
/**
* 滚动视图
*/
private CustomScrollView waterfall_scroll;
/**
* 布局内容框架
*/
private LinearLayout waterfall_container;
/**
* 布局内容item
*/
private ArrayList<LinearLayout> waterfall_items;
/**
* 图片文件名
*/
private List<String> image_filenames;
/**
* 图片路径前缀
*/
private final String image_path = "images";
/**
* 提供关于屏幕尺寸和分辨率的信息
*/
private Display display;
/**
* 访问assets目录下的文件
*/
private AssetManager assetManager; /**
* 每个item的宽度
*/
private int itemWidth;
/**
* 显示列数
*/ private int column_count = 3;
/**
* 每次加载15张图片
*/
private int page_count = 15;
/**
* 当前页数
*/
private int current_page = 0; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取手机默认的屏幕尺寸和分辨率的信息
display = this.getWindowManager().getDefaultDisplay();
//根据屏幕计算每列的大小
itemWidth = display.getWidth() / column_count;
//获取asset目录下的文件
assetManager = this.getAssets(); initLayout();
} public void initLayout() {
waterfall_scroll = (CustomScrollView) findViewById(R.id.waterfall_scroll);
//设置滚动监听
waterfall_scroll.setOnScrollListener(new CustomScrollView.OnScrollListener() {
@Override
public void onBottom() {
// 滚动到最低端
AddItemToContainer(++current_page, page_count);
Log.d("Scroll", "Scroll to bottom");
} @Override
public void onTop() {
// 滚动到最顶端
Log.d("Scroll", "Scroll to top");
} @Override
public void onScroll() {
// 滚动中
Log.d("Scroll", "Scrolling");
}
}); waterfall_container = (LinearLayout) findViewById(R.id.waterfall_container);
waterfall_items = new ArrayList<LinearLayout>();
for (int i = 0; i < column_count; i++) {
LinearLayout itemLayout = new LinearLayout(this);
LinearLayout.LayoutParams itemParams = new LinearLayout.LayoutParams(itemWidth, ViewGroup.LayoutParams.WRAP_CONTENT);
itemLayout.setPadding(2, 2, 2, 2);
itemLayout.setOrientation(LinearLayout.VERTICAL);
itemLayout.setLayoutParams(itemParams);
waterfall_items.add(itemLayout);
waterfall_container.addView(itemLayout);
} // 加载所有图片路径
try {
image_filenames = Arrays.asList(assetManager.list(image_path));
} catch (IOException e) {
e.printStackTrace();
}
// 第一次加载
AddItemToContainer(current_page, page_count);
} private void AddItemToContainer(int pageindex, int pagecount) {
int j = 0;
int images_count = image_filenames.size();
for (int i = pageindex * pagecount; i < pagecount * (pageindex + 1)
&& i < images_count; i++) { j = j >= column_count ? j = 0 : j;
AddImage(image_filenames.get(i), j++);
} } private void AddImage(String filename, int columnIndex) {
ImageView item = (ImageView) LayoutInflater.from(this).inflate(
R.layout.waterfall_item, null);
waterfall_items.get(columnIndex).addView(item); TaskParam param = new TaskParam();
param.setAssetManager(assetManager);
param.setFilename(image_path + "/" + filename);
param.setItemWidth(itemWidth);
ImageLoaderTask task = new ImageLoaderTask(item);
task.execute(param);
}
}

4.android-studio   assets目录的创建(这里的图片全部放在assets目录下的,studio的assets目录不像在eclipse中项目一创建完成就有的)

(1) 选择project

(2)选择你项目下src/main,右键鼠标选择new Directory,输入assets,即可创建成功。

源码已经上传:https://github.com/presCheng/WaterFall.git

android 瀑布流(图片浏览)的更多相关文章

  1. 转载—— android 瀑布流的实现详解,附源码

    介绍 参考自:https://github.com/dodola/android_waterfall,因为原来的代码封装不好,所以,我根据源码的思路,重新写了一遍,所以有了现在这个项目:https:/ ...

  2. 用原生JavaScript实现图片瀑布流的浏览效果

    学习JS,活跃思维,灵活运用的一个较为典型的学习案例.同一个瀑布流的效果但实现方式却很多,利用递归.冒泡等等手法都可以达到你想要的目的.这次要说的就是利用类似递归来实现此效果的原创方案.此方案个人认为 ...

  3. Android瀑布流优化,解决Recyclerview展示大批量图片时Item自动切换、闪烁、空白等问题

    本文涉及的代码案例可以在下方的链接中找到,如果对你有帮助,请给个Star(#^.^#) https://github.com/CodeTillDoom/StaggeredRcl 问题分析 这段时间业务 ...

  4. Android瀑布流照片墙实现,体验不规则排列的美感

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/10470797 传统界面的布局方式总是行列分明.坐落有序的,这种布局已是司空见惯,在 ...

  5. RecyclerView 制作瀑布流图片

    这是瀑布流的效果图 RecyclerView(ListView的升级版) 加载图片用的是第三方图片加载框架 ------------------------------------- 在Xml中 &l ...

  6. android 瀑布流

    我们还是来看一款示例: 看起来很像我们的gridview吧,不过又不像,因为item大小不固定的,看起来是不是别有一番风味,确实如此.就如我们的方角图形,斯通见惯后也就出现了圆角.下面我简单介绍下实现 ...

  7. android瀑布流效果(仿蘑菇街)

    Android 转载分享(10)  我们还是来看一款示例:(蘑菇街)           看起来很像我们的gridview吧,不过又不像,因为item大小不固定的,看起来是不是别有一番风味,确实如此. ...

  8. android 瀑布流效果(仿蘑菇街)

    我们还是来看一款示例:(蘑菇街)           看起来很像我们的gridview吧,不过又不像,因为item大小不固定的,看起来是不是别有一番风味,确实如此.就如我们的方角图形,斯通见惯后也就出 ...

  9. Android瀑布流照片

    http://blog.csdn.net/guolin_blog/article/details/10470797 记得我在之前已经写过一篇关于如何在Android上实现照片墙功能的文章了,但那个时候 ...

随机推荐

  1. HDU 1005(周期问题)

    HDU 1005 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u   Descript ...

  2. 禁用ios7 手势滑动返回功能

    禁用ios7 手势滑动返回功能 版权声明:本文为博主原创文章,未经博主允许不得转载. 在有的时候,我们不需要手势返回功能,那么可以在页面中添加以下代码: - (void)viewDidAppear:( ...

  3. C#程序设计基础——转义字符

    \’ 单引号 \” 双引号 \\ 反斜杠 \0 空字符 \a 感叹号 \b 退格 \f 换页 \n 换行 \r 回车 \t 水平Tab \v 垂直Tab

  4. INDEX RANG SCAN无需回表的情况

    create table a3 as select * from dba_objects create index a3_idx1 on a3(owner); select owner from a3 ...

  5. Hadoop InputFormat

    Hadoop可以处理不同数据格式(数据源)的数据,从文本文件到(非)关系型数据库,这很大程度上得益于Hadoop InputFormat的可扩展性设计,InputFormat层次结构图如下:  

  6. 【二分】XMU 1587 中位数

    题目链接: http://acm.xmu.edu.cn/JudgeOnline/problem.php?id=1587 题目大意: 求两个长度为n(n<=109)的有序序列合并后的中位数.序列中 ...

  7. HDOJ 2114 Calculate S(n)(找周期)

    Problem Description Calculate S(n). S(n)=1^3+2^3 +3^3 +--+n^3 . Input Each line will contain one int ...

  8. Java学习日记-2.3 基本数据类型和对象所占内存空间大小

    转自:http://www.newsmth.net/nForum/#!article/Java/324167

  9. TreeSet具体应用

    知识是用来运用的,一辈子用不上的等于没学,学了忘了的等于没学,学了不会用的等于没学 //TreeSetDemo2.java package saturday2; import java.util.Ha ...

  10. jquery and js 判断一个元素是否存在

    一.javascript中判断一个元素是否存在 if(document.getElementById('example')){ // do sth } 二.jquery中判断一个元素是否存在 < ...