代码下载地址
先看主页面的布局ac_home.xml,里面只有一个Button,进入ListView界面展现图片列表
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:onClick="onImageListClick"
android:text="@string/button_image_list" />
</LinearLayout>
</ScrollView>
先看一些数据类Constants--一些图片的链接地址
package com.nostra13.example.universalimageloader;
public final class Constants {
// 一堆图片链接
public static final String[] IMAGES = new String[] {
// Heavy images
"http://img.mukewang.com/55237dcc0001128c06000338-300-170dd.jpg",
"http://img.mukewang.com/55237dcc0001128c06000338.jpg",
"http://img.mukewang.com/55249cf30001sdffae8a06000338-300-170.jpg",
"http://img.mukewang.com/55249csfsf30001ae8a06000338.jpg",
"http://img.mukewang.com/5523711700016d1606000338-300-170.jpg",
"http://img.mukewang.com/5523711700016d1606000338.jpg",
"http://img.mukewang.com/551e470500018dd806000338-300-170.jpg",
"http://img.mukewang.com/551e470500018dd806000338.jpg",
"http://img.mukewang.com/551de0570001134f06000338-300-170.jpg",
"http://img.mukewang.com/551de0570001134f06000338.jpg",
"http://img.mukewang.com/552640c300018a9606000338-300-170.jpg"
};
private Constants() {
}
// 额外类
public static class Extra {
public static final String IMAGES = "com.nostra13.example.universalimageloader.IMAGES";
public static final String IMAGE_POSITION = "com.nostra13.example.universalimageloader.IMAGE_POSITION";
}
}
在看UILApplication这里面的imageLoader配置初始化
UILApplication
package com.nostra13.example.universalimageloader;
import android.app.Application;
import android.content.Context;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
public class UILApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
initImageLoader(getApplicationContext());
}
public static void initImageLoader(Context context) {
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context)
// 3个线程池
.threadPriority(Thread.NORM_PRIORITY - 2)
.threadPoolSize(3)
// 不缓存图片的多种尺寸在内存中
.denyCacheImageMultipleSizesInMemory()
// 将保存的时候的URI名称用MD5
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)//设置加载显示图片队列进程
.writeDebugLogs() // Remove for release app
.build();
ImageLoader.getInstance().init(config);
}
}
接下来application也需要进行相应的变化
<!-- 网络访问权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 文件写入SD卡权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".UILApplication"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".HomeActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".ImageListActivity"
android:label="@string/ac_name_image_list" />
<activity
android:name=".ImagePagerActivity"
android:label="@string/ac_name_image_pager" />
</application>
接下来看主界面的代码
HomeActivity
package com.nostra13.example.universalimageloader;
import static com.nostra13.example.universalimageloader.Constants.IMAGES;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.AbsListView;
import com.nostra13.example.universalimageloader.Constants.Extra;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.utils.L;
public class HomeActivity extends Activity {
protected ImageLoader imageLoader = ImageLoader.getInstance();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_home);
}
// 点击进入ListView展示界面
public void onImageListClick(View view) {
Intent intent = new Intent(this, ImageListActivity.class);
intent.putExtra(Extra.IMAGES, IMAGES);
startActivity(intent);
}
@Override
public void onBackPressed() {
imageLoader.stop(); // 停止加载图片
super.onBackPressed();
}
}
接下来就进入了ListView展示界面了,布局文件就是一个listView视图
ac_image_list.xml
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
listview的item布局item_list_image.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/image"
android:layout_width="72dip"
android:layout_height="72dip"
android:layout_margin="3dip"
android:adjustViewBounds="true"
android:contentDescription="@string/descr_image"
android:scaleType="centerCrop" />
<TextView
android:id="@+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:layout_marginLeft="20dip"
android:textSize="22sp" />
</LinearLayout>
ImageListActivity 接下来看listView界面的主要代码了
package com.nostra13.example.universalimageloader;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.nostra13.example.universalimageloader.Constants.Extra;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.ImageLoadingListener;
import com.nostra13.universalimageloader.core.assist.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
public class ImageListActivity extends Activity {
protected ImageLoader imageLoader = ImageLoader.getInstance();
DisplayImageOptions options; // DisplayImageOptions是用于设置图片显示的类
String[] imageUrls; // 图片路径
protected AbsListView listView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_image_list);
Bundle bundle = getIntent().getExtras();
imageUrls = bundle.getStringArray(Extra.IMAGES);
// 使用DisplayImageOptions.Builder()创建DisplayImageOptions
options = new DisplayImageOptions.Builder()
.showStubImage(R.drawable.ic_stub) // 设置图片下载期间显示的图片
.showImageForEmptyUri(R.drawable.ic_empty) // 设置图片Uri为空或是错误的时候显示的图片
.showImageOnFail(R.drawable.ic_error) // 设置图片加载或解码过程中发生错误显示的图片
.cacheInMemory(true) // 设置下载的图片是否缓存在内存中
.cacheOnDisc(true) // 设置下载的图片是否缓存在SD卡中
.displayer(new RoundedBitmapDisplayer(20)) // 设置成圆角图片
.build(); // 创建配置过得DisplayImageOption对象
listView = (ListView) findViewById(android.R.id.list);
((ListView) listView).setAdapter(new ItemAdapter());
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// 点击列表项转入ViewPager显示界面
Intent intent = new Intent(ImageListActivity.this, ImagePagerActivity.class);
intent.putExtra(Extra.IMAGES, imageUrls);
intent.putExtra(Extra.IMAGE_POSITION, position);
startActivity(intent);
}
});
}
@Override
public void onBackPressed() {
AnimateFirstDisplayListener.displayedImages.clear();
super.onBackPressed();
}
/**
* 自定义列表项适配器
*/
class ItemAdapter extends BaseAdapter {
private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();
private class ViewHolder {
public TextView text;
public ImageView image;
}
@Override
public int getCount() {
return imageUrls.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = convertView;
final ViewHolder holder;
if (convertView == null) {
view = getLayoutInflater().inflate(R.layout.item_list_image,
parent, false);
holder = new ViewHolder();
holder.text = (TextView) view.findViewById(R.id.text);
holder.image = (ImageView) view.findViewById(R.id.image);
view.setTag(holder); // 给View添加一个格外的数据
} else {
holder = (ViewHolder) view.getTag(); // 把数据取出来
}
holder.text.setText("Item " + (position + 1)); // TextView设置文本
/**
* 显示图片 参数1:图片url 参数2:显示图片的控件 参数3:显示图片的设置 参数4:监听器
*/
imageLoader.displayImage(imageUrls[position], holder.image,
options, animateFirstListener);
return view;
}
}
/**
* 图片加载第一次显示监听器
*/
private static class AnimateFirstDisplayListener extends
SimpleImageLoadingListener {
static final List<String> displayedImages = Collections
.synchronizedList(new LinkedList<String>());
@Override
public void onLoadingComplete(String imageUri, View view,
Bitmap loadedImage) {
if (loadedImage != null) {
ImageView imageView = (ImageView) view;
// 是否第一次显示
boolean firstDisplay = !displayedImages.contains(imageUri);
if (firstDisplay) {
// 图片淡入效果
FadeInBitmapDisplayer.animate(imageView, 500);
displayedImages.add(imageUri);
}
}
}
}
}
点击listview的条目进入Viewpager界面,接下来看Viewpager的布局文件
ac_image_pager.xml、
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
item_pager_image.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="1dip" >
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:contentDescription="@string/descr_image" />
<ProgressBar
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
ImagePagerActivity 接下来看viewpager的代码了
package com.nostra13.example.universalimageloader;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.nostra13.example.universalimageloader.Constants.Extra;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.assist.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
public class ImagePagerActivity extends Activity {
private static final String STATE_POSITION = "STATE_POSITION";
DisplayImageOptions options;
ViewPager pager;
protected ImageLoader imageLoader = ImageLoader.getInstance();
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_image_pager);
Bundle bundle = getIntent().getExtras();
String[] imageUrls = bundle.getStringArray(Extra.IMAGES);
// 当前显示View的位置
int pagerPosition = bundle.getInt(Extra.IMAGE_POSITION, 0);
// 如果之前有保存用户数据
if (savedInstanceState != null) {
pagerPosition = savedInstanceState.getInt(STATE_POSITION);
}
options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.resetViewBeforeLoading(true)
.cacheOnDisc(true)
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.displayer(new FadeInBitmapDisplayer(300))
.build();
pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(new ImagePagerAdapter(imageUrls));
pager.setCurrentItem(pagerPosition); // 显示当前位置的View
}
@Override
public void onSaveInstanceState(Bundle outState) {
// 保存用户数据
outState.putInt(STATE_POSITION, pager.getCurrentItem());
}
private class ImagePagerAdapter extends PagerAdapter {
private String[] images;
private LayoutInflater inflater;
ImagePagerAdapter(String[] images) {
this.images = images;
inflater = getLayoutInflater();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public void finishUpdate(View container) {
}
@Override
public int getCount() {
return images.length;
}
@Override
public Object instantiateItem(ViewGroup view, int position) {
View imageLayout = inflater.inflate(R.layout.item_pager_image, view, false);
ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image);
final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading);
imageLoader.displayImage(images[position], imageView, options, new SimpleImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
spinner.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
String message = null;
switch (failReason.getType()) { // 获取图片失败类型
case IO_ERROR: // 文件I/O错误
message = "Input/Output error";
break;
case DECODING_ERROR: // 解码错误
message = "Image can't be decoded";
break;
case NETWORK_DENIED: // 网络延迟
message = "Downloads are denied";
break;
case OUT_OF_MEMORY: // 内存不足
message = "Out Of Memory error";
break;
case UNKNOWN: // 原因不明
message = "Unknown error";
break;
}
Toast.makeText(ImagePagerActivity.this, message, Toast.LENGTH_SHORT).show();
spinner.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
spinner.setVisibility(View.GONE); // 不显示圆形进度条
}
});
((ViewPager) view).addView(imageLayout, 0); // 将图片增加到ViewPager
return imageLayout;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
@Override
public void restoreState(Parcelable state, ClassLoader loader) {
}
@Override
public Parcelable saveState() {
return null;
}
@Override
public void startUpdate(View container) {
}
}
}