有时候就是这样,研究一个问题,一开始想到了一个觉得可行的方案,然后去尝试;尝试了很久、很多次,已经要放弃了,关掉电脑心里

想这个需求没办法实现;在去上厕所的路上突然想到了一个点子,第二天一试,尼玛,搞了这么久的东西,十几二十分钟就解决了......
这次我遇到的是这样一个问题,由于系统的CalendarView不太美观,所以要自己实现一个日历的布局;所以想到了使用GridView,然后

用ViewPager做左右滑动切换日期的效果;

        但是ViewPager是确定页数来滑动的,而且一般启动的时候只能像左滑;而日历是两边都能够滑动的,并且页数不确定;为了实现这个效果,我的思路是给ViewPager指定Adapter的时候,在adapter的getCount方法中返回一个很大的值,大到用户很定不会吃多了去滑那么多次;我指定的是1000;然后设置当前的页面数为500,这要就能够左右滑很多次了,相当于无限滑了;

        开始做的时候不太了解ViewPager的工作原理,就想在ViewPager的page里定义一个静态的Calendar,和一个静态的
mCurrentPageNumber
来分别代表当前展示的日期和当前所示的ViewPager的页数;然后滑动的时候,根据传进来的pageNum和当前的mCurrentPageNumber的大小来判断创建的日历是下个月,还是上个月;

        于是我按照这个思路开始写代码,完成之后发现老是有问题;总是月数不对,或者滑动的时候就错位了;后来我慢慢理解了ViewPager的工作原理,发现ViewPager是在初始化的时候按照当前页分别创建当前页的左边的页面和当前页右边的页面;按照我的上述思路的顺序是:
500,499,501;也就是初始化结束的时候
mCurrentPageNumber的值为501;问题就出在这里,刚开始的时候初始化500,比如500代表8月,那么499的时候就是七月,这没有问题,可是当七月的界面创建完成之后,当前的Calendar就是七月,而
mCurrentPageNumber是499,在创建501的时候七月加1就是八月,也就是本来501代表9月,可是显示的是8月;滑动之后还出现了各种不可预知的结果......然后我就开始无数次的微调,判断如果是初始化就怎么样,然后就怎么样;改变当前页的值等等;一直一直弄了很久之后我都要昏了可还是没有搞定;最后决定算了,解决不了......
        后来上了个厕所回来突然想到了另一个方法,如果这个保存当前状态然后相对的来增加减少月份不行,那使用500为基准,使用传入的页数的与500的绝对差来作为创建月数的标准行不行呢?然后就将这个方法记录了一下,今天来试验的时候发现,尼玛二十分钟就搞定了....而且代码比昨天写的还少了太多太多,根本就不需要那么多的静态变量来存储当前状态;
        有时候编程序真的需要灵感和运气还有对使用控件的了解情况,之前保存当前状态的方法在很多地方都用到,所以刚开始我就想到的是这个方法;而且当我了解了ViewPager的工作原理的时候还想用这种方法来尝试,其实它跟ViewPager的工作原理是不和的,肯定会出问题;这个时候我就应该考虑其他的方法,要是这样的话问题早解决了.....
        好了,来看看我最后是怎么实现这个需求的;
        程序的大致结构是,最外层是ViewPager,ViewPager的每一个页面是一个Fragment,然后再Fragment里根据ViewPager的Adapter传入的页面数创建不同月份的Fragment;
        首先创建一个能够显示日期的GridView的Adapter:
        
  1. package tk.sweetvvck.calender.adapter;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.Calendar;
  5. import java.util.Date;
  6.  
  7. import tk.sweetvvck.calender.R;
  8. import android.app.Activity;
  9. import android.content.res.Resources;
  10. import android.view.Gravity;
  11. import android.view.View;
  12. import android.view.ViewGroup;
  13. import android.widget.BaseAdapter;
  14. import android.widget.LinearLayout;
  15. import android.widget.LinearLayout.LayoutParams;
  16. import android.widget.TextView;
  17.  
  18. public class CalendarGridViewAdapter extends BaseAdapter {
  19.  
  20. private Calendar calStartDate = Calendar.getInstance();// 当前显示的日历
  21. private Calendar calToday = Calendar.getInstance(); // 今日
  22. private int iMonthViewCurrentMonth = 0; // 当前视图月
  23. // 根据改变的日期更新日历
  24. // 填充日历控件用
  25. private void UpdateStartDateForMonth() {
  26. calStartDate.set(Calendar.DATE, 1); // 设置成当月第一天
  27. iMonthViewCurrentMonth = calStartDate.get(Calendar.MONTH);// 得到当前日历显示的月
  28.  
  29. // 星期一是2 星期天是1 填充剩余天数
  30. int iDay = 0;
  31. int iFirstDayOfWeek = Calendar.MONDAY;
  32. int iStartDay = iFirstDayOfWeek;
  33. if (iStartDay == Calendar.MONDAY) {
  34. iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY;
  35. if (iDay < 0)
  36. iDay = 6;
  37. }
  38. if (iStartDay == Calendar.SUNDAY) {
  39. iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
  40. if (iDay < 0)
  41. iDay = 6;
  42. }
  43. calStartDate.add(Calendar.DAY_OF_WEEK, -iDay);
  44.  
  45. calStartDate.add(Calendar.DAY_OF_MONTH, -1);// 周日第一位
  46.  
  47. }
  48. ArrayList<java.util.Date> titles;
  49. private ArrayList<java.util.Date> getDates() {
  50.  
  51. UpdateStartDateForMonth();
  52.  
  53. ArrayList<java.util.Date> alArrayList = new ArrayList<java.util.Date>();
  54.  
  55. for (int i = 1; i <= 42; i++) {
  56. alArrayList.add(calStartDate.getTime());
  57. calStartDate.add(Calendar.DAY_OF_MONTH, 1);
  58. }
  59.  
  60. return alArrayList;
  61. }
  62.  
  63. private Activity activity;
  64. Resources resources;
  65. // construct
  66. public CalendarGridViewAdapter(Activity a,Calendar cal) {
  67. calStartDate=cal;
  68. activity = a;
  69. resources=activity.getResources();
  70. titles = getDates();
  71. }
  72.  
  73. public CalendarGridViewAdapter(Activity a) {
  74. activity = a;
  75. resources=activity.getResources();
  76. }
  77.  
  78. @Override
  79. public int getCount() {
  80. return titles.size();
  81. }
  82.  
  83. @Override
  84. public Object getItem(int position) {
  85. return titles.get(position);
  86. }
  87.  
  88. @Override
  89. public long getItemId(int position) {
  90. return position;
  91. }
  92.  
  93. @SuppressWarnings("deprecation")
  94. @Override
  95. public View getView(int position, View convertView, ViewGroup parent) {
  96. LinearLayout iv = new LinearLayout(activity);
  97. iv.setGravity(Gravity.CENTER);
  98. iv.setOrientation(LinearLayout.VERTICAL);
  99. iv.setBackgroundColor(resources.getColor(R.color.white));
  100.  
  101. Date myDate = (Date) getItem(position);
  102. Calendar calCalendar = Calendar.getInstance();
  103. calCalendar.setTime(myDate);
  104.  
  105. final int iMonth = calCalendar.get(Calendar.MONTH);
  106. final int iDay = calCalendar.get(Calendar.DAY_OF_WEEK);
  107.  
  108. // 判断周六周日
  109. iv.setBackgroundColor(resources.getColor(R.color.white));
  110. if (iDay == 7) {
  111. // 周六
  112. iv.setBackgroundColor(resources.getColor(R.color.text_6));
  113. } else if (iDay == 1) {
  114. // 周日
  115. iv.setBackgroundColor(resources.getColor(R.color.text_7));
  116. } else {
  117.  
  118. }
  119. // 判断周六周日结束
  120.  
  121. TextView txtToDay = new TextView(activity);
  122. txtToDay.setGravity(Gravity.CENTER_HORIZONTAL);
  123. txtToDay.setTextSize(9);
  124. if (equalsDate(calToday.getTime(), myDate)) {
  125. // 当前日期
  126. iv.setBackgroundColor(resources.getColor(R.color.selection));
  127. txtToDay.setText("TODAY!");
  128. }
  129. // 设置背景颜色结束
  130.  
  131. // 日期开始
  132. TextView txtDay = new TextView(activity);// 日期
  133. txtDay.setGravity(Gravity.CENTER_HORIZONTAL);
  134.  
  135. // 判断是否是当前月
  136. if (iMonth == iMonthViewCurrentMonth) {
  137. txtToDay.setTextColor(resources.getColor(R.color.ToDayText));
  138. txtDay.setTextColor(resources.getColor(R.color.Text));
  139. } else {
  140. txtDay.setTextColor(resources.getColor(R.color.noMonth));
  141. txtToDay.setTextColor(resources.getColor(R.color.noMonth));
  142. }
  143.  
  144. int day = myDate.getDate(); // 日期
  145. txtDay.setText(String.valueOf(day));
  146.  
  147. LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
  148. LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
  149. iv.addView(txtDay, lp);
  150.  
  151. LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(
  152. LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
  153. iv.addView(txtToDay, lp1);
  154.  
  155. return iv;
  156. }
  157.  
  158. @SuppressWarnings("deprecation")
  159. private Boolean equalsDate(Date date1, Date date2) {
  160. if (date1.getYear() == date2.getYear()
  161. && date1.getMonth() == date2.getMonth()
  162. && date1.getDate() == date2.getDate()) {
  163. return true;
  164. } else {
  165. return false;
  166. }
  167. }
  168. }
        然后编写根据页数不同来创建不同日历的Fragment:

  1. /*
  2. * Copyright 2012 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package tk.sweetvvck.calender.activity;
  17. import java.util.Calendar;
  18. import tk.sweetvvck.calender.R;
  19. import tk.sweetvvck.calender.adapter.CalendarGridViewAdapter;
  20. import tk.sweetvvck.calender.utils.Utils;
  21. import android.app.Activity;
  22. import android.app.Fragment;
  23. import android.content.res.Resources;
  24. import android.graphics.Color;
  25. import android.os.Bundle;
  26. import android.view.Display;
  27. import android.view.Gravity;
  28. import android.view.LayoutInflater;
  29. import android.view.View;
  30. import android.view.ViewGroup;
  31. import android.view.WindowManager;
  32. import android.widget.AdapterView;
  33. import android.widget.AdapterView.OnItemClickListener;
  34. import android.widget.BaseAdapter;
  35. import android.widget.GridView;
  36. import android.widget.LinearLayout;
  37. import android.widget.LinearLayout.LayoutParams;
  38. import android.widget.TextView;
  39. public class CalendarFragment extends Fragment {
  40. public static final String ARG_PAGE = "page";
  41. private int mPageNumber;
  42. private Calendar mCalendar;
  43. private CalendarGridViewAdapter calendarGridViewAdapter;
  44. public static Fragment create(int pageNumber) {
  45. CalendarFragment fragment = new CalendarFragment();
  46. Bundle args = new Bundle();
  47. args.putInt(ARG_PAGE, pageNumber);
  48. fragment.setArguments(args);
  49. return fragment;
  50. }
  51. public CalendarFragment() {
  52. }
  53. @Override
  54. public void onCreate(Bundle savedInstanceState) {
  55. super.onCreate(savedInstanceState);
  56. mPageNumber = getArguments().getInt(ARG_PAGE);
  57. mCalendar = Utils.getSelectCalendar(mPageNumber);
  58. calendarGridViewAdapter = new CalendarGridViewAdapter(getActivity(),
  59. mCalendar);
  60. }
  61. @Override
  62. public View onCreateView(LayoutInflater inflater, ViewGroup container,
  63. Bundle savedInstanceState) {
  64. // Inflate the layout containing a title and body text.
  65. ViewGroup rootView = (ViewGroup) inflater.inflate(
  66. R.layout.calendar_view, container, false);
  67. GridView titleGridView = (GridView) rootView
  68. .findViewById(R.id.gridview);
  69. TitleGridAdapter titleAdapter = new TitleGridAdapter(getActivity());
  70. initGridView(titleGridView, titleAdapter);
  71. GridView calendarView = (GridView) rootView
  72. .findViewById(R.id.calendarView);
  73. initGridView(calendarView, calendarGridViewAdapter);
  74. calendarView.setOnItemClickListener(new OnItemClickListener() {
  75. @Override
  76. public void onItemClick(AdapterView<?> parent, View view,
  77. int position, long id) {
  78. for (int i = 0; i < parent.getCount(); i++) {
  79. if ((i % 7) == 6) {
  80. parent.getChildAt(i).setBackgroundColor(
  81. getActivity().getResources().getColor(
  82. R.color.text_6));
  83. } else if ((i % 7) == 0) {
  84. parent.getChildAt(i).setBackgroundColor(
  85. getActivity().getResources().getColor(
  86. R.color.text_7));
  87. } else {
  88. parent.getChildAt(i).setBackgroundColor(
  89. Color.TRANSPARENT);
  90. }
  91. }
  92. view.setBackgroundColor(getActivity().getResources().getColor(
  93. R.color.selection));
  94. }
  95. });
  96. return rootView;
  97. }
  98. private void initGridView(GridView gridView, BaseAdapter adapter) {
  99. gridView = setGirdView(gridView);
  100. gridView.setAdapter(adapter);// 设置菜单Adapter
  101. }
  102. @SuppressWarnings("deprecation")
  103. private GridView setGirdView(GridView gridView) {
  104. gridView.setNumColumns(7);// 设置每行列数
  105. gridView.setGravity(Gravity.CENTER_VERTICAL);// 位置居中
  106. gridView.setVerticalSpacing(1);// 垂直间隔
  107. gridView.setHorizontalSpacing(1);// 水平间隔
  108. gridView.setBackgroundColor(getResources().getColor(
  109. R.color.calendar_background));
  110. WindowManager windowManager = getActivity().getWindowManager();
  111. Display display = windowManager.getDefaultDisplay();
  112. int i = display.getWidth() / 7;
  113. int j = display.getWidth() - (i * 7);
  114. int x = j / 2;
  115. gridView.setPadding(x, 0, 0, 0);// 居中
  116. return gridView;
  117. }
  118. public class TitleGridAdapter extends BaseAdapter {
  119. int[] titles = new int[] { R.string.Sun, R.string.Mon, R.string.Tue,
  120. R.string.Wed, R.string.Thu, R.string.Fri, R.string.Sat };
  121. private Activity activity;
  122. // construct
  123. public TitleGridAdapter(Activity a) {
  124. activity = a;
  125. }
  126. @Override
  127. public int getCount() {
  128. return titles.length;
  129. }
  130. @Override
  131. public Object getItem(int position) {
  132. return titles[position];
  133. }
  134. @Override
  135. public long getItemId(int position) {
  136. return position;
  137. }
  138. @Override
  139. public View getView(int position, View convertView, ViewGroup parent) {
  140. LinearLayout iv = new LinearLayout(activity);
  141. TextView txtDay = new TextView(activity);
  142. txtDay.setFocusable(false);
  143. txtDay.setBackgroundColor(Color.TRANSPARENT);
  144. iv.setOrientation(LinearLayout.VERTICAL);
  145. txtDay.setGravity(Gravity.CENTER);
  146. LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
  147. LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
  148. int i = (Integer) getItem(position);
  149. txtDay.setTextColor(Color.GRAY);
  150. Resources res = getResources();
  151. if (i == R.string.Sat) {
  152. // 周六
  153. txtDay.setBackgroundColor(res.getColor(R.color.title_text_6));
  154. } else if (i == R.string.Sun) {
  155. // 周日
  156. txtDay.setBackgroundColor(res.getColor(R.color.title_text_7));
  157. } else {
  158. }
  159. txtDay.setText((Integer) getItem(position));
  160. iv.addView(txtDay, lp);
  161. return iv;
  162. }
  163. }
  164. }

        然后在来完成Activity里的ViewPager的创建以及ViewPager的Adapter:

  1. package tk.sweetvvck.calender.activity;
  2.  
  3. import java.util.Calendar;
  4. import tk.sweetvvck.calender.R;
  5. import tk.sweetvvck.calender.utils.Utils;
  6. import android.app.Fragment;
  7. import android.app.FragmentManager;
  8. import android.os.Bundle;
  9. import android.support.v13.app.FragmentStatePagerAdapter;
  10. import android.support.v4.app.FragmentActivity;
  11. import android.support.v4.view.ViewPager;
  12. import android.widget.TextView;
  13. /**
  14. * 日历
  15. * @author 程科
  16. */
  17. public class MainActivity extends FragmentActivity {
  18. private ViewPager viewPager;
  19. private TextView tvMonth;
  20. private String month;
  21. @Override
  22. protected void onCreate(Bundle savedInstanceState) {
  23. super.onCreate(savedInstanceState);
  24. setContentView(R.layout.activity_main);
  25. viewPager = (ViewPager) this.findViewById(R.id.viewpager);
  26. final ScreenSlidePagerAdapter screenSlidePagerAdapter = new ScreenSlidePagerAdapter(
  27. getFragmentManager());
  28. viewPager.setAdapter(screenSlidePagerAdapter);
  29. viewPager.setCurrentItem(500);
  30. tvMonth = (TextView) this.findViewById(R.id.tv_month);
  31. month = Calendar.getInstance().get(Calendar.YEAR)
  32. + "-"
  33. + Utils.LeftPad_Tow_Zero(Calendar.getInstance().get(
  34. Calendar.MONTH) + 1);
  35. tvMonth.setText(month);
  36. viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
  37. @Override
  38. public void onPageSelected(int position) {
  39. Calendar calendar = Utils.getSelectCalendar(position);
  40. month = calendar.get(Calendar.YEAR)
  41. + "-"
  42. + Utils.LeftPad_Tow_Zero(calendar.get(Calendar.MONTH) + 1);
  43. tvMonth.setText(month);
  44. }
  45. @Override
  46. public void onPageScrolled(int position, float positionOffset,
  47. int positionOffsetPixels) {
  48. }
  49. @Override
  50. public void onPageScrollStateChanged(int state) {
  51. }
  52. });
  53. }
  54. private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
  55. public ScreenSlidePagerAdapter(FragmentManager fm) {
  56. super(fm);
  57. }
  58. @Override
  59. public Fragment getItem(int position) {
  60. return CalendarFragment.create(position);
  61. }
  62. @Override
  63. public int getCount() {
  64. return 1000;
  65. }
  66. }
  67. }


使用ViewPager实现左右“无限”滑动的万年历的更多相关文章

  1. ViewPager结合view无限滑动

    使用viewPager进无限滑动,这里的实现是在适配器里面进行,当然在外头使用滑动监听也行. import android.support.v4.view.PagerAdapter; import a ...

  2. ViewPager无限滑动

    2016-6-19 前言 View轮播效果在app中很常见,一想到左右滑动的效果就很容易想到使用ViewPager来实现.对于像我们常说的banner这样的效果,具备无限滑动的功能是可以用ViewPa ...

  3. Android使用ViewPager实现左右循环滑动及轮播效果

    边界的时候会看到一个不能翻页的动画,可能影响用户体验.此外,某些区域性的ViewPager(例如展示广告或者公告之类的ViewPager),可能需要自动轮播的效果,即用户在不用滑动的情况下就能够看到其 ...

  4. android笔记:ViewPager实现界面的滑动

    最近在学习ViewPager实现界面的滑动,拜读了郭神的博客文章,并抽取归纳了自己对ViewPager的理解. ViewPager实现界面滑动的步骤如下: 1.在xml布局内加入控件android.s ...

  5. Android 使用ViewPager实现左右循环滑动图片

    ViewPager这个小demo实现的是可以左右循环滑动图片,下面带索引,滑到最后一页在往右滑动就要第一页,第一页往左滑动就到最后一页,先上效果图,用美女图片是我一贯的作风,呵呵 1.    首先看一 ...

  6. android 解决ViewPager双层嵌套的滑动问题

    解决ViewPager双层嵌套的滑动问题 今天我分享一下ViewPager的双层嵌套时影响内部ViewPager的触摸滑动问题 之前在做自己的一个项目的时候,遇到广告栏图片动态切换,我第一时间想到的就 ...

  7. Android实战简易教程-第三十四枪(基于ViewPager和FragmentPagerAdapter实现滑动通用Tab)

    上一段时间写过一篇文章<基于ViewPager实现微信页面切换效果> 里面实现了相似微信Tab的页面.可是这样的实现方法有个问题.就是以后全部的代码逻辑都必须在MainActivity中实 ...

  8. Android 仿美团网,探索使用ViewPager+GridView实现左右滑动查看更多分类的功能

    看下效果图,自己考虑下自己会如何实现,然后再继续看看作者的实现~ 不记得什么时候,我留意到到美团网首页有使用ViewPager+GridView实现左右滑动查看更多分类的一个功能,感觉它很有趣,于是想 ...

  9. android 事件拦截 (Viewpager不可以左右滑动)

    以前没有做过真正的需求,所以从来没有觉得事件拦截分发处理有什么好懂的. 现在做需求了,真的是什么需求都有,你作为开发都要去研究实现.比如说,只能点不能滑动的viewpager.其实这都可以不用view ...

随机推荐

  1. 【转】将Vim改造为强大的IDE—Vim集成Ctags/Taglist/Cscope/Winmanager/NERDTree/OmniCppComplete(有图有真相)

    原文网址:http://blog.csdn.net/bokee/article/details/6633193 工欲善其事,必先利其器.一个强大的开发环境可以大大提高工作效率.好吧,我知道这是废话.. ...

  2. 【转】深入理解Android的startservice和bindservice--不错

    原文网址:http://www.cnblogs.com/yejiurui/p/3429451.html 一.首先,让我们确认下什么是service?         service就是android系 ...

  3. 推荐2个小工具 .NET reflector resharper

  4. centos6.4安装Vmware exsi CLI

    1,Vmware官网Exsi CLI下载链接 https://download2.vmware.com/software/sdk/VMware-vSphere-CLI-4.1.0-254719.x86 ...

  5. 用Nginx实现Session共享的均衡负载

    前言 大学三年多,也做个几个网站和APP后端,老是被人问到,如果用户多了服务器会不会挂,总是很尴尬的回答:“哈哈,我们的用户还少,到了服务器撑不住的时候,估计都上市了吧”.说是这么说,但是对于有强迫症 ...

  6. mysql 获取当前时间戳

      mysql 获取当前时间为select now() 运行结果: 2012-09-05 17:24:15 mysql 获取当前时间戳为select unix_timestamp(now()) 运行结 ...

  7. qt下面例子学习(部分功能)

    from aa import Ui_Formfrom PyQt4.Qt import *from PyQt4.QtCore import *from PyQt4.QtGui import *from ...

  8. python倒计时

    #coding=utf-8 #!/usr/bin/env python import datetime,time i=3 while i==3: spring=datetime.datetime(20 ...

  9. [RxJS] Refactoring Composable Streams in RxJS, switchMap()

    Refactoring streams in RxJS is mostly moving pieces of smaller streams around. This lessons demonstr ...

  10. SQL 分组获取最近(大)一条记录

    SELECT MAX( table.Column),.... FROM table.Name WHERE ....... GROUP BY 分组规则