ViewPager是谷歌在jar包android-suppot-v4.jar内置的控件,主要是是view的左右滑动切换,有点类似于tabHost,不过tabHost是加载activity并且不能左右滑动。
谷歌的控件很多控件好像就是一个写的一样,用法几乎一模一样,只能说能在里面工作的人都太厉害了。
ViewPager用法和GridView,ListView差不多,就是设置适配器设置监听。
适配器:
package com.example.viewpagerimagetest;
import java.util.List;
import android.content.Context;
import android.support.v4.view.PagerAdapter;
import android.view.View;
import android.view.ViewGroup;
public class adapter extends PagerAdapter
{
List<View> views;//viewPager加载的View集合
//构造方法,上下文context不用,写适配器习惯了就加进来了
public adapter(Context context, List<View> views)
{
this.views = views;
}
//加载view 的回调方法
@Override
public Object instantiateItem(ViewGroup container, int position)
{
container.addView(views.get(position));
return views.get(position);
}
//加载view的个数
@Override
public int getCount()
{
return views.size();
}
/*好像要这样写,原因不知道。官方解释:Determines whether a page View is associated with a specific key object as returned by instantiateItem(ViewGroup, int)
. This method is required for a PagerAdapter to function properly.
true if view
is associated with the key object object
*/
@Override
public boolean isViewFromObject(View arg0, Object arg1)
{
return arg0 == arg1;
}
//删除页卡,刚才不小心没在里面写东西划多几下会报错,求解释
@Override
public void destroyItem(ViewGroup container, int position, Object object)
{
container.removeView(views.get(position));
}
}
布局:跟其他系统空间一模一样
<RelativeLayout 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"
tools:context=".MainActivity" >
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</RelativeLayout>
监听:
viewPager.setOnPageChangeListener(new OnPageChangeListener()
{
@Override
public void onPageSelected(final int arg0)
{
//页卡改变时回调
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
//滑动的时候回调,arg0改变之后的页数,arg1是滑动的距离占屏幕宽度的百分比,如果写跟随滑动的游标可以用到
}
@Override
public void onPageScrollStateChanged(int arg0)
{
//这个东东没搞明白,Log出来总是0,1,2没什么规律
}
}
}
今天同事在做用viewpager来做类似图片浏览器的东西,滑动的页数太多了加载的图片太多会报oom,今晚回来想了一下,用这种思路,有点木,原则是显示一张bitmap释放一张bitmap,永远保证整个程序没被释放的图片只有三张,就是当前显示的,和上一张和下一张,其他的释放,更改一次页码释放一张。代码写的有点凌乱,不要见笑。除了这样方法有没有更好的方法啊,我看系统的图片浏览器特别流畅而且永远不会OOM,不知道是怎么实现的。
代码:
package com.example.viewpagerimagetest;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.Menu;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends Activity
{
//viewpager适配器
adapter adapter;
//viewpager的布局View
List<View> views = new ArrayList<View>();
//保持的3个bitmap对象
Bitmap[] bitmaps = new Bitmap[3];
//显示图片的控件
ImageView id1;
//用于判断是向前滑还是向后滑
int arg;
// 图片资源
int[] ids = new int[] { R.drawable.xu, R.drawable.xu1, R.drawable.a,
R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e,
R.drawable.g, R.drawable.f, R.drawable.h, R.drawable.l,
R.drawable.k, R.drawable.m1, R.drawable.m2, R.drawable.m3,
R.drawable.m4, R.drawable.n1, R.drawable.n2, R.drawable.n3,
R.drawable.n4, R.drawable.n5, R.drawable.n6, R.drawable.n7,
R.drawable.n8, R.drawable.n9, R.drawable.n10, R.drawable.n11,
R.drawable.n12, R.drawable.n13, R.drawable.n14, R.drawable.n15,
R.drawable.n16, R.drawable.n17, R.drawable.n19, R.drawable.n20,
R.drawable.n22, R.drawable.n21, R.drawable.n24, R.drawable.n23,
R.drawable.n25 };
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
for (int i = 0; i < 36; i++)
{
views.add(getLayoutInflater().inflate(R.layout.cell, null));
if (i == 1 || i == 0)
{
id1 = (ImageView) views.get(i).findViewById(R.id.image);
Bitmap bitmap = BitmapFactory.decodeStream(getResources()
.openRawResource(ids[i]));
id1.setImageBitmap(bitmap);
if (i == 0)
{
bitmaps[1] = bitmap;
}
else
{
bitmaps[2] = bitmap;
}
}
}
adapter = new adapter(this, views);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
viewPager.setOnPageChangeListener(new OnPageChangeListener()
{
@Override
public void onPageSelected(final int arg0)
{
// 当页数改变时启动线程加载控件和图片bitmap
new AsyncTask<Integer, Void, Integer>()
{
@Override
protected Integer doInBackground(Integer... params)
{
int i = 0;
if (arg0 < views.size() - 1 && (arg0 > arg))
{
//向后滑,释放第一张bitmap
if (bitmaps[0] != null && !bitmaps[0].isRecycled())
{
bitmaps[0].recycle();
System.out.println("+ "
+ bitmaps[0].isRecycled());
}
//让之前的当前页b变成前一页
bitmaps[0] = bitmaps[1];
// 让之前的之后一页变成当前页
bitmaps[1] = bitmaps[2];
id1 = (ImageView) views.get(arg0 + 1).findViewById(
R.id.image);
Bitmap bitmap = BitmapFactory
.decodeStream(getResources()
.openRawResource(ids[arg0 + 1]));
bitmaps[2] = bitmap;
id1.setImageBitmap(bitmap);
i = 2;
}
if (arg0 > 0 && (arg0 < arg))
{
if (bitmaps[2] != null && !bitmaps[2].isRecycled())
{
bitmaps[2].recycle();
System.out.println("-");
}
bitmaps[2] = bitmaps[1];
bitmaps[1] = bitmaps[0];
id1 = (ImageView) views.get(arg0 - 1).findViewById(
R.id.image);
Bitmap bitmap = BitmapFactory
.decodeStream(getResources()
.openRawResource(ids[arg0 - 1]));
bitmaps[0] = bitmap;
i = 0;
}
arg = arg0;
return i;
}
@Override
protected void onPostExecute(Integer result)
{
id1.setImageBitmap(bitmaps[result]);
}
}.execute(1);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
}
@Override
public void onPageScrollStateChanged(int arg0)
{
}
});
viewPager.setAdapter(adapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
出现了一个问题,如果划得太快会导致doInBackGround的没执行完,然后就报错了。但是不加线程又会导致手指离开屏幕的一刹那UI卡一下。