Android:ViewPager详解(异步网络加载图片,带图片缓存,并带导航小圆点)

时间:2022-01-19 20:43:18

android 应用中,如欢迎指引页面, 和图片轮播功能, 或者更多的内容在一页显示不了,要分成多个页面,这时候viewpager是很好用的。


首先看下效果:

Android:ViewPager详解(异步网络加载图片,带图片缓存,并带导航小圆点)


下面是一个例子,带异步网络加载图片,并带导航小圆点


packagecom.example.viewpagertest;

importjava.io.IOException;
importjava.lang.ref.SoftReference;
importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.List;

importorg.apache.http.HttpEntity;
importorg.apache.http.HttpResponse;
importorg.apache.http.HttpStatus;
importorg.apache.http.client.ClientProtocolException;
importorg.apache.http.client.HttpClient;
importorg.apache.http.client.methods.HttpGet;
importorg.apache.http.impl.client.DefaultHttpClient;
importorg.apache.http.params.CoreConnectionPNames;

importandroid.annotation.SuppressLint;
importandroid.app.Activity;
importandroid.graphics.drawable.Drawable;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.os.Message;
importandroid.support.v4.view.PagerAdapter;
importandroid.support.v4.view.ViewPager;
importandroid.support.v4.view.ViewPager.OnPageChangeListener;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.ImageView;
importandroid.widget.LinearLayout;
importandroid.widget.TextView;

importcom.example.viewpagertest.MainActivity.AsyncImageLoader.ImageCallback;



/***
*
* 说明:ViewPager ,带小圆点导航,适配器采用PagerAdapter,基本可以满足需求
* 也可以采用FragmentPagerAdapter,有人说,Fragment可以更好的适应平板和手机,
* 并且可以更好的代码重用,具体这些好处大家试一下就知道了。
*
* @author andylaw
*
* 更多内容请查看博客:http://blog.csdn.net/lyc66666666666
*
*/

@SuppressLint("NewApi")
publicclass MainActivity extendsActivity {

privateViewPager view_pager;

privateLayoutInflater inflater;

// 图片的地址,这里可以从服务器获取
String[] urls = newString[]{

"http://a.hiphotos.baidu.com/image/pic/item/3bf33a87e950352ad6465dad5143fbf2b2118b6b.jpg",
"http://a.hiphotos.baidu.com/image/pic/item/c8177f3e6709c93d002077529d3df8dcd0005440.jpg",
"http://f.hiphotos.baidu.com/image/pic/item/7aec54e736d12f2ecc3d90f84dc2d56285356869.jpg",
"http://e.hiphotos.baidu.com/image/pic/item/9c16fdfaaf51f3de308a87fc96eef01f3a297969.jpg",
"http://d.hiphotos.baidu.com/image/pic/item/f31fbe096b63f624b88f7e8e8544ebf81b4ca369.jpg",
"http://h.hiphotos.baidu.com/image/pic/item/11385343fbf2b2117c2dc3c3c88065380cd78e38.jpg",
"http://c.hiphotos.baidu.com/image/pic/item/3801213fb80e7bec5ed8456c2d2eb9389b506b38.jpg"

};

privateImageView image;
privateView item ;
privateMyAdapter adapter ;
privateImageView[] indicator_imgs = newImageView[7];//存放引到图片数组



@Override
protectedvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

view_pager = (ViewPager) findViewById(R.id.view_pager);
List<view> list = newArrayList<view>();
inflater = LayoutInflater.from(this);

/**
* 创建多个item (每一条viewPager都是一个item)
* 从服务器获取完数据(如文章标题、url地址) 后,再设置适配器
*/
for(inti = 0; i < 7; i++) {
item = inflater.inflate(R.layout.item, null);
((TextView) item.findViewById(R.id.text_view)).setText("第 " + i+ " 个 viewPager");
list.add(item);
}

//创建适配器, 把组装完的组件传递进去
adapter = newMyAdapter(list);
view_pager.setAdapter(adapter);

//绑定动作监听器:如翻页的动画
view_pager.setOnPageChangeListener(newMyListener());

initIndicator();
}



/**
* 初始化引导图标
* 动态创建多个小圆点,然后组装到线性布局里
*/
privatevoid initIndicator(){

ImageView imgView;
View v = findViewById(R.id.indicator);// 线性水平布局,负责动态调整导航图标

for(inti = 0; i < 7; i++) {
imgView = newImageView(this);
LinearLayout.LayoutParams params_linear = newLinearLayout.LayoutParams(10,10);
params_linear.setMargins(7,10,7,10);
imgView.setLayoutParams(params_linear);
indicator_imgs[i] = imgView;

if(i == 0) { // 初始化第一个为选中状态

indicator_imgs[i].setBackgroundResource(R.drawable.indicator_focused);
}else{
indicator_imgs[i].setBackgroundResource(R.drawable.indicator);
}
((ViewGroup)v).addView(indicator_imgs[i]);
}

}




/**
* 适配器,负责装配 、销毁 数据 和 组件 。
*/
privateclass MyAdapter extendsPagerAdapter {

privateList<view> mList;


privateAsyncImageLoader asyncImageLoader;

publicMyAdapter(List<view> list) {
mList = list;
asyncImageLoader = newAsyncImageLoader();
}



/**
* Return the number of views available.
*/
@Override
publicint getCount() {
// TODO Auto-generated method stub
returnmList.size();
}


/**
* Remove a page for the given position.
* 滑动过后就销毁 ,销毁当前页的前一个的前一个的页!
* instantiateItem(View container, int position)
* This method was deprecated in API level . Use instantiateItem(ViewGroup, int)
*/
@Override
publicvoid destroyItem(ViewGroup container, intposition, Object object) {
// TODO Auto-generated method stub
container.removeView(mList.get(position));

}

@Override
publicboolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
returnarg0==arg1;
}


/**
* Create the page for the given position.
*/
@Override
publicObject instantiateItem(finalViewGroup container, finalint position) {


Drawable cachedImage = asyncImageLoader.loadDrawable(
urls[position],newImageCallback() {

publicvoid imageLoaded(Drawable imageDrawable,
String imageUrl) {

View view = mList.get(position);
image = ((ImageView) view.findViewById(R.id.image));
image.setBackground(imageDrawable);
container.removeView(mList.get(position));
container.addView(mList.get(position));
// adapter.notifyDataSetChanged();

}
});

View view = mList.get(position);
image = ((ImageView) view.findViewById(R.id.image));
image.setBackground(cachedImage);

container.removeView(mList.get(position));
container.addView(mList.get(position));
// adapter.notifyDataSetChanged();


returnmList.get(position);

}


}


/**
* 动作监听器,可异步加载图片
*
*/
privateclass MyListener implementsOnPageChangeListener{

@Override
publicvoid onPageScrollStateChanged(intstate) {
// TODO Auto-generated method stub
if(state == 0) {
//new MyAdapter(null).notifyDataSetChanged();
}
}


@Override
publicvoid onPageScrolled(intarg0, floatarg1, intarg2) {
// TODO Auto-generated method stub

}

@Override
publicvoid onPageSelected(intposition) {

// 改变所有导航的背景图片为:未选中
for(inti = 0; i < indicator_imgs.length; i++) {

indicator_imgs[i].setBackgroundResource(R.drawable.indicator);

}

// 改变当前背景图片为:选中
indicator_imgs[position].setBackgroundResource(R.drawable.indicator_focused);
}


}



/**
* 异步加载图片
*/
staticclass AsyncImageLoader {

// 软引用,使用内存做临时缓存 (程序退出,或内存不够则清除软引用)
privateHashMap<string, softreference<drawable="">> imageCache;

publicAsyncImageLoader() {
imageCache = newHashMap<string, softreference<drawable="">>();
}

/**
* 定义回调接口
*/
publicinterface ImageCallback {
publicvoid imageLoaded(Drawable imageDrawable, String imageUrl);
}


/**
* 创建子线程加载图片
* 子线程加载完图片交给handler处理(子线程不能更新ui,而handler处在主线程,可以更新ui)
* handler又交给imageCallback,imageCallback须要自己来实现,在这里可以对回调参数进行处理
*
* @param imageUrl :须要加载的图片url
* @param imageCallback:
* @return
*/
publicDrawable loadDrawable(finalString imageUrl,
finalImageCallback imageCallback) {

//如果缓存中存在图片 ,则首先使用缓存
if(imageCache.containsKey(imageUrl)) {
SoftReference<drawable> softReference = imageCache.get(imageUrl);
Drawable drawable = softReference.get();
if(drawable != null) {
imageCallback.imageLoaded(drawable, imageUrl);//执行回调
returndrawable;
}
}

/**
* 在主线程里执行回调,更新视图
*/
finalHandler handler = newHandler() {
publicvoid handleMessage(Message message) {
imageCallback.imageLoaded((Drawable) message.obj, imageUrl);
}
};


/**
* 创建子线程访问网络并加载图片 ,把结果交给handler处理
*/
newThread() {
@Override
publicvoid run() {
Drawable drawable = loadImageFromUrl(imageUrl);
// 下载完的图片放到缓存里
imageCache.put(imageUrl,newSoftReference<drawable>(drawable));
Message message = handler.obtainMessage(0, drawable);
handler.sendMessage(message);
}
}.start();

returnnull;
}


/**
* 下载图片 (注意HttpClient 和httpUrlConnection的区别)
*/
publicDrawable loadImageFromUrl(String url) {

try{
HttpClient client = newDefaultHttpClient();
client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,1000*15);
HttpGet get = newHttpGet(url);
HttpResponse response;

response = client.execute(get);
if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();

Drawable d = Drawable.createFromStream(entity.getContent(),
"src");

returnd;
}else{
returnnull;
}
}catch(ClientProtocolException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}

returnnull;
}

//清除缓存
publicvoid clearCache() {

if(this.imageCache.size() > 0) {

this.imageCache.clear();
}

}

}






}


下面是layout主文件:

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
<span style="white-space:pre"></span>xmlns:tools="http://schemas.android.com/tools"
<span style="white-space:pre"></span>android:layout_width="match_parent"
<span style="white-space:pre"></span>android:layout_height="match_parent"
<span style="white-space:pre"></span>android:paddingbottom="@dimen/activity_vertical_margin"
<span style="white-space:pre"></span>android:paddingleft="@dimen/activity_horizontal_margin"
<span style="white-space:pre"></span>android:paddingright="@dimen/activity_horizontal_margin"
<span style="white-space:pre"></span>android:paddingtop="@dimen/activity_vertical_margin">         <relativelayout 
<span style="white-space:pre"></span>android:layout_width="fill_parent"
<span style="white-space:pre"></span>android:layout_height="fill_parent">                </android.support.v4.view.viewpager>        <linearlayout 
<span style="white-space:pre"></span>android:id="@+id/indicator"
<span style="white-space:pre"></span>android:layout_width="fill_parent"
<span style="white-space:pre"></span>android:layout_height="100px"
<span style="white-space:pre"></span>android:layout_margintop="500px"
<span style="white-space:pre"></span>android:gravity="center_horizontal"
<span style="white-space:pre"></span>android:orientation="horizontal">        </linearlayout>           </relativelayout></linearlayout>

下面是每一条item文件:

?
1234567 <span
style=
"font-size:14px;"><linearlayout 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"android:paddingbottom="@dimen/activity_vertical_margin"android:paddingleft="@dimen/activity_horizontal_margin"android:paddingright="@dimen/activity_horizontal_margin"android:paddingtop="@dimen/activity_vertical_margin"android:orientation="vertical">
    <textview android:id="@+id/text_view"android:layout_width="fill_parent"android:layout_height="wrap_content">       <imageview android:id="@+id/image"android:layout_width="fill_parent"android:layout_height="wrap_content"> </imageview></textview></linearlayout></span>