效果图:
瀑流流实现涉及的知识点
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