Android之ViewPager学习笔记(MVP模式)
今天来分享分享我在android中学习的ViewPager控件,相信大家对这款控件非常熟悉也非常喜爱,在我们平时的微信中,滑动一个个的界面,就可以用我们的ViewPager来实现,由于内容不是很多,我今天就只用简单的MVP模式来写,不使用通用MVP模式了。
今天主要学习的内容有:
1. 如何实现简单的图片滑动
2. 如何实现手动无限轮播图片
3. 如何实现自动轮播图片
首先来看看简单的图片滑动:
具体结构如下:
view层:
MainActivity.java
public class MainActivity extends AppCompatActivity implements ViewInter<List<ImageView>>{
//图片数据源
private List<ImageView> mImages;
//ViewPager控件
private ViewPager mVPager;
//适配器
private MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mVPager = (ViewPager)findViewById(R.id.mVPager);
new Presenter(this).load();
}
/**
* 设置适配器数据
* @param mImages 数据源
*/
private void showAdapterData(List<ImageView> mImages){
if(adapter == null){
adapter = new MyAdapter(mImages);
mVPager.setAdapter(adapter);
}else{
this.mImages.addAll(mImages);
adapter.notifyDataSetChanged();
}
}
/**
* 获取Presenter层传回来的数据
* @param mImages
*/
@Override
public void getData(List<ImageView> mImages) {
this.mImages = mImages;
showAdapterData(this.mImages);
}
}
在MainActivity中,我们主要的任务就是通过请求presenter获取数据,然后presenter为我们回传我们需要的数据,然后拿到数据之后设置到自定的adapter中去,最后完成操作,数据就可以显示了
ViewInter.java
/**
* 将MainActivity中的所有功能都放入到这个接口中
*/
public interface ViewInter<T> {
void getData(T t);
}
model层:
ModelInter.java
public interface ModelInter {
/**
* 处理数据
* @param listener 回调接口
*/
void getData(OnLoadLocalPicListener listener);
interface OnLoadLocalPicListener{
/**
* 获取本地图片的方法
*/
void getLocalPic();
}
}
ModelImp.java
public class ModelImp implements ModelInter{
/**
* 负责处理数据,直接调用传过来的接口listener
* @param listener 回调接口
*/
@Override
public void getData(OnLoadLocalPicListener listener) {
listener.getLocalPic();
}
}
presenter层:
Presenter.java
public class Presenter {
ViewInter viewInter;
ModelInter modelInter;
public Presenter(ViewInter viewInter){
this.viewInter = viewInter;
modelInter = new ModelImp();
}
/**
* 为view层处理请求
*/
public void load(){
/**
* 请求调用model层的数据处理方法
*/
modelInter.getData(new OnLoadLocalPic<>(viewInter,((MainActivity)viewInter).getApplicationContext()));
}
}
callback包:
OnLoadLocalPic.java
public class OnLoadLocalPic<T extends ViewInter> implements ModelInter.OnLoadLocalPicListener {
//ViewInter的子类Activity
private T activity;
//上下文
private Context context;
public OnLoadLocalPic(T view, Context context){
this.activity = view;
this.context = context;
mImages = new ArrayList<>();
}
//获取图片数据集
private List<ImageView> mImages;
//本地的图片ID
private int[] ids = {R.mipmap.one,R.mipmap.two,R.mipmap.three};
@Override
public void getLocalPic() {
//设置数据
for(int i = 0; i < ids.length; i++){
//创建一个图片控件
ImageView imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageView.setImageResource(ids[i]);
mImages.add(imageView);
}
//回传给MainActivity
activity.getData(mImages);
}
}
上面的OnLoadLocalPic类,主要就是去实现ModelInter.OnLoadLocalPicListener接口中的getLocalPic方法,该方法主要的功能就是获取本地的图片,然后添加到集合中,回传给view层的MainActivity即可
下面看看简单的运行效果图:
上面的滑动效果没有录制好,所以将就一下吧。简单的来回滑动就实现了,很简单吧。
- 对于三张图片采取无限轮播的方式,这里我采用两种方式来实现无限轮播
实现前,先讲一个注意事项和PagerAdapter中的所有方法的运行过程,在我们用手指从右向左滑动屏幕时,首先执行移除当前不需要的图片(执行destroyItem方法,第一张和最后一张时,不需要执行该方法),再执行的是加载图片(执行instantiateItem方法)。默认来说,当前所加载的图片为当前显示页面的左右两张图片,除特殊情况下(第一张显示的,加载其右边的,最后一张,加载其左边的),而我们要了解的是,当我们用手指从左向右滑动时,首先执行的是先加载图片(先执行instantiateItem方法),然后再执行移除当前不需要的图片(执行destroyItem方法),在了解这个步奏后,下面开始实现代码:
方式1:将当前数据源修改一下,把List集合改成一个int[]类型,然后传过来当前本地的图片id,因为是无限滑动,所以我们要修改一下getCount方法的返回值。adapter中的instantiateItem方法代码如下
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = new ImageView(container.getContext());
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setImageResource(ids[position%ids.length]);
container.addView(imageView);
return imageView;
}
每次滑动,都加载一个新的ImageView即可实现无限滑动,但是这种方式比较好内存,不推荐使用
方式2:添加一个标记,判断当前滑动的方向,代码如下:
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView imageView = images.get(position % images.size());
if(imageView.getParent() == null){
Log.i("IT_Real", "instantiateItem: 加载");
container.addView(imageView);
}else{
isBack = true;
Log.i("IT_Real", "instantiateItem: 手动删除了");
((ViewGroup) imageView.getParent()).removeView(imageView);
Log.i("IT_Real", "instantiateItem: 加载了");
container.addView(imageView);
}
return imageView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if(!isBack){
Log.i("IT_Real", "destroyItem: 调用系统删除");
container.removeView((View) object);
}
isBack = false;
}
上的代码则可以节省内存的开销。
3. 最后就是实现自动无限轮播了
实现过程,只需要在主函数中添加一个handler消息机制即可,然后在设置完adapter之后,调用一次发送消息即可。代码如下:
在主函数中添加:
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 100:
mVPager.setCurrentItem(mVPager.getCurrentItem() + 1);//每发送一个消息过来,就向后移动一次
sendEmptyMessageDelayed(100,1000);//每隔一秒发送一次请求
break;
}
}
};
然后在onCreate中调用一次handler.sendEmptyMessageDelayed(100,1000);
即可,注意该语句的顺序,要放在加载完数据语句new Presenter(this).load();
之后