現在我們終於可以通過這個框架來實現ListView中加載圖片了,至於ViewPager還是別的,原理其實都是一樣的
一、ListView
1.布局文件
list_layout.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android:id="@+id/item_imageView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:src="@drawable/ic_launcher" /> </LinearLayout>
圖片來源類:
package com.kale.universalimageloadertest; public class PicArrays { public static String[] getPicArray() { String[] arrs = new String[]{ "http://static4.photo.sina.com.cn/middle/69670edbx9475f3f01283&690", "http://s8.sinaimg.cn/middle/6f78405exa6e437719ea7&690", "http://s3.sinaimg.cn/middle/6f78405ex9f4d66911f22&690", "http://s8.sinaimg.cn/middle/6f78405exa6e436d8f357&690", "http://s4.sinaimg.cn/middle/6f78405exa6e43621ecb3&690", "http://s10.sinaimg.cn/middle/6f78405exa0f4f335c589&690", "http://s16.sinaimg.cn/middle/6f78405ex9f4d7b2eff0f&690", "http://s7.sinaimg.cn/middle/6f78405exa6e2fa1d4ab6&690", "http://s8.sinaimg.cn/middle/6f78405exa6e2fa4b19c7&690", "http://s6.sinaimg.cn/middle/69670edbx94da12276525&690", "http://s2.sinaimg.cn/middle/69670edbx94da117f7c41&690", "http://s3.sinaimg.cn/bmiddle/6f78405exa503c5d0a462&690", "http://s6.sinaimg.cn/middle/6f78405exa72b24119765&690", "http://s11.sinaimg.cn/middle/6f78405ex9f4d5245988a&690", "http://s10.sinaimg.cn/middle/6f78405ex9f4d7b107f29&690", "http://img0.tech2ipo.com/upload/img/article/2013/03/1364556945327.png", "http://s7.sinaimg.cn/middle/6f78405eta77a260b8d96&690", "http://s3.sinaimg.cn/middle/6f78405eta77a29344d92&690", "http://s10.sinaimg.cn/middle/6f78405exa0f4f250e469&690", "http://s3.sinaimg.cn/middle/6f78405eta77a21932632&690", "http://s13.sinaimg.cn/middle/6f78405eta77a2c9a0d2c&690", "http://s9.sinaimg.cn/middle/6f78405eta77a47b89188&690", "http://s16.sinaimg.cn/middle/6f78405exa0f4f11fb58f&690", "http://img2.imgtn.bdimg.com/it/u=2449553173,1966285445&fm=23&gp=0.jpg", "http://h.hiphotos.baidu.com/baike/w%3D150/sign=406f3d00251f95caa6f596b3f9167fc5/d50735fae6cd7b89493402fd0f2442a7d9330e77.jpg" }; return arrs; } public static void main(String[] args) { System.out.println("圖片總數:"+getPicArray().length); } }
寫一個listview的適配器
這里在載入圖片的時候放入了一個動畫的效果。可見這個框架的擴展性是相當強的!!!
final private DisplayImageOptions options = getSimpleOptions(); final private ImageLoader imageLoader = ImageLoader.getInstance();
/** * * 自定義列表項適配器 * */ class ItemAdapter extends BaseAdapter { //圖片第一次加載的監聽器 private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener(); private String[] picArrs; public ItemAdapter() { // TODO 自動生成的構造函數存根 picArrs = PicArrays.getPicArray(); } private class ViewHolder { public ImageView image; } @Override public int getCount() { return picArrs.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; //通過convertView來判斷是否已經加載過了,如果沒有就加載 if (convertView == null) { view = getLayoutInflater().inflate(R.layout.list_item, parent, false); holder = new ViewHolder(); holder.image = (ImageView) view.findViewById(R.id.item_imageView); view.setTag(holder);// 給View添加一個格外的數據 } else { holder = (ViewHolder) view.getTag(); // 把數據取出來 } /** * 顯示圖片 * 參數1:圖片url * 參數2:顯示圖片的控件 * 參數3:顯示圖片的設置 * 參數4:監聽器 */ imageLoader.displayImage(picArrs[position], holder.image, options,animateFirstListener); return view; } } /** * 圖片加載第一次顯示監聽器 * @author Administrator * */ 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, 200); displayedImages.add(imageUri); } } } }
全部的Activity代碼:
package com.kale.universalimageloadertest; import java.util.Collections; import java.util.LinkedList; import java.util.List; import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ListView; import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.assist.ImageScaleType; import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer; import com.nostra13.universalimageloader.core.listener.ImageLoadingListener; import com.nostra13.universalimageloader.core.listener.PauseOnScrollListener; import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener; public class UILListActivity extends Activity{ final private DisplayImageOptions options = getSimpleOptions(); final private ImageLoader imageLoader = ImageLoader.getInstance(); @Override protected void onCreate(Bundle savedInstanceState) { // TODO 自動生成的方法存根 super.onCreate(savedInstanceState); setContentView(R.layout.list_layout); ListView listView = (ListView)findViewById(R.id.listView); /* * 3個參數-> * 1:圖片加載對象ImageLoader, * 2:控制是否在滑動過程中暫停加載圖片,如果需要暫停傳true就行了 * 3:控制猛的滑動界面的時候圖片是否加載 * */ listView.setOnScrollListener(new PauseOnScrollListener(imageLoader, false, true)); listView.setAdapter(new ItemAdapter()); } /** * 設置常用的設置項 * @return */ private DisplayImageOptions getSimpleOptions() { DisplayImageOptions options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.loading) //設置圖片在下載期間顯示的圖片 .showImageForEmptyUri(R.drawable.ic_launcher)//設置圖片Uri為空或是錯誤的時候顯示的圖片 .showImageOnFail(R.drawable.error) //設置圖片加載/解碼過程中錯誤時候顯示的圖片 .cacheInMemory(true)//設置下載的圖片是否緩存在內存中 .cacheOnDisk(true)//設置下載的圖片是否緩存在SD卡中 .imageScaleType(ImageScaleType.IN_SAMPLE_INT)//設置圖片以如何的編碼方式顯示 .considerExifParams(true) .bitmapConfig(Bitmap.Config.RGB_565)//設置圖片的解碼類型 .build();//構建完成 return options; } /** * * 自定義列表項適配器 * */ class ItemAdapter extends BaseAdapter { //圖片第一次加載的監聽器 private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener(); private String[] picArrs; public ItemAdapter() { // TODO 自動生成的構造函數存根 picArrs = PicArrays.getPicArray(); } private class ViewHolder { public ImageView image; } @Override public int getCount() { return picArrs.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; //通過convertView來判斷是否已經加載過了,如果沒有就加載 if (convertView == null) { view = getLayoutInflater().inflate(R.layout.list_item, parent, false); holder = new ViewHolder(); holder.image = (ImageView) view.findViewById(R.id.item_imageView); view.setTag(holder);// 給View添加一個格外的數據 } else { holder = (ViewHolder) view.getTag(); // 把數據取出來 } /** * 顯示圖片 * 參數1:圖片url * 參數2:顯示圖片的控件 * 參數3:顯示圖片的設置 * 參數4:監聽器 */ imageLoader.displayImage(picArrs[position], holder.image, options,animateFirstListener); return view; } } /** * 圖片加載第一次顯示監聽器 * @author Administrator * */ 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, 200); displayedImages.add(imageUri); } } } } }
通過ViewHolder和convertView配合使用,可以提高效率。這點也是我們應該學習的
二、ViewPager
viewPager_layout.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/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" />
viewpager_item.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_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/hello_world" /> <ProgressBar android:id="@+id/loading" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:visibility="gone" /> </FrameLayout>
UILViewPagerActivity.java
package com.kale.universalimageloadertest; import android.app.Activity; import android.graphics.Bitmap; import android.os.Bundle; 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.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.listener.SimpleImageLoadingListener; public class UILViewPagerActivity extends Activity { ViewPager pager; DisplayImageOptions options; ImageLoader imageLoader; private static final String STATE_POSITION = "STATE_POSITION"; @Override protected void onCreate(Bundle savedInstanceState) { // TODO 自動生成的方法存根 super.onCreate(savedInstanceState); setContentView(R.layout.viewpager_layout); // 當前顯示View的位置 */ int pagerPosition = 0; // 如果之前有保存用戶數據 if (savedInstanceState != null) { pagerPosition = savedInstanceState.getInt(STATE_POSITION); } options = getSimpleOptions(); imageLoader = ImageLoader.getInstance(); pager = (ViewPager) findViewById(R.id.viewPager); pager.setAdapter(new ImagePagerAdapter(PicArrays.getPicArray())); pager.setCurrentItem(pagerPosition); } @Override public void onSaveInstanceState(Bundle outState) { // outState.putInt(STATE_POSITION, pager.getCurrentItem()); } /** * 設置常用的設置項 * * @return */ private DisplayImageOptions getSimpleOptions() { DisplayImageOptions options = new DisplayImageOptions.Builder() .showImageOnLoading(R.drawable.loading) // 設置圖片在下載期間顯示的圖片 .showImageForEmptyUri(R.drawable.ic_launcher)// 設置圖片Uri為空或是錯誤的時候顯示的圖片 .showImageOnFail(R.drawable.error) // 設置圖片加載/解碼過程中錯誤時候顯示的圖片 .cacheInMemory(true)// 設置下載的圖片是否緩存在內存中 .cacheOnDisk(true)// 設置下載的圖片是否緩存在SD卡中 .imageScaleType(ImageScaleType.IN_SAMPLE_INT)// 設置圖片以如何的編碼方式顯示 .considerExifParams(true).bitmapConfig(Bitmap.Config.RGB_565)// 設置圖片的解碼類型 .build();// 構建完成 return options; } private class ImagePagerAdapter extends PagerAdapter { private String[] images; private LayoutInflater inflater; ImagePagerAdapter(String[] images) { this.images = images; inflater = getLayoutInflater(); } @Override public int getCount() { return images.length; } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public void destroyItem(ViewGroup container, int position, Object object) { ((ViewPager) container).removeView((View) object); } @Override public Object instantiateItem(ViewGroup view, int position) { View viewLayout = inflater.inflate(R.layout.viewpager_item, view, false); ImageView imageView = (ImageView) viewLayout .findViewById(R.id.image); final ProgressBar spinner = (ProgressBar) viewLayout .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(getApplicationContext(), 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(viewLayout, 0); // 將圖片增加到ViewPager return viewLayout; } @Override public void finishUpdate(View container) { } } }
這里ViewPager的實現是通過動態加載的方式來做的,結合了進度條。很具有實用性!以前我們用ViewPager的時候是傳入一個List<View>對象,在getView()中返回list.getindex(position)的方式來得到view對象。這里不傳入view,直接在getView()中產生一個view,然后給view中加載圖片。這種方式好處是節約了內存,要顯示的時候才判斷加載哪個對象;而壞處是沒實現預加載,所以要配合進度條。在今后的改進中應該是預加載當前viewpager左右的圖片,這樣可以流暢的顯示圖片了~
源碼下載:http://download.csdn.net/detail/shark0017/8055421
參考自:
http://blog.csdn.net/wwj_748/article/details/10079311