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

想这个需求没办法实现;在去上厕所的路上突然想到了一个点子,第二天一试,尼玛,搞了这么久的东西,十几二十分钟就解决了......
这次我遇到的是这样一个问题,由于系统的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:
        
package tk.sweetvvck.calender.adapter;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date; import tk.sweetvvck.calender.R;
import android.app.Activity;
import android.content.res.Resources;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView; public class CalendarGridViewAdapter extends BaseAdapter { private Calendar calStartDate = Calendar.getInstance();// 当前显示的日历
private Calendar calToday = Calendar.getInstance(); // 今日
private int iMonthViewCurrentMonth = 0; // 当前视图月
// 根据改变的日期更新日历
// 填充日历控件用
private void UpdateStartDateForMonth() {
calStartDate.set(Calendar.DATE, 1); // 设置成当月第一天
iMonthViewCurrentMonth = calStartDate.get(Calendar.MONTH);// 得到当前日历显示的月 // 星期一是2 星期天是1 填充剩余天数
int iDay = 0;
int iFirstDayOfWeek = Calendar.MONDAY;
int iStartDay = iFirstDayOfWeek;
if (iStartDay == Calendar.MONDAY) {
iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.MONDAY;
if (iDay < 0)
iDay = 6;
}
if (iStartDay == Calendar.SUNDAY) {
iDay = calStartDate.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY;
if (iDay < 0)
iDay = 6;
}
calStartDate.add(Calendar.DAY_OF_WEEK, -iDay); calStartDate.add(Calendar.DAY_OF_MONTH, -1);// 周日第一位 }
ArrayList<java.util.Date> titles;
private ArrayList<java.util.Date> getDates() { UpdateStartDateForMonth(); ArrayList<java.util.Date> alArrayList = new ArrayList<java.util.Date>(); for (int i = 1; i <= 42; i++) {
alArrayList.add(calStartDate.getTime());
calStartDate.add(Calendar.DAY_OF_MONTH, 1);
} return alArrayList;
} private Activity activity;
Resources resources;
// construct
public CalendarGridViewAdapter(Activity a,Calendar cal) {
calStartDate=cal;
activity = a;
resources=activity.getResources();
titles = getDates();
} public CalendarGridViewAdapter(Activity a) {
activity = a;
resources=activity.getResources();
} @Override
public int getCount() {
return titles.size();
} @Override
public Object getItem(int position) {
return titles.get(position);
} @Override
public long getItemId(int position) {
return position;
} @SuppressWarnings("deprecation")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout iv = new LinearLayout(activity);
iv.setGravity(Gravity.CENTER);
iv.setOrientation(LinearLayout.VERTICAL);
iv.setBackgroundColor(resources.getColor(R.color.white)); Date myDate = (Date) getItem(position);
Calendar calCalendar = Calendar.getInstance();
calCalendar.setTime(myDate); final int iMonth = calCalendar.get(Calendar.MONTH);
final int iDay = calCalendar.get(Calendar.DAY_OF_WEEK); // 判断周六周日
iv.setBackgroundColor(resources.getColor(R.color.white));
if (iDay == 7) {
// 周六
iv.setBackgroundColor(resources.getColor(R.color.text_6));
} else if (iDay == 1) {
// 周日
iv.setBackgroundColor(resources.getColor(R.color.text_7));
} else { }
// 判断周六周日结束 TextView txtToDay = new TextView(activity);
txtToDay.setGravity(Gravity.CENTER_HORIZONTAL);
txtToDay.setTextSize(9);
if (equalsDate(calToday.getTime(), myDate)) {
// 当前日期
iv.setBackgroundColor(resources.getColor(R.color.selection));
txtToDay.setText("TODAY!");
}
// 设置背景颜色结束 // 日期开始
TextView txtDay = new TextView(activity);// 日期
txtDay.setGravity(Gravity.CENTER_HORIZONTAL); // 判断是否是当前月
if (iMonth == iMonthViewCurrentMonth) {
txtToDay.setTextColor(resources.getColor(R.color.ToDayText));
txtDay.setTextColor(resources.getColor(R.color.Text));
} else {
txtDay.setTextColor(resources.getColor(R.color.noMonth));
txtToDay.setTextColor(resources.getColor(R.color.noMonth));
} int day = myDate.getDate(); // 日期
txtDay.setText(String.valueOf(day)); LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
iv.addView(txtDay, lp); LinearLayout.LayoutParams lp1 = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
iv.addView(txtToDay, lp1); return iv;
} @SuppressWarnings("deprecation")
private Boolean equalsDate(Date date1, Date date2) {
if (date1.getYear() == date2.getYear()
&& date1.getMonth() == date2.getMonth()
&& date1.getDate() == date2.getDate()) {
return true;
} else {
return false;
}
}
}
        然后编写根据页数不同来创建不同日历的Fragment:

 /*
* Copyright 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package tk.sweetvvck.calender.activity;
import java.util.Calendar;
import tk.sweetvvck.calender.R;
import tk.sweetvvck.calender.adapter.CalendarGridViewAdapter;
import tk.sweetvvck.calender.utils.Utils;
import android.app.Activity;
import android.app.Fragment;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
public class CalendarFragment extends Fragment {
public static final String ARG_PAGE = "page";
private int mPageNumber;
private Calendar mCalendar;
private CalendarGridViewAdapter calendarGridViewAdapter;
public static Fragment create(int pageNumber) {
CalendarFragment fragment = new CalendarFragment();
Bundle args = new Bundle();
args.putInt(ARG_PAGE, pageNumber);
fragment.setArguments(args);
return fragment;
}
public CalendarFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mPageNumber = getArguments().getInt(ARG_PAGE);
mCalendar = Utils.getSelectCalendar(mPageNumber);
calendarGridViewAdapter = new CalendarGridViewAdapter(getActivity(),
mCalendar);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout containing a title and body text.
ViewGroup rootView = (ViewGroup) inflater.inflate(
R.layout.calendar_view, container, false);
GridView titleGridView = (GridView) rootView
.findViewById(R.id.gridview);
TitleGridAdapter titleAdapter = new TitleGridAdapter(getActivity());
initGridView(titleGridView, titleAdapter);
GridView calendarView = (GridView) rootView
.findViewById(R.id.calendarView);
initGridView(calendarView, calendarGridViewAdapter);
calendarView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
for (int i = 0; i < parent.getCount(); i++) {
if ((i % 7) == 6) {
parent.getChildAt(i).setBackgroundColor(
getActivity().getResources().getColor(
R.color.text_6));
} else if ((i % 7) == 0) {
parent.getChildAt(i).setBackgroundColor(
getActivity().getResources().getColor(
R.color.text_7));
} else {
parent.getChildAt(i).setBackgroundColor(
Color.TRANSPARENT);
}
}
view.setBackgroundColor(getActivity().getResources().getColor(
R.color.selection));
}
});
return rootView;
}
private void initGridView(GridView gridView, BaseAdapter adapter) {
gridView = setGirdView(gridView);
gridView.setAdapter(adapter);// 设置菜单Adapter
}
@SuppressWarnings("deprecation")
private GridView setGirdView(GridView gridView) {
gridView.setNumColumns(7);// 设置每行列数
gridView.setGravity(Gravity.CENTER_VERTICAL);// 位置居中
gridView.setVerticalSpacing(1);// 垂直间隔
gridView.setHorizontalSpacing(1);// 水平间隔
gridView.setBackgroundColor(getResources().getColor(
R.color.calendar_background));
WindowManager windowManager = getActivity().getWindowManager();
Display display = windowManager.getDefaultDisplay();
int i = display.getWidth() / 7;
int j = display.getWidth() - (i * 7);
int x = j / 2;
gridView.setPadding(x, 0, 0, 0);// 居中
return gridView;
}
public class TitleGridAdapter extends BaseAdapter {
int[] titles = new int[] { R.string.Sun, R.string.Mon, R.string.Tue,
R.string.Wed, R.string.Thu, R.string.Fri, R.string.Sat };
private Activity activity;
// construct
public TitleGridAdapter(Activity a) {
activity = a;
}
@Override
public int getCount() {
return titles.length;
}
@Override
public Object getItem(int position) {
return titles[position];
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout iv = new LinearLayout(activity);
TextView txtDay = new TextView(activity);
txtDay.setFocusable(false);
txtDay.setBackgroundColor(Color.TRANSPARENT);
iv.setOrientation(LinearLayout.VERTICAL);
txtDay.setGravity(Gravity.CENTER);
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
int i = (Integer) getItem(position);
txtDay.setTextColor(Color.GRAY);
Resources res = getResources();
if (i == R.string.Sat) {
// 周六
txtDay.setBackgroundColor(res.getColor(R.color.title_text_6));
} else if (i == R.string.Sun) {
// 周日
txtDay.setBackgroundColor(res.getColor(R.color.title_text_7));
} else {
}
txtDay.setText((Integer) getItem(position));
iv.addView(txtDay, lp);
return iv;
}
}
}

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

package tk.sweetvvck.calender.activity;

import java.util.Calendar;
import tk.sweetvvck.calender.R;
import tk.sweetvvck.calender.utils.Utils;
import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.widget.TextView;
/**
* 日历
* @author 程科
*/
public class MainActivity extends FragmentActivity {
private ViewPager viewPager;
private TextView tvMonth;
private String month;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager) this.findViewById(R.id.viewpager);
final ScreenSlidePagerAdapter screenSlidePagerAdapter = new ScreenSlidePagerAdapter(
getFragmentManager());
viewPager.setAdapter(screenSlidePagerAdapter);
viewPager.setCurrentItem(500);
tvMonth = (TextView) this.findViewById(R.id.tv_month);
month = Calendar.getInstance().get(Calendar.YEAR)
+ "-"
+ Utils.LeftPad_Tow_Zero(Calendar.getInstance().get(
Calendar.MONTH) + 1);
tvMonth.setText(month);
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
Calendar calendar = Utils.getSelectCalendar(position);
month = calendar.get(Calendar.YEAR)
+ "-"
+ Utils.LeftPad_Tow_Zero(calendar.get(Calendar.MONTH) + 1);
tvMonth.setText(month);
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
}
private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter {
public ScreenSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return CalendarFragment.create(position);
}
@Override
public int getCount() {
return 1000;
}
}
}


使用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. Teach Yourself Scheme in Fixnum Days 13 Jump跳转

    Jumps One of the signal features of Scheme is its support for jumps or nonlocal control. Specificall ...

  2. bzoj4033

    http://www.lydsy.com/JudgeOnline/problem.php?id=4033 树形DP. 我们发现,每条边都是一条桥,若我们知道这条边其中一侧有多少个黑点,我们就可以知道这 ...

  3. poj 3744 Scout YYF I (矩阵)

    Description YYF -p. Here is the task, given the place of each mine, please calculate the probality t ...

  4. 手动同步chrome浏览器

    chrome浏览器每次设置好的标签在重新开机后都会变回设置前的状态,崩溃,每次设置好后还是手动同步一下吧. 1. 点击 工具(右上角的三个点)-->设置 2. 点击 高级同步设置 3. 点击 使 ...

  5. 如何将EXCEL表导入MYSQL

            在平时的工作学习中,难免会遇到需要把EXCEL表中的数据导入到MYSQL中,比如要把EXCEL中的数据进行核对,或者要把测试用例导入到TestLink中.本人搜集相关的资料并加以实践总 ...

  6. 调用百度地图API实现手机自动定位 (逆地址解析)

    //声明地址解析器 var geoc = new BMap.Geocoder(); //自动定位 var autoLocation = function () { if (navigator.geol ...

  7. Oracle关联查询关于left/right join的那点事

    /*题外话 --更改foreign key约束定义引用行(delete cascade/delete set null/delete no action),默认delete on action--引用 ...

  8. (一)原生JS实现 - 基本类方法

    类 var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } } ...

  9. arm汇编(c内嵌汇编及c和汇编互调)

    C语言编译成汇编: arm-linux-gcc -S test.c -o test.S C语言编译成可执行文件: arm-linux-gcc test.c -o test 多个文件编译链接: arm- ...

  10. coconHashMap实现原理分析

    1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1 ...