一、效果图如下
二、关键代码讲解
本例参考别人写的一个demo,这里写上个人的理解,方便日后使用方便
1、准备工作
第三方框架:universal-image-loader-1.8.6.jar,复制到libs中
第三方引用library:MultiColumnListView_HUEWU
2、配置文件
添加联网权限
3、初始化图片加载库
这里引用了universal-image-loader-1.8.6.jar,但是具体使用之前,还需要进行初始化工作,初始化工作可以在Application类中进行,也可以在第一个Activity中进行,一般习惯于在Application类中进行
初始化主要有三个步骤:
1)初始化ImageLoaderConfiguration
File cacheDir = StorageUtils.getOwnCacheDirectory(context, "topnews/Cache");//获取到缓存的目录地址 ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context) .memoryCacheExtraOptions(480, 800) // max width, max height,即保存的每个缓存文件的最大长宽 //.discCacheExtraOptions(480, 800, CompressFormat.JPEG, 75, null) // Can slow ImageLoader, use it carefully (Better don't use it)设置缓存的详细信息,最好不要设置这个 .threadPoolSize(3)//线程池内加载的数量 .threadPriority(Thread.NORM_PRIORITY - 2) .denyCacheImageMultipleSizesInMemory() //.memoryCache(new UsingFreqLimitedMemoryCache(2 * 1024 * 1024)) // You can pass your own memory cache implementation你可以通过自己的内存缓存实现 .memoryCacheSize(2 * 1024 * 1024) .discCacheSize(50 * 1024 * 1024) .discCacheFileNameGenerator(new Md5FileNameGenerator())//将保存的时候的URI名称用MD5 加密 .discCacheFileNameGenerator(new HashCodeFileNameGenerator())//将保存的时候的URI名称用HASHCODE加密 .tasksProcessingOrder(QueueProcessingType.LIFO) .discCacheFileCount(100) //缓存的File数量 .discCache(new UnlimitedDiscCache(cacheDir))//自定义缓存路径 .defaultDisplayImageOptions(DisplayImageOptions.createSimple()) .imageDownloader(new BaseImageDownloader(context, 5 * 1000, 30 * 1000)) // connectTimeout (5 s), readTimeout (30 s)超时时间 .writeDebugLogs() // Remove for release app .build();
DisplayImageOptions options = new DisplayImageOptions.Builder() // // 设置图片在下载期间显示的图片 .showImageOnLoading(R.drawable.empty_photo2) // // 设置图片Uri为空或是错误的时候显示的图片 .showImageForEmptyUri(R.drawable.empty_photo2) // // 设置图片加载/解码过程中错误时候显示的图片 .showImageOnFail(R.drawable.empty_photo2).cacheInMemory(true) // 设置下载的图片是否缓存在内存中 .cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中 .considerExifParams(true).imageScaleType(ImageScaleType.EXACTLY_STRETCHED)// 设置图片以如何的编码方式显示 .bitmapConfig(Bitmap.Config.RGB_565)// 设置图片的解码类型 // .decodingOptions(android.graphics.BitmapFactory.Options // decodingOptions)//设置图片的解码配置 .considerExifParams(true) // 设置图片下载前的延迟 .delayBeforeLoading(0)//int // delayInMillis为你设置的延迟时间 // 设置图片加入缓存前,对bitmap进行设置 // 。preProcessor(BitmapProcessor preProcessor) .resetViewBeforeLoading(true)// 设置图片在下载前是否重置,复位 .displayer(new RoundedBitmapDisplayer(20))//是否设置为圆角,弧度为多少 .displayer(new FadeInBitmapDisplayer(100))// 淡入 .build();
ImageLoader.getInstance().init(config);4、相关代码
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <com.huewu.pla.lib.MultiColumnPullToRefreshListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>如果不需要下拉刷新功能,可以使用MutiColumnListView
WaterfallAdapter.java
package com.example.waterfalldemo.adapter; import java.util.ArrayList; import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.Toast; import com.example.waterfalldemo.R; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.FailReason; import com.nostra13.universalimageloader.core.assist.ImageLoadingListener; public class WaterfallAdapter extends BaseAdapter { ArrayList<String> list; Context context; private Drawable drawable; public WaterfallAdapter(ArrayList<String> list , Context context) { this.list = list; this.context = context; drawable = context.getResources().getDrawable(R.drawable.load_default); } @Override public int getCount() { return list != null ? list.size() : 0; } @Override public Object getItem(int arg0) { return null; } @Override public long getItemId(int arg0) { return 0; } @Override public View getView(final int position, View view, ViewGroup group) { final Holder holder; // 得到View if (view == null) { holder = new Holder(); LayoutInflater inflater = LayoutInflater.from(context); view = inflater.inflate(R.layout.image_item, null); holder.ivIcon = (ImageView) view.findViewById(R.id.row_icon); holder.pbLoad = (ProgressBar) view.findViewById(R.id.pb_load); view.setTag(holder); } else { holder = (Holder) view.getTag(); } String url = list.get(position); ImageLoader.getInstance().displayImage(url, holder.ivIcon, new ImageLoadingListener() { @Override public void onLoadingStarted(String imageUri, View view) { //这儿初先初始化出来image所占的位置的大小,先把瀑布流固定住,这样瀑布流就不会因为图片加载出来后大小变化了 //LayoutParams lp = (LayoutParams) holder.ivIcon.getLayoutParams(); //多屏幕适配 //int dWidth = 480; //int dHeight = 800; //float wscale = dWidth / 480.0f; //float hscale = dHeight / 800.0f; //lp.height = (int) (yourImageHeight * hscale); //lp.width = (int) (yourImageWidth * wscale); //holder.ivIcon.setLayoutParams(lp); holder.ivIcon.setImageDrawable(drawable); holder.pbLoad.setVisibility(View.VISIBLE); } @Override public void onLoadingFailed(String imageUri, View view, FailReason failReason) { String message = null; switch (failReason.getType()) { case IO_ERROR: message = "Input/Output error"; break; case DECODING_ERROR: message = "can not be decoding"; break; case NETWORK_DENIED: message = "Downloads are denied"; break; case OUT_OF_MEMORY: message = "内存不足"; Toast.makeText(context, message, Toast.LENGTH_SHORT) .show(); break; case UNKNOWN: message = "Unknown error"; Toast.makeText(context, message, Toast.LENGTH_SHORT) .show(); break; } holder.pbLoad.setVisibility(View.GONE); } @Override public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { holder.pbLoad.setVisibility(View.GONE); } @Override public void onLoadingCancelled(String paramString, View paramView) { } }); holder.ivIcon.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { // TODO Auto-generated method stub Log.i("TAG", "image click"); } }); return view; } } class Holder { public ImageView ivIcon; public ProgressBar pbLoad; }MainActivity.java
package com.example.waterfalldemo; import java.util.ArrayList; import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import com.example.waterfalldemo.adapter.WaterfallAdapter; import com.huewu.pla.lib.MultiColumnPullToRefreshListView; import com.huewu.pla.lib.MultiColumnPullToRefreshListView.OnRefreshListener; import com.nostra13.universalimageloader.cache.memory.impl.UsingFreqLimitedMemoryCache; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; public class MainActivity extends Activity { private MultiColumnPullToRefreshListView waterfallView;//可以把它当成一个listView //如果不想用下拉刷新这个特性,只是瀑布流,可以用这个:MultiColumnListView 一样的用法 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //初始化图片加载库 DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder() .cacheOnDisc(true)//图片存本地 .cacheInMemory(true) .displayer(new FadeInBitmapDisplayer(50)) .bitmapConfig(Bitmap.Config.RGB_565) .imageScaleType(ImageScaleType.EXACTLY) // default .build(); ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext()) .memoryCache(new UsingFreqLimitedMemoryCache(16 * 1024 * 1024)) .defaultDisplayImageOptions(defaultOptions).build(); ImageLoader.getInstance().init(config); waterfallView = (MultiColumnPullToRefreshListView) findViewById(R.id.list); ArrayList<String> imageList = new ArrayList<String>(); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043531502.jpg"); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043532264.jpg"); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043533581.jpg"); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043533571.jpg"); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043534672.jpg"); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043534854.jpg"); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043535929.jpg"); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043535784.jpg"); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043536626.jpg"); imageList.add("http://www.yjz9.com/uploadfile/2012/1219/20121219043536244.jpg"); WaterfallAdapter adapter = new WaterfallAdapter(imageList, this); waterfallView.setAdapter(adapter); waterfallView.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh() { // TODO Auto-generated method stub //下拉刷新要做的事 //刷新完成后记得调用这个 waterfallView.onRefreshComplete(); } }); } }