Universal-Image-Loader解析(三)——用ListView和ViewPager加载网络中的图片
现在我们终于可以通过这个框架来实现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
Universal-Image-Loader解析(三)——用ListView和ViewPager加载网络中的图片的更多相关文章
- Android基本控件之listView(三)<用ListView实现分页加载>
我们之前讨论了ListView的基本使用方法和ListView的优化 今天我们再来讨论一个关于ListView的一个新的东西~就是分页加载.那么什么是分页加载呢?简单点说,就是"下拉刷新&q ...
- [Android] Android 用于异步加载 ContentProvider 中的内容的机制 -- Loader 机制 (LoaderManager + CursorLoader + LoaderManager.LoaderCallbacks)
Android 用于异步加载 ContentProvider 中的内容的机制 -- Loader 机制 (LoaderManager + CursorLoader + LoaderManager.Lo ...
- Python3从零开始爬取今日头条的新闻【三、滚动到底自动加载】
Python3从零开始爬取今日头条的新闻[一.开发环境搭建] Python3从零开始爬取今日头条的新闻[二.首页热点新闻抓取] Python3从零开始爬取今日头条的新闻[三.滚动到底自动加载] Pyt ...
- listView的异步加载数据
1 public class MainActivity extends Activity { 2 3 private ListView listView; 4 private ArrayList< ...
- Flutter 开发从 0 到 1(四)ListView 下拉加载和加载更多
在<APP 开发从 0 到 1(三)布局与 ListView>我们完成了 ListView,这篇文章将做 ListView 下拉加载和加载更多. ListView 下拉加载 Flutter ...
- springboot源码解析-管中窥豹系列之BeanDefine如何加载(十三)
一.前言 Springboot源码解析是一件大工程,逐行逐句的去研究代码,会很枯燥,也不容易坚持下去. 我们不追求大而全,而是试着每次去研究一个小知识点,最终聚沙成塔,这就是我们的springboot ...
- ListView用法及加载数据时的闪烁问题和加载数据过慢问题
ListView介绍及添加数据时的闪烁问题 1. ListView类 1.1 ListView常用的基本属性: (1)FullRowSelect:设置是否行选择模式.(默认为false) 提示 ...
- ListView 上拉加载更多
ListView 上拉加载更多 首先来个效果图 界面布局 <?xml version="1.0" encoding="utf-8"?> <Re ...
- XE7 & FMX 那些年我们一起上过的控件:ListView 之 (3) 加载数据时如何显示自定义样式
本文介绍一下ListView下如何加载数据.及使用进度条反馈当前进度给用户. 注意: 原创作品,请尊重作者劳动成果,转载请注明出处!!!原文永久固定地址:http://www.cnblogs.com/ ...
随机推荐
- Java编程的逻辑 (61) - 内存映射文件及其应用 - 实现一个简单的消息队列
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- Serilog 记录日志
Serilog 记录日志 Serilog是.net里面非常不错的记录日志的库,另外一个我认为比较好的Log库是NLog. 在我个人的asp.net web api 2 基础框架(Github地址)里, ...
- 跟厂长学PHP7内核(七):常见变量类型的基本结构
上篇文章讲述了变量的存储结构zval,今天我们就来学习一下几个常见变量类型的基本结构. 一.类型一览 zval中的u1.v.type用来存储变量的类型,而zval.value存储的是不同类型对应的值, ...
- AngularJs指令配置参数scope详解
AngularJs最重要也是最难理解的模块之一就是它的指令(directive)了,自定义指令配置有很多个参数,下面我只说说其中scope的配置极其含义. scope表示指令的作用域,它有三个可选值: ...
- python 修改文件中的内容
在python的文件操作中,是没有办法对文件中具体某行或者某个位置的内容进行局部的修改的,如果需要对文件的某一行内容进行修改,可以先将文件中的所有的内容全部读取出来,再进行内容判断,是否是需要修改的内 ...
- 【BZOJ 4818】 4818: [Sdoi2017]序列计数 (矩阵乘法、容斥计数)
4818: [Sdoi2017]序列计数 Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 560 Solved: 359 Description Al ...
- POJ.2774.Long Long Message/SPOJ.1811.LCS(后缀自动机)
题目链接 POJ2774 SPOJ1811 LCS - Longest Common Substring 确实比后缀数组快多了(废话→_→). \(Description\) 求两个字符串最长公共子串 ...
- beta6
吴晓晖(组长) 过去两天完成了哪些任务 对手写输入进行了重构,然后重新捋了一下bayes的思路 展示GitHub当日代码/文档签入记录 接下来的计划 推荐算法 还剩下哪些任务 过去两天完成了哪些任务: ...
- jquery开发表格插件项目之知识点累积 二
$.addClass() 增加样式 $.removeClass() 去除样式 $.toggleClass() 单击增加样式,再单击取消样式 $.hasClass() 判断是否存在样式,存在返回true ...
- Boost StateChart实现状态机----秒表例程
Boost 提供了状态机的实现接口,采用了CRTP技术实现,下面以秒表为例子实现一个状态机,这是一个官方的例子,也可以参考资料:Boost Statechart 庫,状态机的状态转换图如下所示: 实现 ...