巧用ViewPager实现日历场景
在 android中用ViewPager实现循环滑动 一文的结尾我们曾留了个小问题:
提个小问题:如果换一个场景,比如在日历中,我们每滑一下就显示下一个月或上一个月的日历,一般做个日历的话都要可以查询上百年的日期吧,如果使用上述方法,难道我们要传N多个view到ViewPagerAdapter里面吗?显然这是不可能的。如果只用三个view呢,让它们循环使用,这也有个问题,你怎么知道它滑到哪年哪月了呢?难道要自己用个计数器把它记起来?会不会太麻烦?下一篇来讲讲如何解决这个问题。
那么今天就来看看怎么解决这个问题。显然传n个view的情况是不现实的,所以放弃。接下来看看第二种方案。
使用循环是值得考虑的,循环可以节省很多资源,也基本上能实现我们的需求。只是有个计数的问题我们需要再考虑一下,看有没有比使用计数器更简便的方法来实现。一般情况下,我们需要显示几个view就传几个view到viewPagerAdapter当中,如我们要显示100个月的日历,那么按一般情况下传100个view进去,每个view代表一个月的日历。这样viewPagerAdapter中的每个position所对应的view就是月份数,不需要计数。那么很自然我们就会想到在getCount()方法中返回我们要显示的月份的个数,然后只传一个view到adapter中,每个月的日历都复用这个view,然后动态加载数据,由于position跟月份是一一对应的,所以就不需要额外的计数器来记月份了。利用这个position就可以知道我们要加载哪个月份的数据了。这样一来,计数的问题就解决了。
当然了,在实际操作时由于需要循环,只传一个view是实现不了的,还要加上头尾两个view(原因请看android中用ViewPager实现循环滑动 一文),因此总共只要传3个view到viewPagerAdapter中就可以了,实现了占用资源的最小化,代码也简洁易懂。
好,大体的思路就是这样,下面来看看代码:
1、在viewPagerAdapter中的getCount()方法返回要显示的月份个数,另外加上两个用于循环的view所占的位置
@Override
public int getCount() {
// 这里作为示例我们只显示12个月的日期,另外加上两个用于循环的view
return 12 + 2;
}
2、在instantiateItem(ViewGroup container, int position)方法中复用我们传入的view,也即是日历的布局。然后根据position动态绑定要显示的数据。
@Override
public Object instantiateItem(ViewGroup container, int position) {
// 复用日历布局,动态改变布局展示的数据
int index = position % mViews.size();
View v = mViews.get(index);
if (container.indexOfChild(v) != -1) {
container.removeView(v);
}
container.addView(v);
// 动态改变View里面的显示内容
bindData(v, position);
return v;
}
3、绑定数据,根据position就可以知道我们要显示哪个月份的数据,要注意一点的就是在一头一尾两个位置时,要分别设置最后一个月份与第一个月份的数据,本例中position等于1-12时显示1-12月的数据,等于0时显示12月份数据,等于13时显示1月份数据
/**
* 绑定数据
* @param v
* @param position
*/
private void bindData(View v, int position) {
// 这里只要根据position就可以知道要显示哪个月的内容了,而不必额外记住当前要显示什么内容
TextView tv = (TextView) v;
String s;
if (position == 0) {
s = (getCount() - 2) + "";
} else if (position == getCount() - 1) {
s = "1";
} else {
s = position + "";
}
tv.setText("2017年" + s + "月");
}
4、由于第2步中我们删除了container中与新添加进来的veiw重复的view,所以在destroyItem方法不要再去删除任何view,保持为空方法即可。
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
这样主要的代码就完成了。
来看下效果:
最后,上源码:
demo源码:https://github.com/MingHuang1024/FlexiableViewPager
由于水平有限,如果文中存在错误之处,请大家批评指正,欢迎大家一起来分享、探讨!
博客:http://blog.csdn.net/MingHuang2017
GitHub:https://github.com/MingHuang1024
Email:MingHuang1024@foxmail.com
微信:724360018