精华内容
下载资源
问答
  • 这样在瀑布流展示时,由于一瞬间图片还没有下载下来,这样瀑布流模块的高度计算(也就是top值的计算)是没有图片的高度,当图片加载完成后,上一个模块往下撑开,就会被下面模块遮挡,出现重叠的bug。     解决...

    ff和google不同,如果图片没有加载完成是不占高度的。这样在瀑布流展示时,由于一瞬间图片还没有下载下来,这样瀑布流模块的高度计算(也就是top值的计算)是没有图片的高度,当图片加载完成后,上一个模块往下撑开,就会被下面模块遮挡,出现重叠的bug。

     

     

    解决方法:在照片的div上高度写死。由于瀑布流的图片高度是预先知道的,这样可以在图片的div上写死这个高度,及时图片还未加载完成,高度也都预留好了,这样图片加载好后,就不会被遮挡了。

     

     

    <script type="tpl" id="tpl">
      <div class="pin ks-waterfall poster-grid-float">
        <div class="posterimg" style="height:{{height}}px"> //这里的height是重点
          <a href="/area/photo/{{id}}" title="{{description}}" target="_blank"><img alt="{{photoDesc}}" src="{{coverpath_x200}}" height="{{height}}"/></a>
          <div class="postermask" style="display:none;"><a href="/area/photo/{{id}}" title="{{photoDesc}}" target="_blank">{{photoDesc}}</a></div>
        </div>
        <div class="poster-grid-user clearfix">
          <a class="fleft" href="/user/{{mid}}" target="_blank">
            <img src="{{userPhoto}}" alt="{{mname}}">
          </a>
          <div class="fleft">
            <a class="fcblue" href="/user/{{mid}}" target="_blank">{{mname}}</a>
            <br />
            <span>{{posttimeStr}}</span>
          </div>
          <div class="fright">
            <div><a title="好评" href="/area/photo/{{id}}#comments" class="dot-goodmini">{{goodnum}}</a></div>
            <div><a title="回应" href="/area/photo/{{id}}#respond" class="dot-commentmini">{{reviewnum}}</a></div>
          </div>
        </div>
      </div>
    </script>
    展开全文
  • waterfall自适应图片瀑布流布局无限加载代码,兼容电脑、平板和手机端浏览,使用front封装渲染,cell的宽高间隙定义全局参数自行修改。
  • Waterfall

    2015-11-27 11:54:20
    * 遍历imageViewList中的每张图片,对图片的可见性进行检查,如果图片已经离开屏幕可见范围,则将图片替换成一张空。 */ public void checkVisibility () { for ( int i = 0 ; i (); i++) { ...

    1.1

    package com.example.photowallfallsdemo;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.os.AsyncTask;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.Message;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.View.OnTouchListener;
    import android.widget.ImageView;
    import android.widget.ImageView.ScaleType;
    import android.widget.LinearLayout;
    import android.widget.ScrollView;
    import android.widget.Toast;
    
    /**
     * 自定义的ScrollView,在其中动态地对图片进行添加。
     * 
     * @author guolin
     */
    public class MyScrollView extends ScrollView implements OnTouchListener {
    
        /**
         * 每页要加载的图片数量
         */
        public static final int PAGE_SIZE = 15;
    
        /**
         * 记录当前已加载到第几页
         */
        private int page;
    
        /**
         * 每一列的宽度
         */
        private int columnWidth;
    
        /**
         * 当前第一列的高度
         */
        private int firstColumnHeight;
    
        /**
         * 当前第二列的高度
         */
        private int secondColumnHeight;
    
        /**
         * 当前第三列的高度
         */
        private int thirdColumnHeight;
    
        /**
         * 是否已加载过一次layout,这里onLayout中的初始化只需加载一次
         */
        private boolean loadOnce;
    
        /**
         * 对图片进行管理的工具类
         */
        private ImageLoader imageLoader;
    
        /**
         * 第一列的布局
         */
        private LinearLayout firstColumn;
    
        /**
         * 第二列的布局
         */
        private LinearLayout secondColumn;
    
        /**
         * 第三列的布局
         */
        private LinearLayout thirdColumn;
    
        /**
         * 记录所有正在下载或等待下载的任务。
         */
        private static Set<LoadImageTask> taskCollection;
    
        /**
         * MyScrollView下的直接子布局。
         */
        private static View scrollLayout;
    
        /**
         * MyScrollView布局的高度。
         */
        private static int scrollViewHeight;
    
        /**
         * 记录上垂直方向的滚动距离。
         */
        private static int lastScrollY = -1;
    
        /**
         * 记录所有界面上的图片,用以可以随时控制对图片的释放。
         */
        private List<ImageView> imageViewList = new ArrayList<ImageView>();
    
        /**
         * 在Handler中进行图片可见性检查的判断,以及加载更多图片的操作。
         */
        private static Handler handler = new Handler() {
    
            public void handleMessage(android.os.Message msg) {
                MyScrollView myScrollView = (MyScrollView) msg.obj;
                int scrollY = myScrollView.getScrollY();
                // 如果当前的滚动位置和上次相同,表示已停止滚动
                if (scrollY == lastScrollY) {
                    // 当滚动的最底部,并且当前没有正在下载的任务时,开始加载下一页的图片
                    if (scrollViewHeight + scrollY >= scrollLayout.getHeight()
                            && taskCollection.isEmpty()) {
                        myScrollView.loadMoreImages();
                    }
                    myScrollView.checkVisibility();
                } else {
                    lastScrollY = scrollY;
                    Message message = new Message();
                    message.obj = myScrollView;
                    // 5毫秒后再次对滚动位置进行判断
                    handler.sendMessageDelayed(message, 5);
                }
            };
    
        };
    
        /**
         * MyScrollView的构造函数。
         * 
         * @param context
         * @param attrs
         */
        public MyScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
            imageLoader = ImageLoader.getInstance();
            taskCollection = new HashSet<LoadImageTask>();
            setOnTouchListener(this);
        }
    
        /**
         * 进行一些关键性的初始化操作,获取MyScrollView的高度,以及得到第一列的宽度值。并在这里开始加载第一页的图片。
         */
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            super.onLayout(changed, l, t, r, b);
            if (changed && !loadOnce) {
                scrollViewHeight = getHeight();
                scrollLayout = getChildAt(0);
                firstColumn = (LinearLayout) findViewById(R.id.first_column);
                secondColumn = (LinearLayout) findViewById(R.id.second_column);
                thirdColumn = (LinearLayout) findViewById(R.id.third_column);
                columnWidth = firstColumn.getWidth();
                loadOnce = true;
                loadMoreImages();
            }
        }
    
        /**
         * 监听用户的触屏事件,如果用户手指离开屏幕则开始进行滚动检测。
         */
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                Message message = new Message();
                message.obj = this;
                handler.sendMessageDelayed(message, 5);
            }
            return false;
        }
    
        /**
         * 开始加载下一页的图片,每张图片都会开启一个异步线程去下载。
         */
        public void loadMoreImages() {
            if (hasSDCard()) {
                int startIndex = page * PAGE_SIZE;
                int endIndex = page * PAGE_SIZE + PAGE_SIZE;
                if (startIndex < Images.imageUrls.length) {
                    Toast.makeText(getContext(), "正在加载...", Toast.LENGTH_SHORT)
                            .show();
                    if (endIndex > Images.imageUrls.length) {
                        endIndex = Images.imageUrls.length;
                    }
                    for (int i = startIndex; i < endIndex; i++) {
                        LoadImageTask task = new LoadImageTask();
                        taskCollection.add(task);
                        task.execute(Images.imageUrls[i]);
                    }
                    page++;
                } else {
                    Toast.makeText(getContext(), "已没有更多图片", Toast.LENGTH_SHORT)
                            .show();
                }
            } else {
                Toast.makeText(getContext(), "未发现SD卡", Toast.LENGTH_SHORT).show();
            }
        }
    
        /**
         * 遍历imageViewList中的每张图片,对图片的可见性进行检查,如果图片已经离开屏幕可见范围,则将图片替换成一张空图。
         */
        public void checkVisibility() {
            for (int i = 0; i < imageViewList.size(); i++) {
                ImageView imageView = imageViewList.get(i);
                int borderTop = (Integer) imageView.getTag(R.string.border_top);
                int borderBottom = (Integer) imageView
                        .getTag(R.string.border_bottom);
                if (borderBottom > getScrollY()
                        && borderTop < getScrollY() + scrollViewHeight) {
                    String imageUrl = (String) imageView.getTag(R.string.image_url);
                    Bitmap bitmap = imageLoader.getBitmapFromMemoryCache(imageUrl);
                    if (bitmap != null) {
                        imageView.setImageBitmap(bitmap);
                    } else {
                        LoadImageTask task = new LoadImageTask(imageView);
                        task.execute(imageUrl);
                    }
                } else {
                    imageView.setImageResource(R.drawable.empty_photo);
                }
            }
        }
    
        /**
         * 判断手机是否有SD卡。
         * 
         * @return 有SD卡返回true,没有返回false。
         */
        private boolean hasSDCard() {
            return Environment.MEDIA_MOUNTED.equals(Environment
                    .getExternalStorageState());
        }
    
        /**
         * 异步下载图片的任务。
         * 
         * @author guolin
         */
        class LoadImageTask extends AsyncTask<String, Void, Bitmap> {
    
            /**
             * 图片的URL地址
             */
            private String mImageUrl;
    
            /**
             * 可重复使用的ImageView
             */
            private ImageView mImageView;
    
            public LoadImageTask() {
            }
    
            /**
             * 将可重复使用的ImageView传入
             * 
             * @param imageView
             */
            public LoadImageTask(ImageView imageView) {
                mImageView = imageView;
            }
    
            @Override
            protected Bitmap doInBackground(String... params) {
                mImageUrl = params[0];
                Bitmap imageBitmap = imageLoader
                        .getBitmapFromMemoryCache(mImageUrl);
                if (imageBitmap == null) {
                    imageBitmap = loadImage(mImageUrl);
                }
                return imageBitmap;
            }
    
            @Override
            protected void onPostExecute(Bitmap bitmap) {
                if (bitmap != null) {
                    double ratio = bitmap.getWidth() / (columnWidth * 1.0);
                    int scaledHeight = (int) (bitmap.getHeight() / ratio);
                    addImage(bitmap, columnWidth, scaledHeight);
                }
                taskCollection.remove(this);
            }
    
            /**
             * 根据传入的URL,对图片进行加载。如果这张图片已经存在于SD卡中,则直接从SD卡里读取,否则就从网络上下载。
             * 
             * @param imageUrl
             *            图片的URL地址
             * @return 加载到内存的图片。
             */
            private Bitmap loadImage(String imageUrl) {
                File imageFile = new File(getImagePath(imageUrl));
                if (!imageFile.exists()) {
                    downloadImage(imageUrl);
                }
                if (imageUrl != null) {
                    Bitmap bitmap = ImageLoader.decodeSampledBitmapFromResource(
                            imageFile.getPath(), columnWidth);
                    if (bitmap != null) {
                        imageLoader.addBitmapToMemoryCache(imageUrl, bitmap);
                        return bitmap;
                    }
                }
                return null;
            }
    
            /**
             * 向ImageView中添加一张图片
             * 
             * @param bitmap
             *            待添加的图片
             * @param imageWidth
             *            图片的宽度
             * @param imageHeight
             *            图片的高度
             */
            private void addImage(Bitmap bitmap, int imageWidth, int imageHeight) {
                LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                        imageWidth, imageHeight);
                if (mImageView != null) {
                    mImageView.setImageBitmap(bitmap);
                } else {
                    ImageView imageView = new ImageView(getContext());
                    imageView.setLayoutParams(params);
                    imageView.setImageBitmap(bitmap);
                    imageView.setScaleType(ScaleType.FIT_XY);
                    imageView.setPadding(5, 5, 5, 5);
                    imageView.setTag(R.string.image_url, mImageUrl);
                    findColumnToAdd(imageView, imageHeight).addView(imageView);
                    imageViewList.add(imageView);
                }
            }
    
            /**
             * 找到此时应该添加图片的一列。原则就是对三列的高度进行判断,当前高度最小的一列就是应该添加的一列。
             * 
             * @param imageView
             * @param imageHeight
             * @return 应该添加图片的一列
             */
            private LinearLayout findColumnToAdd(ImageView imageView,
                    int imageHeight) {
                if (firstColumnHeight <= secondColumnHeight) {
                    if (firstColumnHeight <= thirdColumnHeight) {
                        imageView.setTag(R.string.border_top, firstColumnHeight);
                        firstColumnHeight += imageHeight;
                        imageView.setTag(R.string.border_bottom, firstColumnHeight);
                        return firstColumn;
                    }
                    imageView.setTag(R.string.border_top, thirdColumnHeight);
                    thirdColumnHeight += imageHeight;
                    imageView.setTag(R.string.border_bottom, thirdColumnHeight);
                    return thirdColumn;
                } else {
                    if (secondColumnHeight <= thirdColumnHeight) {
                        imageView.setTag(R.string.border_top, secondColumnHeight);
                        secondColumnHeight += imageHeight;
                        imageView
                                .setTag(R.string.border_bottom, secondColumnHeight);
                        return secondColumn;
                    }
                    imageView.setTag(R.string.border_top, thirdColumnHeight);
                    thirdColumnHeight += imageHeight;
                    imageView.setTag(R.string.border_bottom, thirdColumnHeight);
                    return thirdColumn;
                }
            }
    
            /**
             * 将图片下载到SD卡缓存起来。
             * 
             * @param imageUrl
             *            图片的URL地址。
             */
            private void downloadImage(String imageUrl) {
                if (Environment.getExternalStorageState().equals(
                        Environment.MEDIA_MOUNTED)) {
                    Log.d("TAG", "monted sdcard");
                } else {
                    Log.d("TAG", "has no sdcard");
                }
                HttpURLConnection con = null;
                FileOutputStream fos = null;
                BufferedOutputStream bos = null;
                BufferedInputStream bis = null;
                File imageFile = null;
                try {
                    URL url = new URL(imageUrl);
                    con = (HttpURLConnection) url.openConnection();
                    con.setConnectTimeout(5 * 1000);
                    con.setReadTimeout(15 * 1000);
                    con.setDoInput(true);
                    con.setDoOutput(true);
                    bis = new BufferedInputStream(con.getInputStream());
                    imageFile = new File(getImagePath(imageUrl));
                    fos = new FileOutputStream(imageFile);
                    bos = new BufferedOutputStream(fos);
                    byte[] b = new byte[1024];
                    int length;
                    while ((length = bis.read(b)) != -1) {
                        bos.write(b, 0, length);
                        bos.flush();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (bis != null) {
                            bis.close();
                        }
                        if (bos != null) {
                            bos.close();
                        }
                        if (con != null) {
                            con.disconnect();
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (imageFile != null) {
                    Bitmap bitmap = ImageLoader.decodeSampledBitmapFromResource(
                            imageFile.getPath(), columnWidth);
                    if (bitmap != null) {
                        imageLoader.addBitmapToMemoryCache(imageUrl, bitmap);
                    }
                }
            }
    
            /**
             * 获取图片的本地存储路径。
             * 
             * @param imageUrl
             *            图片的URL地址。
             * @return 图片的本地存储路径。
             */
            private String getImagePath(String imageUrl) {
                int lastSlashIndex = imageUrl.lastIndexOf("/");
                String imageName = imageUrl.substring(lastSlashIndex + 1);
                String imageDir = Environment.getExternalStorageDirectory()
                        .getPath() + "/PhotoWallFalls/";
                File file = new File(imageDir);
                if (!file.exists()) {
                    file.mkdirs();
                }
                String imagePath = imageDir + imageName;
                return imagePath;
            }
        }
    
    }

    1.2

    package com.example.photowallfallsdemo;
    
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.util.LruCache;
    
    /**
     * 对图片进行管理的工具类。
     * 
     * @author Tony
     */
    public class ImageLoader {
    
        /**
         * 图片缓存技术的核心类,用于缓存所有下载好的图片,在程序内存达到设定值时会将最少最近使用的图片移除掉。
         */
        private static LruCache<String, Bitmap> mMemoryCache;
    
        /**
         * ImageLoader的实例。
         */
        private static ImageLoader mImageLoader;
    
        private ImageLoader() {
            // 获取应用程序最大可用内存
            int maxMemory = (int) Runtime.getRuntime().maxMemory();
            int cacheSize = maxMemory / 8;
            // 设置图片缓存大小为程序最大可用内存的1/8
            mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
                @Override
                protected int sizeOf(String key, Bitmap bitmap) {
                    return bitmap.getByteCount();
                }
            };
        }
    
        /**
         * 获取ImageLoader的实例。
         * 
         * @return ImageLoader的实例。
         */
        public static ImageLoader getInstance() {
            if (mImageLoader == null) {
                mImageLoader = new ImageLoader();
            }
            return mImageLoader;
        }
    
        /**
         * 将一张图片存储到LruCache中。
         * 
         * @param key
         *            LruCache的键,这里传入图片的URL地址。
         * @param bitmap
         *            LruCache的键,这里传入从网络上下载的Bitmap对象。
         */
        public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
            if (getBitmapFromMemoryCache(key) == null) {
                mMemoryCache.put(key, bitmap);
            }
        }
    
        /**
         * 从LruCache中获取一张图片,如果不存在就返回null。
         * 
         * @param key
         *            LruCache的键,这里传入图片的URL地址。
         * @return 对应传入键的Bitmap对象,或者null。
         */
        public Bitmap getBitmapFromMemoryCache(String key) {
            return mMemoryCache.get(key);
        }
    
        public static int calculateInSampleSize(BitmapFactory.Options options,
                int reqWidth) {
            // 源图片的宽度
            final int width = options.outWidth;
            int inSampleSize = 1;
            if (width > reqWidth) {
                // 计算出实际宽度和目标宽度的比率
                final int widthRatio = Math.round((float) width / (float) reqWidth);
                inSampleSize = widthRatio;
            }
            return inSampleSize;
        }
    
        public static Bitmap decodeSampledBitmapFromResource(String pathName,
                int reqWidth) {
            // 第一次解析将inJustDecodeBounds设置为true,来获取图片大小
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(pathName, options);
            // 调用上面定义的方法计算inSampleSize值
            options.inSampleSize = calculateInSampleSize(options, reqWidth);
            // 使用获取到的inSampleSize值再次解析图片
            options.inJustDecodeBounds = false;
            return BitmapFactory.decodeFile(pathName, options);
        }
    
    }
    

    2.1

    package com.example.demo_zhy_18_networkimageloader;
    import android.content.Context;
    import android.os.Bundle;
    import android.app.Fragment;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ArrayAdapter;
    import android.widget.GridView;
    import android.widget.ImageView;
    import com.zhy.utils.ImageLoader;
    import com.zhy.utils.ImageLoader.Type;
    import com.zhy.utils.Images;
    public class ListImgsFragment extends Fragment
    {
        private GridView mGridView;
        private String[] mUrlStrs = Images.imageThumbUrls;
        private ImageLoader mImageLoader;
        @Override
        public void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            mImageLoader = ImageLoader.getInstance(3, Type.LIFO);
        }
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState)
        {
            View view = inflater.inflate(R.layout.fragment_list_imgs, container,
                    false);
            mGridView = (GridView) view.findViewById(R.id.id_gridview);
            setUpAdapter();
            return view;
        }
        private void setUpAdapter()
        {
            if (getActivity() == null || mGridView == null)
                return;
            if (mUrlStrs != null)
            {
                mGridView.setAdapter(new ListImgItemAdaper(getActivity(), 0,
                        mUrlStrs));
            } else
            {
                mGridView.setAdapter(null);
            }
        }
        private class ListImgItemAdaper extends ArrayAdapter<String>
        {
            public ListImgItemAdaper(Context context, int resource, String[] datas)
            {
                super(getActivity(), 0, datas);
                Log.e("TAG", "ListImgItemAdaper");
            }
            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                if (convertView == null)
                {
                    convertView = getActivity().getLayoutInflater().inflate(
                            R.layout.item_fragment_list_imgs, parent, false);
                }
                ImageView imageview = (ImageView) convertView
                        .findViewById(R.id.id_img);
                imageview.setImageResource(R.drawable.pictures_no);
                mImageLoader.loadImage(getItem(position), imageview, true);
                return convertView;
            }
        }
    }
    

    2.2

    package com.zhy.utils;
    import java.io.File;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.LinkedList;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Semaphore;
    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.Looper;
    import android.os.Message;
    import android.util.LruCache;
    import android.util.Log;
    import android.widget.ImageView;
    import com.zhy.utils.ImageSizeUtil.ImageSize;
    public class ImageLoader
    {
        private static ImageLoader mInstance;
    
        private LruCache<String, Bitmap> mLruCache;
    
        private ExecutorService mThreadPool;
        private static final int DEAFULT_THREAD_COUNT = 1;
    
        private Type mType = Type.LIFO;
    
        private LinkedList<Runnable> mTaskQueue;
    
        private Thread mPoolThread;
        private Handler mPoolThreadHandler;
    
        private Handler mUIHandler;
        private Semaphore mSemaphorePoolThreadHandler = new Semaphore(0);
        private Semaphore mSemaphoreThreadPool;
        private boolean isDiskCacheEnable = true;
        private static final String TAG = "ImageLoader";
        public enum Type
        {
            FIFO, LIFO;
        }
        private ImageLoader(int threadCount, Type type)
        {
            init(threadCount, type);
        }
    
        private void init(int threadCount, Type type)
        {
            initBackThread();
    
            int maxMemory = (int) Runtime.getRuntime().maxMemory();
            int cacheMemory = maxMemory / 8;
            mLruCache = new LruCache<String, Bitmap>(cacheMemory)
            {
                @Override
                protected int sizeOf(String key, Bitmap value)
                {
                    return value.getRowBytes() * value.getHeight();
                }
            };
    
            mThreadPool = Executors.newFixedThreadPool(threadCount);
            mTaskQueue = new LinkedList<Runnable>();
            mType = type;
            mSemaphoreThreadPool = new Semaphore(threadCount);
        }
    
        private void initBackThread()
        {
    
            mPoolThread = new Thread()
            {
                @Override
                public void run()
                {
                    Looper.prepare();
                    mPoolThreadHandler = new Handler()
                    {
                        @Override
                        public void handleMessage(Message msg)
                        {
    
                            mThreadPool.execute(getTask());
                            try
                            {
                                mSemaphoreThreadPool.acquire();
                            } catch (InterruptedException e)
                            {
                            }
                        }
                    };
    
                    mSemaphorePoolThreadHandler.release();
                    Looper.loop();
                };
            };
            mPoolThread.start();
        }
        public static ImageLoader getInstance()
        {
            if (mInstance == null)
            {
                synchronized (ImageLoader.class)
                {
                    if (mInstance == null)
                    {
                        mInstance = new ImageLoader(DEAFULT_THREAD_COUNT, Type.LIFO);
                    }
                }
            }
            return mInstance;
        }
        public static ImageLoader getInstance(int threadCount, Type type)
        {
            if (mInstance == null)
            {
                synchronized (ImageLoader.class)
                {
                    if (mInstance == null)
                    {
                        mInstance = new ImageLoader(threadCount, type);
                    }
                }
            }
            return mInstance;
        }
    
        public void loadImage(final String path, final ImageView imageView,
                final boolean isFromNet)
        {
            imageView.setTag(path);
            if (mUIHandler == null)
            {
                mUIHandler = new Handler()
                {
                    public void handleMessage(Message msg)
                    {
    
                        ImgBeanHolder holder = (ImgBeanHolder) msg.obj;
                        Bitmap bm = holder.bitmap;
                        ImageView imageview = holder.imageView;
                        String path = holder.path;
    
                        if (imageview.getTag().toString().equals(path))
                        {
                            imageview.setImageBitmap(bm);
                        }
                    };
                };
            }
    
            Bitmap bm = getBitmapFromLruCache(path);
            if (bm != null)
            {
                refreashBitmap(path, imageView, bm);
            } else
            {
                addTask(buildTask(path, imageView, isFromNet));
            }
        }
    
        private Runnable buildTask(final String path, final ImageView imageView,
                final boolean isFromNet)
        {
            return new Runnable()
            {
                @Override
                public void run()
                {
                    Bitmap bm = null;
                    if (isFromNet)
                    {
                        File file = getDiskCacheDir(imageView.getContext(),
                                md5(path));
                        if (file.exists())
                        {
                            Log.e(TAG, "find image :" + path + " in disk cache .");
                            bm = loadImageFromLocal(file.getAbsolutePath(),
                                    imageView);
                        } else
                        {
                            if (isDiskCacheEnable)
                            {
                                boolean downloadState = DownloadImgUtils
                                        .downloadImgByUrl(path, file);
                                if (downloadState)
                                {
                                    Log.e(TAG,
                                            "download image :" + path
                                                    + " to disk cache . path is "
                                                    + file.getAbsolutePath());
                                    bm = loadImageFromLocal(file.getAbsolutePath(),
                                            imageView);
                                }
                            } else
    
                            {
                                Log.e(TAG, "load image :" + path + " to memory.");
                                bm = DownloadImgUtils.downloadImgByUrl(path,
                                        imageView);
                            }
                        }
                    } else
                    {
                        bm = loadImageFromLocal(path, imageView);
                    }
    
                    addBitmapToLruCache(path, bm);
                    refreashBitmap(path, imageView, bm);
                    mSemaphoreThreadPool.release();
                }
            };
        }
        private Bitmap loadImageFromLocal(final String path,
                final ImageView imageView)
        {
            Bitmap bm;
    
    
    
            ImageSize imageSize = ImageSizeUtil.getImageViewSize(imageView);
    
            bm = decodeSampledBitmapFromPath(path, imageSize.width,
                    imageSize.height);
            return bm;
        }
    
        private Runnable getTask()
        {
            if (mType == Type.FIFO)
            {
                return mTaskQueue.removeFirst();
            } else if (mType == Type.LIFO)
            {
                return mTaskQueue.removeLast();
            }
            return null;
        }
    
        public String md5(String str)
        {
            byte[] digest = null;
            try
            {
                MessageDigest md = MessageDigest.getInstance("md5");
                digest = md.digest(str.getBytes());
                return bytes2hex02(digest);
            } catch (NoSuchAlgorithmException e)
            {
                e.printStackTrace();
            }
            return null;
        }
    
        public String bytes2hex02(byte[] bytes)
        {
            StringBuilder sb = new StringBuilder();
            String tmp = null;
            for (byte b : bytes)
            {
    
                tmp = Integer.toHexString(0xFF & b);
                if (tmp.length() == 1)
                {
                    tmp = "0" + tmp;
                }
                sb.append(tmp);
            }
            return sb.toString();
        }
        private void refreashBitmap(final String path, final ImageView imageView,
                Bitmap bm)
        {
            Message message = Message.obtain();
            ImgBeanHolder holder = new ImgBeanHolder();
            holder.bitmap = bm;
            holder.path = path;
            holder.imageView = imageView;
            message.obj = holder;
            mUIHandler.sendMessage(message);
        }
    
        protected void addBitmapToLruCache(String path, Bitmap bm)
        {
            if (getBitmapFromLruCache(path) == null)
            {
                if (bm != null)
                    mLruCache.put(path, bm);
            }
        }
    
        protected Bitmap decodeSampledBitmapFromPath(String path, int width,
                int height)
        {
    
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(path, options);
            options.inSampleSize = ImageSizeUtil.caculateInSampleSize(options,
                    width, height);
    
            options.inJustDecodeBounds = false;
            Bitmap bitmap = BitmapFactory.decodeFile(path, options);
            return bitmap;
        }
        private synchronized void addTask(Runnable runnable)
        {
            mTaskQueue.add(runnable);
    
            try
            {
                if (mPoolThreadHandler == null)
                    mSemaphorePoolThreadHandler.acquire();
            } catch (InterruptedException e)
            {
            }
            mPoolThreadHandler.sendEmptyMessage(0x110);
        }
    
        public File getDiskCacheDir(Context context, String uniqueName)
        {
            String cachePath;
            if (Environment.MEDIA_MOUNTED.equals(Environment
                    .getExternalStorageState()))
            {
                cachePath = context.getExternalCacheDir().getPath();
            } else
            {
                cachePath = context.getCacheDir().getPath();
            }
            return new File(cachePath + File.separator + uniqueName);
        }
    
        private Bitmap getBitmapFromLruCache(String key)
        {
            return mLruCache.get(key);
        }
        private class ImgBeanHolder
        {
            Bitmap bitmap;
            ImageView imageView;
            String path;
        }
    }
    

    2.3

    package com.zhy.utils;
    import java.lang.reflect.Field;
    import android.graphics.BitmapFactory.Options;
    import android.util.DisplayMetrics;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.ImageView;
    public class ImageSizeUtil
    {
    
        public static int caculateInSampleSize(Options options, int reqWidth,
                int reqHeight)
        {
            int width = options.outWidth;
            int height = options.outHeight;
            int inSampleSize = 1;
            if (width > reqWidth || height > reqHeight)
            {
                int widthRadio = Math.round(width * 1.0f / reqWidth);
                int heightRadio = Math.round(height * 1.0f / reqHeight);
                inSampleSize = Math.max(widthRadio, heightRadio);
            }
            return inSampleSize;
        }
    
        public static ImageSize getImageViewSize(ImageView imageView)
        {
            ImageSize imageSize = new ImageSize();
            DisplayMetrics displayMetrics = imageView.getContext().getResources()
                    .getDisplayMetrics();
            LayoutParams lp = imageView.getLayoutParams();
            int width = imageView.getWidth();
            if (width <= 0)
            {
                width = lp.width;
            }
            if (width <= 0)
            {
    
                width = getImageViewFieldValue(imageView, "mMaxWidth");
            }
            if (width <= 0)
            {
                width = displayMetrics.widthPixels;
            }
            int height = imageView.getHeight();
            if (height <= 0)
            {
                height = lp.height;
            }
            if (height <= 0)
            {
                height = getImageViewFieldValue(imageView, "mMaxHeight");
            }
            if (height <= 0)
            {
                height = displayMetrics.heightPixels;
            }
            imageSize.width = width;
            imageSize.height = height;
            return imageSize;
        }
        public static class ImageSize
        {
            int width;
            int height;
        }
    
        private static int getImageViewFieldValue(Object object, String fieldName)
        {
            int value = 0;
            try
            {
                Field field = ImageView.class.getDeclaredField(fieldName);
                field.setAccessible(true);
                int fieldValue = field.getInt(object);
                if (fieldValue > 0 && fieldValue < Integer.MAX_VALUE)
                {
                    value = fieldValue;
                }
            } catch (Exception e)
            {
            }
            return value;
        }
    }
    

    2.4

    package com.zhy.utils;
    import java.io.BufferedInputStream;
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.BitmapFactory.Options;
    import android.util.Log;
    import android.widget.ImageView;
    import com.zhy.utils.ImageSizeUtil.ImageSize;
    public class DownloadImgUtils
    {
    
        public static boolean downloadImgByUrl(String urlStr, File file)
        {
            FileOutputStream fos = null;
            InputStream is = null;
            try
            {
                URL url = new URL(urlStr);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                is = conn.getInputStream();
                fos = new FileOutputStream(file);
                byte[] buf = new byte[512];
                int len = 0;
                while ((len = is.read(buf)) != -1)
                {
                    fos.write(buf, 0, len);
                }
                fos.flush();
                return true;
            } catch (Exception e)
            {
                e.printStackTrace();
            } finally
            {
                try
                {
                    if (is != null)
                        is.close();
                } catch (IOException e)
                {
                }
                try
                {
                    if (fos != null)
                        fos.close();
                } catch (IOException e)
                {
                }
            }
            return false;
        }
    
        public static Bitmap downloadImgByUrl(String urlStr, ImageView imageview)
        {
            FileOutputStream fos = null;
            InputStream is = null;
            try
            {
                URL url = new URL(urlStr);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                is = new BufferedInputStream(conn.getInputStream());
                is.mark(is.available());
                Options opts = new Options();
                opts.inJustDecodeBounds = true;
                Bitmap bitmap = BitmapFactory.decodeStream(is, null, opts);
    
                ImageSize imageViewSize = ImageSizeUtil.getImageViewSize(imageview);
                opts.inSampleSize = ImageSizeUtil.caculateInSampleSize(opts,
                        imageViewSize.width, imageViewSize.height);
                opts.inJustDecodeBounds = false;
                is.reset();
                bitmap = BitmapFactory.decodeStream(is, null, opts);
                conn.disconnect();
                return bitmap;
            } catch (Exception e)
            {
                e.printStackTrace();
            } finally
            {
                try
                {
                    if (is != null)
                        is.close();
                } catch (IOException e)
                {
                }
                try
                {
                    if (fos != null)
                        fos.close();
                } catch (IOException e)
                {
                }
            }
            return null;
        }
    }
    

    3.1

    package com.cascade;
    
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.List;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.res.AssetManager;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.Display;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.BaseAdapter;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.ListView;
    import android.widget.ScrollView;
    
    import com.cascade.DrawableManager.ImageCallback;
    
    public class TestCascadeActivity extends Activity {
        private static final String TAG = "TestCascadeActivity";
    
        private LinearLayout llCcasecade;
        private LinearLayout lvCasecade1;
        private LinearLayout lvCasecade2;
        private LinearLayout lvCasecade3;
    
        private Display display;
        private AssetManager assetManager;
        private List<String> iamgePaths;
        private static final String imgspath = "imgs";
        private int casecadeWidth;
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main_temp);
            display = this.getWindowManager().getDefaultDisplay();
            casecadeWidth = display.getWidth()/3;
            assetManager = this.getAssets();
            findView();
        }
    
        private void findView(){
            llCcasecade = (LinearLayout)this.findViewById(R.id.llCcasecade);
            lvCasecade1 = (LinearLayout)this.findViewById(R.id.casecade1);
            lvCasecade2 = (LinearLayout)this.findViewById(R.id.casecade2);
            lvCasecade3 = (LinearLayout)this.findViewById(R.id.casecade3);
            LayoutParams lp1 = lvCasecade1.getLayoutParams();
            lp1.width = casecadeWidth;
            lvCasecade1.setLayoutParams(lp1);
    
            LayoutParams lp2 = lvCasecade2.getLayoutParams();
            lp2.width = casecadeWidth;
            lvCasecade2.setLayoutParams(lp2);
    
            LayoutParams lp3 = lvCasecade3.getLayoutParams();
            lp3.width = casecadeWidth;
            lvCasecade3.setLayoutParams(lp3);
    
            try {
                iamgePaths = Arrays.asList(assetManager.list("imgs"));
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            int j = 0;
            for (int i = 0; i < iamgePaths.size(); i++) {
                addImgToCasecade(iamgePaths.get(i), j);
                j++;
                if(j>=3) j = 0;
            }
    
        }
    
        private void addImgToCasecade(String filename,int j){
            ImageView iv = (ImageView)LayoutInflater.from(this).inflate(R.layout.item_temp, null);
            if(j==0){
                lvCasecade1.addView(iv);
            }else if(j==1){
                lvCasecade2.addView(iv);
            }else{
                lvCasecade3.addView(iv);
            }
            String imgPath = imgspath+"/"+filename;
            iv.setTag(imgPath);
            Drawable drawable = DrawableManager.getInstance().fetchDrawableOnThread(imgPath, assetManager, new ImageCallback() {
                @Override
                public void imageLoaded(Drawable imageDrawable, String imageUrl) {
                    ImageView iv = (ImageView)llCcasecade.findViewWithTag(imageUrl);
                    if(iv!=null && imageDrawable!=null){
                        int oldwidth = imageDrawable.getIntrinsicWidth();
                        int oldheight = imageDrawable.getIntrinsicHeight();
                        LayoutParams lp = iv.getLayoutParams();
                        lp.height = (oldheight * casecadeWidth)/oldwidth;
                        iv.setPadding(0, 2, 0, 0);
                        iv.setLayoutParams(lp);
                        iv.setImageDrawable(imageDrawable);
                    }
                }
            });
            if(drawable!=null){
                int oldwidth = drawable.getIntrinsicWidth();
                int oldheight = drawable.getIntrinsicHeight();
                LayoutParams lp = iv.getLayoutParams();
                lp.height = (oldheight * casecadeWidth)/oldwidth;
                iv.setPadding(0, 2, 0, 0);
                iv.setLayoutParams(lp);
                iv.setImageDrawable(drawable);
            }
    
        }
    
    }

    3.2

    package com.cascade;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.HashMap;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    import android.content.res.AssetManager;
    import android.graphics.drawable.Drawable;
    import android.os.Handler;
    import android.os.Message;
    import android.util.Log;
    
    public class DrawableManager {
    
        private static Map<String, Drawable> drawableMap = new LinkedHashMap<String, Drawable>();
        private static DrawableManager instance;
    
        private DrawableManager() {
        }
    
        public static DrawableManager getInstance() {
            if (instance == null) {
                instance = new DrawableManager();
            }
            return instance;
        }
    
        public void clear() {
            if (drawableMap != null) {
                drawableMap.clear();
                drawableMap = null;
            }
            Log.d(this.getClass().getSimpleName(), "clear image hashmap");
        }
    
    
        public Drawable fetchDrawableOnThread(final String urlString,final AssetManager assetManager,
                final ImageCallback imageCallback) {
            if (drawableMap == null) {
                drawableMap = new HashMap<String, Drawable>();
            }
            if (drawableMap.containsKey(urlString)) {
                return drawableMap.get(urlString);
            }
            final Handler handler = new Handler() {
                @Override
                public void handleMessage(Message message) {
                    imageCallback.imageLoaded((Drawable) message.obj, urlString);
                }
            };
    
            Thread thread = new Thread() {
                @Override
                public void run() {
                    Drawable drawable = fetchDrawable(urlString,assetManager);
                    Message message = handler.obtainMessage(1, drawable);
                    handler.sendMessage(message);
                }
            };
            thread.start();
            return null;
        }
    
    
        private Drawable fetchDrawable(String urlString,AssetManager assetManager) {
            if (drawableMap.containsKey(urlString)) {
                return drawableMap.get(urlString);
            }
    
            Log.d(this.getClass().getSimpleName(), "image url:" + urlString);
            InputStream is = null;
            try {
                is = assetManager.open(urlString);
                Drawable drawable = Drawable.createFromStream(is, "src");
                if (drawableMap == null) {
                    drawableMap = new HashMap<String, Drawable>();
                }
                drawableMap.put(urlString, drawable);
                return drawable;
            } 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;
        }
    
    
        public Drawable getDrawable(String urlkey) {
            return drawableMap.get(urlkey);
        }
    
        public interface ImageCallback {
            public void imageLoaded(Drawable imageDrawable, String imageUrl);
        }
    
         public void remove(String key){
             if(drawableMap.containsKey(key))
                 drawableMap.remove(key);
         }
    }

    4.1

    package com.dodowaterfall;
    
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    import com.dodowaterfall.LazyScrollView.OnScrollListener;
    
    import android.app.Activity;
    import android.content.Context;
    import android.content.res.AssetManager;
    import android.os.Bundle;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.Display;
    import android.view.LayoutInflater;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    
    public class MainActivity extends Activity {
    
        private LazyScrollView waterfall_scroll;
        private LinearLayout waterfall_container;
        private ArrayList<LinearLayout> waterfall_items;
        private Display display;
        private AssetManager assetManager;
        private List<String> image_filenames;
        private final String image_path = "images";
    
        private int itemWidth;
    
        private int column_count = 3;// 显示列数
        private int page_count = 15;// 每次加载15张图片
    
        private int current_page = 0;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
    
            display = this.getWindowManager().getDefaultDisplay();
            itemWidth = display.getWidth() / column_count;// 根据屏幕大小计算每列大小
            assetManager = this.getAssets();
    
            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() {
                    // 滚动中
                    Log.d("LazyScroll", "Scroll");
                }
    
                @Override
                public void onBottom() {
                    // 滚动到最低端
                    AddItemToContainer(++current_page, page_count);
                }
            });
    
            waterfall_container = (LinearLayout) this
                    .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 itemParam = new LinearLayout.LayoutParams(
                        itemWidth, LayoutParams.WRAP_CONTENT);
                // itemParam.width = itemWidth;
                // itemParam.height = 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(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 imagecount = image_filenames.size();
            for (int i = pageindex * pagecount; i < pagecount * (pageindex + 1)
                    && i < imagecount; 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.waterfallitem, 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.2

    package com.dodowaterfall;
    //来自:http://blog.csdn.net/listening_music/article/details/7192629
    import android.content.Context;
    import android.os.Handler;
    import android.os.Message;
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.ScrollView;
    
    public class LazyScrollView extends ScrollView{
        private static final String tag="LazyScrollView";
        private Handler handler;
        private View view;
        public LazyScrollView(Context context) {
            super(context);
            // TODO Auto-generated constructor stub
        }
        public LazyScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
            // TODO Auto-generated constructor stub
        }
        public LazyScrollView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            // TODO Auto-generated constructor stub
        }
        //这个获得总的高度
        public int computeVerticalScrollRange(){
            return super.computeHorizontalScrollRange();
        }
        public int computeVerticalScrollOffset(){
            return super.computeVerticalScrollOffset();
        }
        private void init(){
    
            this.setOnTouchListener(onTouchListener);
            handler=new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    // process incoming messages here
                    super.handleMessage(msg);
                    switch(msg.what){
                    case 1:
                        if(view.getMeasuredHeight() <= getScrollY() + getHeight()) {
                            if(onScrollListener!=null){
                                onScrollListener.onBottom();
                            }
    
                        }else if(getScrollY()==0){
                            if(onScrollListener!=null){
                                onScrollListener.onTop();
                            }
                        }
                        else{
                            if(onScrollListener!=null){
                                onScrollListener.onScroll();
                            }
                        }
                        break;
                    default:
                        break;
                    }
                }
            };
    
        }
    
          OnTouchListener onTouchListener=new OnTouchListener(){
    
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    // TODO Auto-generated method stub
                    switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        break;
                    case MotionEvent.ACTION_UP:
                        if(view!=null&&onScrollListener!=null){
                            handler.sendMessageDelayed(handler.obtainMessage(1), 200);
                        }
                        break;
    
                    default:
                        break;
                    }
                    return false;
                }
    
            };
    
            /**
             * 获得参考的View,主要是为了获得它的MeasuredHeight,然后和滚动条的ScrollY+getHeight作比较。
             */
            public void getView(){
                this.view=getChildAt(0);
                if(view!=null){
                    init();
                }
            }
    
            /**
             * 定义接口
             * @author admin
             *
             */
            public interface OnScrollListener{
                void onBottom();
                void onTop();
                void onScroll();
            }
            private OnScrollListener onScrollListener;
            public void setOnScrollListener(OnScrollListener onScrollListener){
                this.onScrollListener=onScrollListener;
            }
    }
    

    4.3

    package com.dodowaterfall;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.ref.WeakReference;
    import java.util.HashMap;
    
    import android.content.res.AssetManager;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.graphics.drawable.Drawable;
    import android.os.AsyncTask;
    import android.util.Log;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.ImageView;
    
    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);
    
        }
    
        @Override
        protected Bitmap doInBackground(TaskParam... params) {
    
            param = params[0];
            return loadImageFile(param.getFilename(), param.getAssetManager());
        }
    
        private Bitmap loadImageFile(final String filename,
                final AssetManager manager) {
            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;
        }
    
        @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();
                        LayoutParams lp = imageView.getLayoutParams();
                        lp.height = (height * param.getItemWidth()) / width;// 调整高度
    
                        imageView.setLayoutParams(lp);
    
                        imageView.setImageBitmap(bitmap);
    
                    }
    
                }
            }
        }
    }

    4.4

    package com.dodowaterfall;
    
    import android.content.res.AssetManager;
    
    public class TaskParam {
        private String filename;
        private AssetManager assetManager;
        private int ItemWidth;
    
        public String getFilename() {
            return filename;
        }
    
        public void setFilename(String filename) {
            this.filename = filename;
        }
    
        public AssetManager getAssetManager() {
            return assetManager;
        }
    
        public void setAssetManager(AssetManager assetManager) {
            this.assetManager = assetManager;
        }
    
        public int getItemWidth() {
            return ItemWidth;
        }
    
        public void setItemWidth(int itemWidth) {
            ItemWidth = itemWidth;
        }
    }
    

    4.5

    package com.dodowaterfall;
    
    import java.io.BufferedInputStream;
    import java.io.IOException;
    import java.lang.ref.ReferenceQueue;
    import java.lang.ref.SoftReference;
    import java.util.Hashtable;
    
    import android.content.Context;
    import android.content.res.AssetManager;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    /**
     * 防止溢出
     *
     */
    public class BitmapCache {
        static private BitmapCache cache;
        /** 用于Chche内容的存储 */
        private Hashtable<String, BtimapRef> bitmapRefs;
        /** 垃圾Reference的队列(所引用的对象已经被回收,则将该引用存入队列中) */
        private ReferenceQueue<Bitmap> q;
    
        /**
         * 继承SoftReference,使得每一个实例都具有可识别的标识。
         */
        private class BtimapRef extends SoftReference<Bitmap> {
            private String _key = "";
    
            public BtimapRef(Bitmap bmp, ReferenceQueue<Bitmap> q, String key) {
                super(bmp, q);
                _key = key;
            }
        }
    
        private BitmapCache() {
            bitmapRefs = new Hashtable<String, BtimapRef>();
            q = new ReferenceQueue<Bitmap>();
    
        }
    
        /**
         * 取得缓存器实例
         */
        public static BitmapCache getInstance() {
            if (cache == null) {
                cache = new BitmapCache();
            }
            return cache;
    
        }
    
        /**
         * 以软引用的方式对一个Bitmap对象的实例进行引用并保存该引用
         */
        private void addCacheBitmap(Bitmap bmp, String key) {
            cleanCache();// 清除垃圾引用
            BtimapRef ref = new BtimapRef(bmp, q, key);
            bitmapRefs.put(key, ref);
        }
    
        /**
         * 依据所指定的文件名获取图片
         */
        public Bitmap getBitmap(String filename, AssetManager assetManager) {
    
            Bitmap bitmapImage = null;
            // 缓存中是否有该Bitmap实例的软引用,如果有,从软引用中取得。
            if (bitmapRefs.containsKey(filename)) {
                BtimapRef ref = (BtimapRef) bitmapRefs.get(filename);
                bitmapImage = (Bitmap) ref.get();
            }
            // 如果没有软引用,或者从软引用中得到的实例是null,重新构建一个实例,
            // 并保存对这个新建实例的软引用
            if (bitmapImage == null) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inTempStorage = new byte[16 * 1024];
    
                // bitmapImage = BitmapFactory.decodeFile(filename, options);
                BufferedInputStream buf;
                try {
                    buf = new BufferedInputStream(assetManager.open(filename));
                    bitmapImage = BitmapFactory.decodeStream(buf);
                    this.addCacheBitmap(bitmapImage, filename);
                } catch (IOException e) {
    
                    e.printStackTrace();
                }
    
            }
    
            return bitmapImage;
        }
    
        private void cleanCache() {
            BtimapRef ref = null;
            while ((ref = (BtimapRef) q.poll()) != null) {
                bitmapRefs.remove(ref._key);
            }
        }
    
        // 清除Cache内的全部内容
        public void clearCache() {
            cleanCache();
            bitmapRefs.clear();
            System.gc();
            System.runFinalization();
        }
    
    }
    
    展开全文
  • WaterFall

    2007-06-29 14:22:22
    我制作的瀑布
  • 非常棒的Waterfall Layout自适应图片瀑布流无限加载代码,自适应浏览器宽度,电脑、平板和手机端效果都不错。 文章来自 陌佑网 ym.tenpic.cn 转载请保留本链接,谢谢!
  • waterfall无限动态加载图片支持手机移动端的瀑布流插件
  • waterfall

    2016-08-11 17:34:43
    http://www.cnblogs.com/2050/archive/2012/05/03/2480702.html

    插件:http://www.jq22.com/jquery-info9336

    http://www.cnblogs.com/2050/archive/2012/05/03/2480702.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            #container {
                border: 1px solid red;
                margin: 50px auto 0;
                position: relative;
            }
    
            #container img {
                position: absolute;
            }
    
            #loader {
                width: 100%;
                height: 60px;
                background: url('loader.gif') no-repeat center #FFF;
                position: fixed;
                bottom: 0;
                left: 0;
                display: none;
            }
    
        </style>
    </head>
    
    <body>
    <div id="container"></div>
    <div id="loader"></div>
    <!--<img onerror="javascript:this.src = 'default.jpg';" alt="">-->
    </body>
    <script src="../../jquery-1.11.3.min.js"></script>
    <script>
    
        $(function () {
            var $oContainer = $('#container'),
                    $oLoader = $('#loader'),
                    iWidth = 200,
                    iSpace = 10,
                    iOuterWidth = iWidth + iSpace,
                    iCells = 0,
                    sUrl = 'http://www.wookmark.com/api/json/popular?callback=?',
                    iPage = 0,
                    iBtn = true,
                    arrCells = [];
    
    
            setCellsAndContainer();
            /*init top and left*/
            initCellTopAndLeft();
    
            getData();
    
            $(window).on('scroll', function () {
                getDataAtBottom();
            });
    
            $(window).on('resize', function () {
                /*优化处理setCells();只有当列数发生变化,才调用,否则return*/
                var iOldCells = iCells;
                setCellsAndContainer();
    
                if(iOldCells == iCells){
                    return;
                }
    
                getDataAtBottom();
    
                /*init top and left*/
                initCellTopAndLeft();
                var $aImgs = $oContainer.find('img');
                $aImgs.each(function () {
                    //获取最短列的位置
                    var iMinIndex = getShortestIndex();
                    $(this).animate({
                        left: arrCells[iMinIndex].left,
                        top: arrCells[iMinIndex].top
                    });
                    arrCells[iMinIndex].top += $(this).height() + 10;
                });
            });
    
    
            function getData() {
                if (!iBtn) {
                    return;
                }
                    iBtn = false;
                    iPage++;
                    $.getJSON(sUrl, {page:iPage}, function (data) {
                        $('#loader').show();
                        //data is a Array
                        $.each(data, function (index, obj) {
                            var $oImg = $('<img onerror="javascript:this.src=\'default.jpg\';this.onerror=null">');
    
    
                            var iHeight = iWidth / obj.width * obj.height;
    
                            $oImg.css({
                                width: iWidth,
                                height: iHeight ? iHeight : 240 //防止iHeight没有值
                            });
    
                            //获取最短列的位置
                            var iMinIndex = getShortestIndex();
    
                            $oImg.css({
                                left: arrCells[iMinIndex].left,
                                top: arrCells[iMinIndex].top
                            });
    
    
    
                            arrCells[iMinIndex].top += iHeight + 10;
    
    
                            $oContainer.append($oImg);
    
                            var objImg = new Image();
    
                            objImg.onload = function(){
                                $oImg.attr('src', this.src);
                            }
                            $oImg.attr('src', obj.preview);
    
                            setTimeout(function() {
                                $('#loader').hide();
                            },1000);
    
                            iBtn = true;
                        })
                    });
    
    
    
            }
    
            function getDataAtBottom() {
                var iShortestIndex = getShortestIndex();
                var iH = $(window).scrollTop() + $(window).innerHeight();
                document.title = iH + ':' + (arrCells[iShortestIndex].top + 50);
                if (arrCells[iShortestIndex].top + $oContainer.offset().top <= iH) {
                    getData();
                }
            }
    
    
            function getShortestIndex() {
                var iv = arrCells[0].top;
                var _index = 0;
                for (var i = 1; i < arrCells.length; i++) {
                    if (arrCells[i].top < iv) {
                        _index = i;
                    }
                }
                return _index;
            }
    
            function initCellTopAndLeft() {
                for (var i = 0; i < iCells; i++) {
                    arrCells[i] = {};
                    arrCells[i].top = 0;
                    arrCells[i].left = i * iOuterWidth;
                }
            }
    
    
            function setCellsAndContainer() {
                if (iCells < 3) {
                    iCells = 3;
                }
                else if (iCells > 6) {
                    iCells = 6;
                }
                iCells = Math.floor($(window).innerWidth() / iOuterWidth);
                $oContainer.css('width', iOuterWidth * iCells - iSpace);
            }
    
        })
    </script>
    </html>
    展开全文
  • 一、安装Waterfall npm install vue-waterfall-plugin -s 二、在组件中引入并使用 <template> <div> <Waterfall ref="waterfall" :list="lotList" :gutter="13" backgroundColor="#ffffff" :...

    一、安装Waterfall

    npm install vue-waterfall-plugin -s
    

    二、在组件中引入并使用

    <template>
        <div>
             <Waterfall ref="waterfall" :list="lotList" :gutter="13"  backgroundColor="#ffffff" 
        :breakpoints="{500: { rowPerView: 2,}}">
            <template slot="item" slot-scope="props">
                     <div class="water" :class="block?'showWater':''">
                         <img :src="props.data.mediumUrl" alt=""  @load="$refs.waterfall.refresh()" style="width:100%">
                         <div class="d-flex flex-wrap">
                             <div style="color:#000000;font-size:0.28rem;padding:0 0.2rem">
                               <span class="com-color" style="margin-right:0.2rem;display:inline-block">Lot {{props.data.lotNum}}</span><span style="margin-right:0.13rem">{{props.data.lotAuthor}}</span><span>{{props.data.createYear}}</span><span>{{props.data.lotName}}</span>
                             </div>
                         </div>
                         <div class="com-color" style="padding-left:0.2rem;margin-top:0.1rem"><span>估价 </span>&yen {{props.data.assessValue|currency}} - {{props.data.assessEndValue|currency}}</div>
                     </div>
                 </template>
             </Waterfall>
        </div>
    </template>
    <script>
           import Waterfall from "vue-waterfall-plugin";
           import {otlist} from "./api/special"
          export default({
    	      components:{
    	            Waterfall:Waterfall
    	        },
                data(){
                     param:{
                       specId:75,
                      orderColumn:1,
                      direction:'asc',//asc升序 desc降序
                      size:10,
                      current:1,
                      lotName:null,
                    },
                    lotList:[],
                },
                mounted(){
                      var  that = this;
                      lotlist(that.param).then(res=>{
                        that.specList = res.data.data.records;
                    })
                }
          })
    </script>
    <style lang="scss" scoped>
         .com-color{color:#A57A44;}
         .water{
            display:none;
            text-align: left;
            color:#000000;
            padding-bottom:0.15rem;
            box-shadow: 0 1px 3px rgba(34, 25, 25, .4);
            -moz-box-shadow: 0 1px 3px rgba(34, 25, 25, .4);
            -webkit-box-shadow: 0 1px 3px rgba(34, 25, 25, .4);
            filter: progid:DXImageTransform.Microsoft.Shadow(color = #adacac, direction = 135, strength = 2);
            .top{
                margin: 0.1rem 0;
                // white-space: nowrap;
                // overflow: hidden;
                // text-overflow: ellipsis;
            }
            &.showWater{display:block}
        }
    </style>
    

    三、效果图如下

    在这里插入图片描述
    注意:第一次请求展示数据的时候图片会重叠具体原因我现在还不清楚,只能用个定时器延迟展示瀑布流模块才能正常使用,有明白原因的伙伴欢迎留言告知

    展开全文
  • Waterfall Waterfall is a fork of the well-known BungeeCord server teleportation suite. Waterfall focuses on three main areas: Stability: Waterfall aims to be stable. We will achieve this through ...
  • Android WaterFall

    热门讨论 2013-09-03 14:26:59
    Android上实现的瀑布流WaterFall效果
  • waterfall字体

    2019-10-22 21:48:05
    waterfall字体是一款用于海报设计方面的字体
  • origin 三维坐标中 多条曲线 waterfall 绘图
  • 最近做一个项目需要用到jQuery Waterfall插件-瀑布流图片显示 jquery waterfall plugin,like Pinterest 、 huaban.com 、 faxianla.com 下载地址: waterfall plugin
  • vue-waterfall-easy 2.x This is a vue component that contains waterfall flow layout and infinite scroll loading Compared to other implementations,there is no need to specify the width and height of ...
  • 插件描述:jq-waterfall是一款仿Pinterest网站的响应式无限动态加载图片瀑布流特效jQuery插件。演示地址:http://www.jq22.com/jquery-info9336
  • dcard_pic_waterfall 瀑布流呈现dcard图片,点下以lightbox呈现。
  • waterfall是一款响应式无限动态加载图片瀑布流特效jQuery插件。 waterfall瀑布流特效使用ajax调用来动态加载图片,达到无限加载的效果。 使用方法 使用这个瀑布流插件需要引入jQuery.min.js和jquery.waterfall.js...
  • waterfall model

    2018-12-14 19:56:01
    advantage: 1、provide checkpoints by stages for the ...2、waterfall model can be applied in iteration model disadvantage: 1、The division of each stage is completely fixed, and a large number...
  • 瀑布流waterfall

    2017-09-12 16:07:37
    瀑布流布局插件waterfall,这是基于jquery,类似于 Pinterest、花瓣、发现啦。直接引用js就好。兼容ie8等浏览器
  • vue waterfall vue2-瀑布 (vue2-waterfall) An AutoHeight Waterfall Component For Vue2. Vue2的AutoHeight Waterfall组件。 View demo 查看演示 Download Source 下载源 安装 (Install) 安装vue2-waterfall ...
  • 瀑布流 waterfall

    2012-07-16 13:39:46
    瀑布流 waterfall 随屏加载 人人街 蘑菇街
  • waterfall 瀑布流 demo

    2017-09-22 08:52:00
    jquery 实现图片瀑布流加载,附件中含有全部源代码,waterfall.js为对应的js代码。images中存放图片信息,demo中图片加载为静态加载,后续可以改成ajax服务请求更新。
  • vue-waterfall2 Auto adaption for width and height High degree of customization Support lazy load(attribute with lazy-src) Apply to PC/mobile If you have some questions,welcome to describe issues、...
  • vue-waterfall

    千次阅读 2017-09-27 14:58:35
    vue中的一个瀑布流插件推荐vue-waterfall
  • waterfall waterfall demos 在原来的demo上稍微修改了
  • waterfall, Duitang Waterfall Woo. (堆糖瀑布流)
  • Waterfall & Scrum

    2021-07-21 18:05:00
    Introduction to Scrum [Scrum vs Waterfall] Waterfall Planà Buid àTestà Review àDeploy 瀑布式开发通常会花几个月时间来规划产品 Waterfall typically goes through a lengthy planning process, which ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,407
精华内容 3,762
关键字:

waterfall图