这段时间在思考技术的价值,可能自己水平太菜吧!没有得出任何结论。
好了废话不说了今天来学习一个开源库ImageLoader异步加载图片
水平有限不敢说深谈,写这篇文章一是分享一下自己的理解,二是巩固知识,三希望更上一层楼
一 简介:
ImageLoader是比较早的异步开源框架了,国内使用的人蛮多的,网上教程很丰富。
ImageLoader的全称是Android-Universal-Image-Loader,在GetHub上可以下载该框架https://github.com/nostra13/Android-Universal-Image-Loader
下面我们来看看ImageLoader的特点:
1.多线程下载图片,图片可以来源于网络,文件系统,项目文件夹assets中以及drawable中等
2.支持随意的配置ImageLoader,例如线程池,图片下载器,内存缓存池,硬盘缓存策略等
3.支持图片的内存缓存,文件系统缓存或者SD卡
4.支持图片下载过程的监听
5.根据控件(ImageView)的大小对Bitmap进行裁剪,减小Bitmap占用过多的内存
6.较好的控制图片的加载过程,例如暂停图片加载,重新开始加载图片,一般使用ListView、GridView中,滑动过程中暂停加载图片,停止滑动的时候去加载图片
7.提供在较慢的网络下对图片进行加载
上面说的还是太抽象了,接下来我们来看一下官方的Demo吧,从官方的Demo入手或许会有惊喜吧
8.android 1.5以上支持
二 ImageLoader 配置
我们来看看官方Demo吧,我觉得看大神Demo是很有益的。
1.ImageLoader Application配置
/******************************************************************************* * Copyright 2011-2013 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample; import android.annotation.TargetApi; import android.app.Application; import android.content.Context; import android.os.Build; import android.os.StrictMode; 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; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ public class UILApplication extends Application { /** * TargetApi:使得高版本的Api在底版中不会报错 * * Build.VERSION_CODES.GINGERBREAD:系统的版本号9 */ @TargetApi(Build.VERSION_CODES.GINGERBREAD) @SuppressWarnings("unused") @Override public void onCreate() { /** * 当版本号大于9时用严苛模式 * * 因为严苛模式只有版本号大于9是才支持 */ if (Constants.Config.DEVELOPER_MODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyDialog().build()); StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyDeath().build()); } super.onCreate(); /** * ImageLoader的配置参数 */ initImageLoader(getApplicationContext()); } /** * ImageLoader的配置参数 */ public static void initImageLoader(Context context) { // This configuration tuning is custom. You can tune every option, you may tune some of them, // or you can create default configuration by // ImageLoaderConfiguration.createDefault(this); // method. ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context); config.threadPriority(Thread.NORM_PRIORITY - 2); config.denyCacheImageMultipleSizesInMemory(); config.diskCacheFileNameGenerator(new Md5FileNameGenerator()); config.diskCacheSize(50 * 1024 * 1024); // 50 MiB config.tasksProcessingOrder(QueueProcessingType.LIFO); config.writeDebugLogs(); // Remove for release app // Initialize ImageLoader with configuration. ImageLoader.getInstance().init(config.build()); } }
initImageLoader中是配置参数,在实际开发中根据项目情况可以增加也可以减少
下面是我修改后的代码
/*******************************************************************************
* Copyright 2011-2013 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.sample;
import android.annotation.TargetApi;
import android.app.Application;
import android.content.Context;
import android.os.Build;
import android.os.StrictMode;
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache;
import com.nostra13.universalimageloader.cache.disc.naming.HashCodeFileNameGenerator;
import com.nostra13.universalimageloader.cache.disc.naming.Md5FileNameGenerator;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.QueueProcessingType;
import com.nostra13.universalimageloader.core.decode.BaseImageDecoder;
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
import com.nostra13.universalimageloader.utils.StorageUtils;
import java.io.File;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class UILApplication extends Application {
/**
* TargetApi:使得高版本的Api在底版中不会报错
* <p>
* Build.VERSION_CODES.GINGERBREAD:系统的版本号9
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
@SuppressWarnings("unused")
@Override
public void onCreate() {
/**
* 当版本号大于9时用严苛模
*/
if (Constants.Config.DEVELOPER_MODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyDialog().build());
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyDeath().build());
}
super.onCreate();
/**
* ImageLoader的配置参数
*/
initImageLoader(getApplicationContext());
}
/**
* ImageLoader的配置参数
*/
public static void initImageLoader(Context context) {
// This configuration tuning is custom. You can tune every option, you may tune some of them,
// or you can create default configuration by
// ImageLoaderConfiguration.createDefault(this);
// method.
File cacheDir = StorageUtils.getCacheDirectory(context);//返回应用程序缓存目录。缓存目录将在SD卡上创建
ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);//图片加载器ImageLoader的配置差数
config.threadPriority(Thread.NORM_PRIORITY - 2);//设置单前线程的优先级
config.denyCacheImageMultipleSizesInMemory();//缓存显示不同大小的一张图
config.diskCacheFileNameGenerator(new Md5FileNameGenerator());//将保存的时候的URL名称用MD5加密
config.diskCacheSize(50 * 1024 * 1024); // // 50 Mb sd卡(本地)缓存的最大值
config.tasksProcessingOrder(QueueProcessingType.LIFO);//先进先出
config.writeDebugLogs(); // Remove for release app 打印debug log
/**
* 新增的
*/
config.threadPoolSize(3); //线程池内加载的数量
config.memoryCacheExtraOptions(480, 800); // max width, max height,即保存的每个缓存文件的最大长宽
config.diskCacheExtraOptions(480, 800, null); // 本地缓存的详细信息(缓存的最大长宽),最好不要设置这个
config.memoryCacheSize(2 * 1024 * 1024); // 内存缓存的最大值
config.memoryCacheSizePercentage(13); // 设置最大的缓存大小
config.diskCache(new UnlimitedDiskCache(cacheDir)); // default 为图像设置磁盘缓存
config.diskCacheSize(50 * 1024 * 1024);//为图像设置最大的磁盘缓存大小(以字节为单位)。
config.diskCacheFileCount(100);// 可以缓存的文件数量
config.diskCacheFileNameGenerator(new HashCodeFileNameGenerator());// 为在磁盘缓存中缓存的文件设置名称生成器
config.imageDownloader(new BaseImageDownloader(context)); // default 下载图片
config.defaultDisplayImageOptions(DisplayImageOptions.createSimple());// default图像选项
config.imageDownloader(new BaseImageDownloader(context,5 * 1000, 30 * 1000)); // connectTimeout (5 s), readTimeout (30 s)超时时间
// Initialize ImageLoader with configuration.
ImageLoader.getInstance().init(config.build());//全局初始化此配置
}
}
2.主页(进入的第一个页面HomeActivity.class)
接下来我们看看主页,我已经做了注解
/*******************************************************************************
* Copyright 2011-2013 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.sample.activity;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
import com.nostra13.universalimageloader.sample.fragment.ImageGalleryFragment;
import com.nostra13.universalimageloader.sample.fragment.ImageGridFragment;
import com.nostra13.universalimageloader.sample.fragment.ImageListFragment;
import com.nostra13.universalimageloader.sample.fragment.ImagePagerFragment;
import com.nostra13.universalimageloader.utils.L;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class HomeActivity extends Activity {
private static final String TEST_FILE_NAME = "Universal Image Loader @#&=+-_.,!()~'%20.png";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ac_home);
File testImageOnSdCard = new File("/mnt/sdcard", TEST_FILE_NAME);
/**
* 判断路径是否存在
*/
if (!testImageOnSdCard.exists()) {
copyTestImageToSdCard(testImageOnSdCard);
}
}
/**
* ListView
* @param view
*/
public void onImageListClick(View view) {
Intent intent = new Intent(this, SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImageListFragment.INDEX);
startActivity(intent);
}
/**
* GridView
* @param view
*/
public void onImageGridClick(View view) {
Intent intent = new Intent(this, SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImageGridFragment.INDEX);
startActivity(intent);
}
/**
* ViewPager
* @param view
*/
public void onImagePagerClick(View view) {
Intent intent = new Intent(this, SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImagePagerFragment.INDEX);
startActivity(intent);
}
/**
* gallery 画廊
* @param view
*/
public void onImageGalleryClick(View view) {
Intent intent = new Intent(this, SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImageGalleryFragment.INDEX);
startActivity(intent);
}
/**
* ViewPager (ListView + GridView)
* @param view
*/
public void onFragmentsClick(View view) {
Intent intent = new Intent(this, ComplexImageActivity.class);
startActivity(intent);
}
/**
* 按后退建是停止加载
*/
@Override
public void onBackPressed() {
ImageLoader.getInstance().stop();
super.onBackPressed();
}
/**
* 显示菜单
* @param menu
* @return
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_clear_memory_cache:
//清除内存缓存
ImageLoader.getInstance().clearMemoryCache();
return true;
case R.id.item_clear_disc_cache:
/**
* 清除磁盘缓存
*/
ImageLoader.getInstance().clearDiskCache();
return true;
default:
return false;
}
}
/**
* 把文件拷贝到SD卡
* @param testImageOnSdCard
*/
private void copyTestImageToSdCard(final File testImageOnSdCard) {
new Thread(new Runnable() {
@Override
public void run() {
try {
/**
* assets文件夹里面的文件都是保持原始的文件格式,需要用AssetManager以字节流的形式读取文件。
先在Activity里面调用getAssets() 来获取AssetManager引用。
再用AssetManager的open(String fileName, int accessMode) 方法则指定读取的文件以及访问模式就能得到输入流InputStream。
*/
InputStream is = getAssets().open(TEST_FILE_NAME);
//FileOutputStream:创建一个向指定File对象表示的文件中写入数据的文件输出流
FileOutputStream fos = new FileOutputStream(testImageOnSdCard);
byte[] buffer = new byte[8192];
int read;
try {
while ((read = is.read(buffer)) != -1) {
/**
* 写入文件
*/
fos.write(buffer, 0, read);
}
} finally {
/**
* 主要用在IO中,即清空缓冲区数据,一般在读写流(stream)的时候,数据是先被读到了内存中,再把数据写到文件中,当你数据读完的时候不代表你的数据已经写完了,
* 因为还有一部分有可能会留在内存这个缓冲区中。这时候如果你调用了close()方法关闭了读写流,那么这部分数据就会丢失,所以应该在关闭读写流之前先flush()。
*/
fos.flush();
fos.close();
is.close();
}
} catch (IOException e) {
L.w("Can't copy test image onto SD card");
}
}
}).start();
}
}
来张主页截图
3.来看看SimpleImageActivity.class
HomeActivity会传过来一个值,根据这个值判断显示哪个Fragment
/*******************************************************************************
* Copyright 2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.sample.activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
import com.nostra13.universalimageloader.sample.fragment.ImageGalleryFragment;
import com.nostra13.universalimageloader.sample.fragment.ImageGridFragment;
import com.nostra13.universalimageloader.sample.fragment.ImageListFragment;
import com.nostra13.universalimageloader.sample.fragment.ImagePagerFragment;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class SimpleImageActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* 获取传过来的值
*
*/
int frIndex = getIntent().getIntExtra(Constants.Extra.FRAGMENT_INDEX, 0);
Fragment fr;
String tag;
int titleRes;
switch (frIndex) {
default:
/**
* ListView
*/
case ImageListFragment.INDEX:
/**
* Class.getSimpleName()方法。是获取源代码中给出的‘底层类’简称
*
*这里把Fragment标记设为了‘底层类的’简称
*/
tag = ImageListFragment.class.getSimpleName();
/**
* getSupportFragmentManager()获取FragmentManager()
*
*findFragmentByTag://根据TAG找到对应的Fragment实例,主要用于在动态添加的fragment中,根据TAG来找到fragment实例
*/
fr = getSupportFragmentManager().findFragmentByTag(tag);
if (fr == null) {
fr = new ImageListFragment();
}
titleRes = R.string.ac_name_image_list;
break;
/**
* GridView
*/
case ImageGridFragment.INDEX:
tag = ImageGridFragment.class.getSimpleName();
fr = getSupportFragmentManager().findFragmentByTag(tag);
if (fr == null) {
fr = new ImageGridFragment();
}
titleRes = R.string.ac_name_image_grid;
break;
/**
* ViewPager
*/
case ImagePagerFragment.INDEX:
tag = ImagePagerFragment.class.getSimpleName();
/**
* getSupportFragmentManager:
*
*/
fr = getSupportFragmentManager().findFragmentByTag(tag);
if (fr == null) {
fr = new ImagePagerFragment();
fr.setArguments(getIntent().getExtras());
}
titleRes = R.string.ac_name_image_pager;
break;
/**
* gallery 画廊
*/
case ImageGalleryFragment.INDEX:
tag = ImageGalleryFragment.class.getSimpleName();
fr = getSupportFragmentManager().findFragmentByTag(tag);
if (fr == null) {
fr = new ImageGalleryFragment();
}
titleRes = R.string.ac_name_image_gallery;
break;
}
/**
* 设置标题内容
*/
setTitle(titleRes);
/**
*使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体~
*/
getSupportFragmentManager().beginTransaction().replace(android.R.id.content, fr, tag).commit();
}
}
4.来看看Fragment的2个基类
进入SimpleImageActivity界面我们可以看到有4个Fragment界面
好了重点来了
我们这四个Fragment都继承了AbsListViewBaseFragment这个Fragment类,AbsListViewBaseFragment这个类继承自BaseFragment
先来看看BaseFragment吧,这个类非常简单来看看源码
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.sample.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.sample.R;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public abstract class BaseFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/**
* 通过onCreateOptionsMenu(),fragment可以为activity的Options Menu提供菜单项。为了确保这一方法成功实现回调。必须在onCreate()期间调用setHasOptionsMenu()告知Options Menu fragment要添加菜单项。
*/
setHasOptionsMenu(true);
}
/**
* 通过onCreateOptionsMenu(),fragment可以为activity的Options Menu提供菜单项。为了确保这一方法成功实现回调。必须在onCreate()期间调用setHasOptionsMenu()告知Options Menu fragment要添加菜单项。
*/
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.main_menu, menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
/**
* 清除内存缓存
*/
case R.id.item_clear_memory_cache:
ImageLoader.getInstance().clearMemoryCache();
return true;
/**
* 清除磁盘缓存
*/
case R.id.item_clear_disc_cache:
ImageLoader.getInstance().clearDiskCache();
return true;
default:
return false;
}
}
}
接下来是AbsListViewBaseFragment这个类代码多一点,来上代码
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.sample.fragment;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.AbsListView;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.listener.PauseOnScrollListener;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
import com.nostra13.universalimageloader.sample.activity.SimpleImageActivity;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public abstract class AbsListViewBaseFragment extends BaseFragment {
protected static final String STATE_PAUSE_ON_SCROLL = "STATE_PAUSE_ON_SCROLL";
protected static final String STATE_PAUSE_ON_FLING = "STATE_PAUSE_ON_FLING";
/**
* AbsListView是ListView的父类
*
*
*
*/
protected AbsListView listView;
protected boolean pauseOnScroll = false;
protected boolean pauseOnFling = true;
@Override
public void onResume() {
super.onResume();
applyScrollListener();
}
/**
* 创建菜单
* @param menu
*/
@Override
public void onPrepareOptionsMenu(Menu menu) {
/**
* 短暂滑动式否暂停
*/
MenuItem pauseOnScrollItem = menu.findItem(R.id.item_pause_on_scroll);
pauseOnScrollItem.setVisible(true);
pauseOnScrollItem.setChecked(pauseOnScroll);
/**
* 孟的滑动是否暂停
*/
MenuItem pauseOnFlingItem = menu.findItem(R.id.item_pause_on_fling);
pauseOnFlingItem.setVisible(true);
pauseOnFlingItem.setChecked(pauseOnFling);
}
/**
* 菜单点击事件
* @param item
* @return
*/
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.item_pause_on_scroll:
/**
* 短暂滑动式否暂停
*/
pauseOnScroll = !pauseOnScroll;
item.setChecked(pauseOnScroll);
applyScrollListener();
return true;
case R.id.item_pause_on_fling:
/**
* 孟的滑动是否暂停
*/
pauseOnFling = !pauseOnFling;
item.setChecked(pauseOnFling);
applyScrollListener();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
protected void startImagePagerActivity(int position) {
/**
* 跳转到单个图片的实例
*/
Intent intent = new Intent(getActivity(), SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImagePagerFragment.INDEX);
intent.putExtra(Constants.Extra.IMAGE_POSITION, position);
startActivity(intent);
}
private void applyScrollListener() {
/*这个方法是干嘛用呢,主要是我们在使用ListView,GridView去加载图片的时候,有时候为了滑动更加的流畅,我们会选择手指在滑动或者猛地一滑动的时候不去加载图片,
所以才提出了这么一个方法,那么要怎么用呢? 这里用到了PauseOnScrollListener这个类,使用很简单ListView.setOnScrollListener(new PauseOnScrollListener(pauseOnScroll
, pauseOnFling )), pauseOnScroll控制我们缓慢滑动ListView,GridView是否停止加载图片,pauseOnFling 控制猛的滑动ListView,GridView是否停止加载图片*/
listView.setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(), pauseOnScroll, pauseOnFling));
}
}
其实也并不难就讲了两点:
1.菜单里设置ListView缓慢滑动和猛的缓动是否加载图片
2.startImagePagerActivity 跳转到单个图片实例
5.看看ImageListFragment这个类吧(LISTVIEW)
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.sample.fragment;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
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.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.display.CircleBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class ImageListFragment extends AbsListViewBaseFragment {
/**
* 这个I常量不陌生吧
* HomeActivity.class这个类中已经接触过了
*public 不同包中可以访问
*static 全局可以访问
*常量不能改变
*/
public static final int INDEX = 0;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fr_image_list, container, false);
listView = (ListView) rootView.findViewById(android.R.id.list);
((ListView) listView).setAdapter(new ImageAdapter(getActivity()));
/**
* listView点击事件
*/
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startImagePagerActivity(position);
}
});
return rootView;
}
@Override
public void onDestroy() {
super.onDestroy();
/**
* 销毁的时候清除数据
*/
AnimateFirstDisplayListener.displayedImages.clear();
}
/**
* 这是一个BaseAdapter
*/
private static class ImageAdapter extends BaseAdapter {
private static final String[] IMAGE_URLS = Constants.IMAGES;
private LayoutInflater inflater;
private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();
private DisplayImageOptions options;
/**
* ImageLoader图片的显示选项
*
* 如有需要我们可以自己添加更多配置
*/
ImageAdapter(Context context) {
inflater = LayoutInflater.from(context);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)//默认图片
.showImageForEmptyUri(R.drawable.ic_empty)//url为空时显示的图片
.showImageOnFail(R.drawable.ic_error)//加载失败时显示的图片
.cacheInMemory(true)//缓存到内存中
.cacheOnDisk(true)//缓存到磁盘中
.considerExifParams(true)
.displayer(new CircleBitmapDisplayer(Color.WHITE, 5))
.build();
}
@Override
public int getCount() {
return IMAGE_URLS.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 = inflater.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);
} else {
holder = (ViewHolder) view.getTag();
}
holder.text.setText("Item " + (position + 1));
/**
* 第一个参数:图片连接地址
*
* 第二个参数imageView控件
*
* 第三个参数 ImageLoader图片的显示选项
*
* animateFirstListener:ImageLoader监听
*/
ImageLoader.getInstance().displayImage(IMAGE_URLS[position], holder.image, options, animateFirstListener);
return view;
}
}
static class ViewHolder {
TextView text;
ImageView image;
}
/**
* 这是一个ImageLoader监听事件
*/
private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {
/**
* LinkedList是双向列表
*
* 多个线程同时访问一个LinkedList实例,而其中至少一个线程从结构上修改了列表,那么它就必须保持外部同步。
* (结构上的修改是指任何添加或删除一个或多个元素的操作,或者显式调整底层数组的大小;仅仅设置元素的值不是结构上的修改。)
* 这一般通过对自然封装该列表的对象进行同步操作来完成。如果不存在这样的对象,则应该使用Collections.synchronizedList方法将
* 该列表“包装”起来。这最好在创建时完成,以防止意外对列表进行不同步的访问
*
*/
static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());
/**
* loadComplete是图片加载完成之后的操作
* @param imageUri
* @param view
* @param loadedImage
*/
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
if (loadedImage != null) {
ImageView imageView = (ImageView) view;
boolean firstDisplay = !displayedImages.contains(imageUri);//是否包含地址
/**
* 没有加载购动画
*/
if (firstDisplay) {
/**
* 显示图像淡入动画
*
* 第一个参数:图片
*
* 第2个参数:持续时间
*/
FadeInBitmapDisplayer.animate(imageView, 500);
/**
* 地址添加进listView中
*/
displayedImages.add(imageUri);
}
}
}
}
}
这个类有四点内容:
配置图片的显示选项
加载图片
ImageLoaderr监听
加载图片动画以及判断
6 GridView加载图片(GRIDVIEW)
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.sample.fragment;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
import com.nostra13.universalimageloader.core.listener.ImageLoadingProgressListener;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class ImageGridFragment extends AbsListViewBaseFragment {
public static final int INDEX = 1;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fr_image_grid, container, false);
listView = (GridView) rootView.findViewById(R.id.grid);
((GridView) listView).setAdapter(new ImageAdapter(getActivity()));
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
/**
* 跳转到单个图片的实例
*/
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startImagePagerActivity(position);
}
});
return rootView;
}
private static class ImageAdapter extends BaseAdapter {
/**
* 图片地链接地址
*/
private static final String[] IMAGE_URLS = Constants.IMAGES;
private LayoutInflater inflater;
private DisplayImageOptions options;
ImageAdapter(Context context) {
inflater = LayoutInflater.from(context);
/**
* ImageLoader图片的显示选项
*
* 如有需要我们可以自己添加更多配置
*/
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)//默认图片
.showImageForEmptyUri(R.drawable.ic_empty)//url为空时显示的图片
.showImageOnFail(R.drawable.ic_error)//加载失败时显示的图片
.cacheInMemory(true)//开启缓存
.cacheOnDisk(true)//设置下载的图片是否缓存在SD卡中
.considerExifParams(true)是否考虑JPEG图像EXIF参数(旋转,翻转)
.bitmapConfig(Bitmap.Config.RGB_565)// default 设置图片的解码类型
.build();//创建
}
@Override
public int getCount() {
return IMAGE_URLS.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
View view = convertView;
if (view == null) {
view = inflater.inflate(R.layout.item_grid_image, parent, false);
holder = new ViewHolder();
assert view != null;
holder.imageView = (ImageView) view.findViewById(R.id.image);
holder.progressBar = (ProgressBar) view.findViewById(R.id.progress);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
ImageLoader.getInstance()
.displayImage(IMAGE_URLS[position], holder.imageView, options, new SimpleImageLoadingListener() {
/**
* 参数1:加载的图片
* 参数2:控件
* 参数3:图片的显示选项
* SimpleImageLoadingListener:图片的监听事件
*
* @param imageUri
* @param view
*/
@Override
public void onLoadingStarted(String imageUri, View view) {
/**
* 图片加载中
*/
holder.progressBar.setProgress(0);
holder.progressBar.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
/**
* 图片加载失败
*/
holder.progressBar.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
/**
* 图片加载完的
*/
holder.progressBar.setVisibility(View.GONE);
}
}, new ImageLoadingProgressListener() {
/**
* 显示图片的加载进度
* @param imageUri Image URI
* @param view View for image. Can be <b>null</b>.
* @param current Downloaded size in bytes
* @param total Total size in bytes
*/
@Override
public void onProgressUpdate(String imageUri, View view, int current, int total) {
holder.progressBar.setProgress(Math.round(100.0f * current / total));
}
});
return view;
}
}
static class ViewHolder {
ImageView imageView;
ProgressBar progressBar;
}
}
这里跟ListView加载图片不同的是;
1:没有加载动画
2.加载的方式不一样,采用以下方式加载图片
ImageLoader.getInstance()
.displayImage(IMAGE_URLS[position], holder.imageView, options, new SimpleImageLoadingListener() {
/**
* 参数1:加载的图片
* 参数2:控件
* 参数3:图片的显示选项
* SimpleImageLoadingListener:图片的监听事件
*
* @param imageUri
* @param view
*/
@Override
public void onLoadingStarted(String imageUri, View view) {
/**
* 图片加载中
*/
holder.progressBar.setProgress(0);
holder.progressBar.setVisibility(View.VISIBLE);
}
@Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
/**
* 图片加载失败
*/
holder.progressBar.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
/**
* 图片加载完的
*/
holder.progressBar.setVisibility(View.GONE);
}
}, new ImageLoadingProgressListener() {
/**
* 显示图片的加载进度
* @param imageUri Image URI
* @param view View for image. Can be <b>null</b>.
* @param current Downloaded size in bytes
* @param total Total size in bytes
*/
@Override
public void onProgressUpdate(String imageUri, View view, int current, int total) {
holder.progressBar.setProgress(Math.round(100.0f * current / total));
}
});
7 ImagePager加载图片(VIEWPAGER)
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.sample.fragment;
import android.content.Context;
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.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.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
/**
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class ImagePagerFragment extends BaseFragment {
public static final int INDEX = 2;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fr_image_pager, container, false);
ViewPager pager = (ViewPager) rootView.findViewById(R.id.pager);
/**
* 通过setAdapter绑定ImageAdapter
*/
pager.setAdapter(new ImageAdapter(getActivity()));
/**
*setCurrentItem:ViewPager 跳转到某个页面
*/
pager.setCurrentItem(getArguments().getInt(Constants.Extra.IMAGE_POSITION, 0));
return rootView;
}
private static class ImageAdapter extends PagerAdapter {
/**
*保存下载链接
*/
private static final String[] IMAGE_URLS = Constants.IMAGES;
private LayoutInflater inflater;
private DisplayImageOptions options;
ImageAdapter(Context context) {
inflater = LayoutInflater.from(context);
/**
* ImageLoader的显示选项
*/
options = new DisplayImageOptions.Builder()
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.resetViewBeforeLoading(true)
.cacheOnDisk(true)
.imageScaleType(ImageScaleType.EXACTLY)
.bitmapConfig(Bitmap.Config.RGB_565)
.considerExifParams(true)
.displayer(new FadeInBitmapDisplayer(300))
.build();
}
/**
* 移除页面
* @param container
* @param position
* @param object
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
/**
* 页面数量
* @return
*/
@Override
public int getCount() {
return IMAGE_URLS.length;
}
/**
* 这个方法用来实例化页面
* @param view
* @param position
* @return
*/
@Override
public Object instantiateItem(ViewGroup view, int position) {
View imageLayout = inflater.inflate(R.layout.item_pager_image, view, false);
assert imageLayout != null;
ImageView imageView = (ImageView) imageLayout.findViewById(R.id.image);
final ProgressBar spinner = (ProgressBar) imageLayout.findViewById(R.id.loading);
/**
* 加载图片
*/
ImageLoader.getInstance().displayImage(IMAGE_URLS[position], imageView, options, new SimpleImageLoadingListener() {
@Override
public void onLoadingStarted(String imageUri, View view) {
spinner.setVisibility(View.VISIBLE);
}
/**
* 获取异常信息
* @param imageUri
* @param view
* @param failReason
*/
@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 = "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(view.getContext(), message, Toast.LENGTH_SHORT).show();
spinner.setVisibility(View.GONE);
}
@Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
spinner.setVisibility(View.GONE);
}
});
view.addView(imageLayout, 0);
return imageLayout;
}
/**
* isViewFromObject方法是用来判断pager的一个view是否和instantiateItem方法返回的object有关联
* @param view
* @param object
* @return
*/
@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;
}
}
}
这里用到了ViewPager
有一点要注意
这里输出异常信息并用Toast提示
/**
* 获取异常信息
* @param imageUri
* @param view
* @param failReason
*/
@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 = "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(view.getContext(), message, Toast.LENGTH_SHORT).show();
8 ImageGalleryFragment.class(画廊视图GALLERY)
/*******************************************************************************
* Copyright 2011-2014 Sergey Tarasevich
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package com.nostra13.universalimageloader.sample.fragment;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import com.nostra13.universalimageloader.sample.Constants;
import com.nostra13.universalimageloader.sample.R;
import com.nostra13.universalimageloader.sample.activity.SimpleImageActivity;
/**
* 画廊界面
* @author Sergey Tarasevich (nostra13[at]gmail[dot]com)
*/
public class ImageGalleryFragment extends BaseFragment {
public static final int INDEX = 3;
@SuppressWarnings("deprecation")
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fr_image_gallery, container, false);
Gallery gallery = (Gallery) rootView.findViewById(R.id.gallery);
gallery.setAdapter(new ImageAdapter(getActivity()));
gallery.setOnItemClickListener(new OnItemClickListener() {
/**
* 跳转到单个图片的实例
* @param parent
* @param view
* @param position
* @param id
*/
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startImagePagerActivity(position);
}
});
return rootView;
}
private void startImagePagerActivity(int position) {
Intent intent = new Intent(getActivity(), SimpleImageActivity.class);
intent.putExtra(Constants.Extra.FRAGMENT_INDEX, ImagePagerFragment.INDEX);
intent.putExtra(Constants.Extra.IMAGE_POSITION, position);
startActivity(intent);
}
private static class ImageAdapter extends BaseAdapter {
private static final String[] IMAGE_URLS = Constants.IMAGES;
private LayoutInflater inflater;
private DisplayImageOptions options;
ImageAdapter(Context context) {
inflater = LayoutInflater.from(context);
/**
* ImageLoader的图片显示选项
*/
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub)
.showImageForEmptyUri(R.drawable.ic_empty)
.showImageOnFail(R.drawable.ic_error)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.displayer(new RoundedBitmapDisplayer(20))
.build();
}
@Override
public int getCount() {
return IMAGE_URLS.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = (ImageView) convertView;
if (imageView == null) {
imageView = (ImageView) inflater.inflate(R.layout.item_gallery_image, parent, false);
}
/**
* 加载图片
*/
ImageLoader.getInstance().displayImage(IMAGE_URLS[position], imageView, options);
return imageView;
}
}
}
画廊视图没什么好说的
9.ComplexImageActivity.class(VIEWPAGER)
/******************************************************************************* * Copyright 2014 Sergey Tarasevich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package com.nostra13.universalimageloader.sample.activity; import android.annotation.TargetApi; import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; import com.nostra13.universalimageloader.sample.R; import com.nostra13.universalimageloader.sample.fragment.ImageGridFragment; import com.nostra13.universalimageloader.sample.fragment.ImageListFragment; /** * @author Sergey Tarasevich (nostra13[at]gmail[dot]com) */ public class ComplexImageActivity extends FragmentActivity { private static final String STATE_POSITION = "STATE_POSITION"; private ViewPager pager; @TargetApi(Build.VERSION_CODES.GINGERBREAD) @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.ac_complex); /** * FragmentActivity的状态信息 * *savedInstanceState.getInt:返回与给定键关联的值,或0 if对于给定的键,不存在所需类型的映射。 * */ int pagerPosition = savedInstanceState == null ? 0 : savedInstanceState.getInt(STATE_POSITION); /** * 标题栏 */ pager = (ViewPager) findViewById(R.id.pager); /** * 通过setAdapter绑定ImageAdapter */ pager.setAdapter(new ImagePagerAdapter(getSupportFragmentManager())); /** * 跳转到指定的页面 */ pager.setCurrentItem(pagerPosition); } @TargetApi(Build.VERSION_CODES.GINGERBREAD) /** * 保存Activity状态信息 * * 这里保存当前页面 */ @Override public void onSaveInstanceState(Bundle outState) { outState.putInt(STATE_POSITION, pager.getCurrentItem()); } /** * FragmentPagerAdapter适配器 */ private class ImagePagerAdapter extends FragmentPagerAdapter { Fragment listFragment; Fragment gridFragment; ImagePagerAdapter(FragmentManager fm) { super(fm); listFragment = new ImageListFragment(); gridFragment = new ImageGridFragment(); } @Override public int getCount() { return 2; } /** * 页面数量 * @param position * @return */ @Override public Fragment getItem(int position) { switch (position) { case 0: return listFragment; case 1: return gridFragment; default: return null; } } /** * 设置页面标题 * @param position * @return */ @Override public CharSequence getPageTitle(int position) { switch (position) { case 0: return getString(R.string.title_list); case 1: return getString(R.string.title_grid); default: return null; } } } }
这里有两个页面
ListView+GridView
ViewPager实现切换,PagerTitleStrip实现标题栏
10 再来说一下ImagePagerFragment.class类
我们可以看到LISTVIEW,GRIDVIEW,GALLERY,VIEWPAGERZ这几个界面setOnItemClickListener时都会进入一个新的界面,这个界面用到了ViewPager,那么这个界面用到了哪个类呢。从代码中我们可找到它用到了这个类setOnItemClickListener.class ,ImageLoader作者写的Demo是不是很棒。