自定义日历控件,支持旧历、节气、日期标注、点击操作 (参考网络上的日历控件改写)

注:将下面的四张资源图片拷贝到所建包的下一个image目录中,如Calendar.java 所在包为

cc.util.android.view,则需要再创建一个包cc.util.android.view.image 然后将图片拷贝进去

/****************从此出开始将代码拷贝到一个文件中*******************/

package cc.util.android.view;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Calendar;

import java.util.Date;

import java.util.List;

import java.util.Locale;

import android.annotation.SuppressLint;

import android.content.Context;

import android.graphics.BitmapFactory;

import android.graphics.Color;

import android.graphics.drawable.BitmapDrawable;

import android.graphics.drawable.Drawable;

import android.graphics.drawable.StateListDrawable;

import android.text.TextUtils.TruncateAt;

import android.util.AttributeSet;

import android.view.GestureDetector;

import android.view.GestureDetector.OnGestureListener;

import android.view.Gravity;

import android.view.MotionEvent;

import android.view.View;

import android.view.ViewGroup;

import android.view.View.OnTouchListener;

import android.view.animation.Animation;

import android.view.animation.Animation.AnimationListener;

import android.view.animation.TranslateAnimation;

import android.widget.BaseAdapter;

import android.widget.GridView;

import android.widget.ImageButton;

import android.widget.LinearLayout;

import android.widget.RelativeLayout;

import android.widget.TextView;

import android.widget.ViewFlipper;

import android.widget.AbsListView.LayoutParams;

/**

* 日历控件,支持旧历、节气、日期标注、点击操作 (参考网络上的日历控件改写)

*

* @author wangcccong

* @version 1.406 create at: Mon, 03 Sep. 2014

*
update at: Mon, 23 Sep. 2014

*   新增日期标注和点击操作

*/

public class CalendarView extends LinearLayout implements OnTouchListener,

AnimationListener, OnGestureListener {

/**

* 点击日历

*/

public interface OnCalendarViewListener {

void onCalendarItemClick(CalendarView view, Date date);

}

/** 顶部控件所占高度 */

private final static int TOP_HEIGHT = 40;

/** 日历item中默认id从0xff0000开始 */

private final static int DEFAULT_ID = 0xff0000;

// 判断手势用

private static final int SWIPE_MIN_DISTANCE = 120;

private static final int SWIPE_MAX_OFF_PATH = 250;

private static final int SWIPE_THRESHOLD_VELOCITY = 200;

// 屏幕宽度和高度

private int screenWidth;

// 动画

private Animation slideLeftIn;

private Animation slideLeftOut;

private Animation slideRightIn;

private Animation slideRightOut;

private ViewFlipper viewFlipper;

private GestureDetector mGesture = null;

/** 上一月 */

private GridView gView1;

/** 当月 */

private GridView gView2;

/** 下一月 */

private GridView gView3;

boolean bIsSelection = false;// 是否是选择事件发生

private Calendar calStartDate = Calendar.getInstance();// 当前显示的日历

private Calendar calSelected = Calendar.getInstance(); // 选择的日历

private CalendarGridViewAdapter gAdapter;

private CalendarGridViewAdapter gAdapter1;

private CalendarGridViewAdapter gAdapter3;

private LinearLayout mMainLayout;

private TextView mTitle; // 显示年月

private int iMonthViewCurrentMonth = 0; // 当前视图月

private int iMonthViewCurrentYear = 0; // 当前视图年

private static final int caltitleLayoutID = 66; // title布局ID

private static final int calLayoutID = 55; // 日历布局ID

private Context mContext;

/** 标注日期 */

private final List markDates;

private OnCalendarViewListener mListener;

public CalendarView(Context context) {

this(context, null);

}

public CalendarView(Context context, AttributeSet attrs) {

super(context, attrs);

// TODO Auto-generated constructor stub

mContext = context;

markDates = new ArrayList();

init();

}

// 初始化相关工作

protected void init() {

// 得到屏幕的宽度

screenWidth = mContext.getResources().getDisplayMetrics().widthPixels;

// 滑动的动画

slideLeftIn = new TranslateAnimation(screenWidth, 0, 0, 0);

slideLeftIn.setDuration(400);

slideLeftIn.setAnimationListener(this);

slideLeftOut = new TranslateAnimation(0, -screenWidth, 0, 0);

slideLeftOut.setDuration(400);

slideLeftOut.setAnimationListener(this);

slideRightIn = new TranslateAnimation(-screenWidth, 0, 0, 0);

slideRightIn.setDuration(400);

slideRightIn.setAnimationListener(this);

slideRightOut = new TranslateAnimation(0, screenWidth, 0, 0);

slideRightOut.setDuration(400);

slideRightOut.setAnimationListener(this);

// 手势操作

mGesture = new GestureDetector(mContext, this);

// 获取到当前日期

UpdateStartDateForMonth();

// 绘制界面

setOrientation(LinearLayout.HORIZONTAL);

mMainLayout = new LinearLayout(mContext);

LinearLayout.LayoutParams main_params = new LinearLayout.LayoutParams(

LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

mMainLayout.setLayoutParams(main_params);

mMainLayout.setGravity(Gravity.CENTER_HORIZONTAL);

mMainLayout.setOrientation(LinearLayout.VERTICAL);

addView(mMainLayout);

// 顶部控件

generateTopView();

// 中间显示星期

generateWeekGirdView();

// 底部显示日历

viewFlipper = new ViewFlipper(mContext);

RelativeLayout.LayoutParams fliper_params = new RelativeLayout.LayoutParams(

LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

fliper_params.addRule(RelativeLayout.BELOW, caltitleLayoutID);

mMainLayout.addView(viewFlipper, fliper_params);

generateClaendarGirdView();

// 最下方的一条线条

LinearLayout br = new LinearLayout(mContext);

br.setBackgroundColor(Color.argb(0xff, 0xe3, 0xee, 0xf4));

LinearLayout.LayoutParams params_br = new LinearLayout.LayoutParams(

LayoutParams.MATCH_PARENT, 3);

mMainLayout.addView(br, params_br);

}

/** 生成顶部控件 */

@SuppressWarnings("deprecation")

private void generateTopView() {

// 顶部显示上一个下一个,以及当前年月

RelativeLayout top = new RelativeLayout(mContext);

top.setBackgroundColor(Color.argb(0xff, 0x0e, 0x6b, 0xc2));

LinearLayout.LayoutParams top_params = new LinearLayout.LayoutParams(

LayoutParams.MATCH_PARENT,

ViewUtil.dip2px(mContext, TOP_HEIGHT));

top.setLayoutParams(top_params);

mMainLayout.addView(top);

// 左方按钮、中间日期显示、右方按钮

mTitle = new TextView(mContext);

android.widget.RelativeLayout.LayoutParams title_params = new android.widget.RelativeLayout.LayoutParams(

android.widget.RelativeLayout.LayoutParams.MATCH_PARENT,

android.widget.RelativeLayout.LayoutParams.MATCH_PARENT);

mTitle.setLayoutParams(title_params);

mTitle.setTextColor(Color.WHITE);

mTitle.setTextSize(18);

mTitle.setFocusableInTouchMode(true);

mTitle.setMarqueeRepeatLimit(-1);

mTitle.setEllipsize(TruncateAt.MARQUEE);

mTitle.setSingleLine(true);

mTitle.setGravity(Gravity.CENTER);

mTitle.setHorizontallyScrolling(true);

mTitle.setText("2014年9月");

top.addView(mTitle);

// 左方按钮

ImageButton mLeftView = new ImageButton(mContext);

StateListDrawable stateListDrawableL = new StateListDrawable();

Drawable lDrawableNor = new BitmapDrawable(mContext.getResources(),

BitmapFactory.decodeStream(CalendarView.class

.getResourceAsStream("image/left_arrow.png")));

Drawable lDrawablePre = new BitmapDrawable(mContext.getResources(),

BitmapFactory.decodeStream(CalendarView.class

.getResourceAsStream("image/left_arrow_pre.png")));

stateListDrawableL.addState(

new int[] { -android.R.attr.state_pressed }, lDrawableNor);

stateListDrawableL.addState(new int[] { android.R.attr.state_pressed },

lDrawablePre);

mLeftView.setBackgroundDrawable(stateListDrawableL);

android.widget.RelativeLayout.LayoutParams leftPP = new android.widget.RelativeLayout.LayoutParams(

ViewUtil.dip2px(mContext, 25), ViewUtil.dip2px(mContext, 22));

leftPP.addRule(RelativeLayout.ALIGN_PARENT_LEFT);

leftPP.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);

leftPP.setMargins(20, 0, 0, 0);

mLeftView.setLayoutParams(leftPP);

mLeftView.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

viewFlipper.setInAnimation(slideRightIn);

viewFlipper.setOutAnimation(slideRightOut);

viewFlipper.showPrevious();

setPrevViewItem();

}

});

top.addView(mLeftView);

// 右方按钮

ImageButton mRightView = new ImageButton(mContext);

StateListDrawable stateListDrawable = new StateListDrawable();

Drawable rDrawableNor = new BitmapDrawable(mContext.getResources(),

BitmapFactory.decodeStream(CalendarView.class

.getResourceAsStream("image/right_arrow.png")));

Drawable rDrawablePre = new BitmapDrawable(mContext.getResources(),

BitmapFactory.decodeStream(CalendarView.class

.getResourceAsStream("image/right_arrow_pre.png")));

stateListDrawable.addState(new int[] { -android.R.attr.state_pressed },

rDrawableNor);

stateListDrawable.addState(new int[] { android.R.attr.state_pressed },

rDrawablePre);

mRightView.setBackgroundDrawable(stateListDrawable);

android.widget.RelativeLayout.LayoutParams rightPP = new android.widget.RelativeLayout.LayoutParams(

ViewUtil.dip2px(mContext, 25), ViewUtil.dip2px(mContext, 22));

rightPP.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);

rightPP.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);

rightPP.setMargins(0, 0, 20, 0);

mRightView.setLayoutParams(rightPP);

mRightView.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View v) {

// TODO Auto-generated method stub

viewFlipper.setInAnimation(slideLeftIn);

viewFlipper.setOutAnimation(slideLeftOut);

viewFlipper.showNext();

setNextViewItem();

}

});

top.addView(mRightView);

}

/** 生成中间显示week */

private void generateWeekGirdView() {

GridView gridView = new GridView(mContext);

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(

LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

gridView.setLayoutParams(params);

gridView.setNumColumns(7);// 设置每行列数

gridView.setGravity(Gravity.CENTER_VERTICAL);// 位置居中

gridView.setVerticalSpacing(1);// 垂直间隔

gridView.setHorizontalSpacing(1);// 水平间隔

gridView.setBackgroundColor(Color.argb(0xff, 0xe3, 0xee, 0xf4));

int i = screenWidth / 7;

int j = screenWidth - (i * 7);

int x = j / 2;

gridView.setPadding(x, 0, 0, 0);// 居中

WeekGridAdapter weekAdapter = new WeekGridAdapter(mContext);

gridView.setAdapter(weekAdapter);// 设置菜单Adapter

mMainLayout.addView(gridView);

}

/** 生成底部日历 */

private void generateClaendarGirdView() {

Calendar tempSelected1 = Calendar.getInstance(); // 临时

Calendar tempSelected2 = Calendar.getInstance(); // 临时

Calendar tempSelected3 = Calendar.getInstance(); // 临时

tempSelected1.setTime(calStartDate.getTime());

tempSelected2.setTime(calStartDate.getTime());

tempSelected3.setTime(calStartDate.getTime());

gView1 = new CalendarGridView(mContext);

tempSelected1.add(Calendar.MONTH, -1);

gAdapter1 = new CalendarGridViewAdapter(mContext, tempSelected1,

markDates);

gView1.setAdapter(gAdapter1);// 设置菜单Adapter

gView1.setId(calLayoutID);

gView2 = new CalendarGridView(mContext);

gAdapter = new CalendarGridViewAdapter(mContext, tempSelected2,

markDates);

gView2.setAdapter(gAdapter);// 设置菜单Adapter

gView2.setId(calLayoutID);

gView3 = new CalendarGridView(mContext);

tempSelected3.add(Calendar.MONTH, 1);

gAdapter3 = new CalendarGridViewAdapter(mContext, tempSelected3,

markDates);

gView3.setAdapter(gAdapter3);// 设置菜单Adapter

gView3.setId(calLayoutID);

gView2.setOnTouchListener(this);

gView1.setOnTouchListener(this);

gView3.setOnTouchListener(this);

if (viewFlipper.getChildCount() != 0) {

viewFlipper.removeAllViews();

}

viewFlipper.addView(gView2);

viewFlipper.addView(gView3);

viewFlipper.addView(gView1);

String title = calStartDate.get(Calendar.YEAR)

+ "年"

+ NumberHelper.LeftPad_Tow_Zero(calStartDate

.get(Calendar.MONTH) + 1) + "月";

mTitle.setText(title);

}

// 上一个月

private void setPrevViewItem() {

iMonthViewCurrentMonth--;// 当前选择月--

// 如果当前月为负数的话显示上一年

if (iMonthViewCurrentMonth == -1) {

iMonthViewCurrentMonth = 11;

iMonthViewCurrentYear--;

}

calStartDate.set(Calendar.DAY_OF_MONTH, 1); // 设置日为当月1日

calStartDate.set(Calendar.MONTH, iMonthViewCurrentMonth); // 设置月

calStartDate.set(Calendar.YEAR, iMonthViewCurrentYear); // 设置年

}

// 下一个月

private void setNextViewItem() {

iMonthViewCurrentMonth++;

if (iMonthViewCurrentMonth == 12) {

iMonthViewCurrentMonth = 0;

iMonthViewCurrentYear++;

}

calStartDate.set(Calendar.DAY_OF_MONTH, 1);

calStartDate.set(Calendar.MONTH, iMonthViewCurrentMonth);

calStartDate.set(Calendar.YEAR, iMonthViewCurrentYear);

}

// 根据改变的日期更新日历

// 填充日历控件用

private void UpdateStartDateForMonth() {

calStartDate.set(Calendar.DATE, 1); // 设置成当月第一天

iMonthViewCurrentMonth = calStartDate.get(Calendar.MONTH);// 得到当前日历显示的月

iMonthViewCurrentYear = calStartDate.get(Calendar.YEAR);// 得到当前日历显示的年

// 星期一是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);

}

/**

* 设置标注的日期

*

* @param markDates

*/

public void setMarkDates(List markDates) {

this.markDates.clear();

this.markDates.addAll(markDates);

gAdapter.notifyDataSetChanged();

gAdapter1.notifyDataSetChanged();

gAdapter3.notifyDataSetChanged();

}

/**

* 设置点击日历监听

*

* @param listener

*/

public void setOnCalendarViewListener(OnCalendarViewListener listener) {

this.mListener = listener;

}

@Override

public boolean onDown(MotionEvent e) {

// TODO Auto-generated method stub

return false;

}

@SuppressLint("ClickableViewAccessibility")

@Override

public boolean onTouch(View v, MotionEvent event) {

return mGesture.onTouchEvent(event);

}

@Override

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,

float velocityY) {

// TODO Auto-generated method stub

try {

if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)

return false;

// right to left swipe

if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE

&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {

viewFlipper.setInAnimation(slideLeftIn);

viewFlipper.setOutAnimation(slideLeftOut);

viewFlipper.showNext();

setNextViewItem();

return true;

} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE

&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {

viewFlipper.setInAnimation(slideRightIn);

viewFlipper.setOutAnimation(slideRightOut);

viewFlipper.showPrevious();

setPrevViewItem();

return true;

}

} catch (Exception e) {

// nothing

}

return false;

}

@Override

public void onLongPress(MotionEvent e) {

// TODO Auto-generated method stub

}

@Override

public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,

float distanceY) {

// TODO Auto-generated method stub

return false;

}

@Override

public void onShowPress(MotionEvent e) {

// TODO Auto-generated method stub

}

@Override

public boolean onSingleTapUp(MotionEvent e) {

// TODO Auto-generated method stub

// 得到当前选中的是第几个单元格

int pos = gView2.pointToPosition((int) e.getX(), (int) e.getY());

LinearLayout txtDay = (LinearLayout) gView2.findViewById(pos

+ DEFAULT_ID);

if (txtDay != null) {

if (txtDay.getTag() != null) {

Date date = (Date) txtDay.getTag();

calSelected.setTime(date);

gAdapter.setSelectedDate(calSelected);

gAdapter.notifyDataSetChanged();

gAdapter1.setSelectedDate(calSelected);

gAdapter1.notifyDataSetChanged();

gAdapter3.setSelectedDate(calSelected);

gAdapter3.notifyDataSetChanged();

if (mListener != null)

mListener.onCalendarItemClick(this, date);

}

}

return false;

}

@Override

public void onAnimationEnd(Animation animation) {

// TODO Auto-generated method stub

generateClaendarGirdView();

}

@Override

public void onAnimationRepeat(Animation animation) {

// TODO Auto-generated method stub

}

@Override

public void onAnimationStart(Animation animation) {

// TODO Auto-generated method stub

}

}

/**

* 显示week的布局adapter

*

*/

class WeekGridAdapter extends BaseAdapter {

final String[] titles = new String[] { "日", "一", "二", "三", "四", "五", "六" };

private Context mContext;

public WeekGridAdapter(Context context) {

this.mContext = context;

}

@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) {

TextView week = new TextView(mContext);

android.view.ViewGroup.LayoutParams week_params = new LayoutParams(

android.view.ViewGroup.LayoutParams.MATCH_PARENT,

android.view.ViewGroup.LayoutParams.MATCH_PARENT);

week.setLayoutParams(week_params);

week.setPadding(0, 0, 0, 0);

week.setGravity(Gravity.CENTER);

week.setFocusable(false);

week.setBackgroundColor(Color.TRANSPARENT);

if (position == 6) { // 周六

week.setBackgroundColor(Color.argb(0xff, 0x52, 0x9b, 0xd0));

week.setTextColor(Color.WHITE);

} else if (position == 0) { // 周日

week.setBackgroundColor(Color.argb(0xff, 0xbc, 0x44, 0x45));

week.setTextColor(Color.WHITE);

} else {

week.setTextColor(Color.BLACK);

}

week.setText(getItem(position) + "");

return week;

}

}

/**

* 显示日期的adapter

*/

class CalendarGridViewAdapter extends BaseAdapter {

/** 日历item中默认id从0xff0000开始 */

private final static int DEFAULT_ID = 0xff0000;

private Calendar calStartDate = Calendar.getInstance();// 当前显示的日历

private Calendar calSelected = Calendar.getInstance(); // 选择的日历

/** 标注的日期 */

private List markDates;

private Context mContext;

private Calendar calToday = Calendar.getInstance(); // 今日

private ArrayList titles;

private ArrayList getDates() {

UpdateStartDateForMonth();

ArrayList alArrayList = new ArrayList();

for (int i = 1; i <= 42; i++) {

alArrayList.add(calStartDate.getTime());

calStartDate.add(Calendar.DAY_OF_MONTH, 1);

}

return alArrayList;

}

// construct

public CalendarGridViewAdapter(Context context, Calendar cal, List dates) {

calStartDate = cal;

this.mContext = context;

titles = getDates();

this.markDates = dates;

}

public CalendarGridViewAdapter(Context context) {

this.mContext = context;

}

@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) {

// 整个Item

LinearLayout itemLayout = new LinearLayout(mContext);

itemLayout.setId(position + DEFAULT_ID);

itemLayout.setGravity(Gravity.CENTER);

itemLayout.setOrientation(1);

itemLayout.setBackgroundColor(Color.WHITE);

Date myDate = (Date) getItem(position);

itemLayout.setTag(myDate);

Calendar calCalendar = Calendar.getInstance();

calCalendar.setTime(myDate);

// 显示日期day

TextView textDay = new TextView(mContext);// 日期

LinearLayout.LayoutParams text_params = new LinearLayout.LayoutParams(

LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

textDay.setGravity(Gravity.CENTER_HORIZONTAL);

int day = myDate.getDate(); // 日期

textDay.setText(String.valueOf(day));

textDay.setId(position + DEFAULT_ID);

itemLayout.addView(textDay, text_params);

// 显示公历

TextView chineseDay = new TextView(mContext);

LinearLayout.LayoutParams chinese_params = new LinearLayout.LayoutParams(

LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

chineseDay.setGravity(Gravity.CENTER_HORIZONTAL);

chineseDay.setTextSize(9);

CalendarUtil calendarUtil = new CalendarUtil(calCalendar);

chineseDay.setText(calendarUtil.toString());

itemLayout.addView(chineseDay, chinese_params);

// 如果是当前日期则显示不同颜色

if (equalsDate(calToday.getTime(), myDate)) {

itemLayout.setBackgroundColor(Color.argb(0xff, 0x6d, 0xd6, 0x97));

}

// 这里用于比对是不是比当前日期小,如果比当前日期小则显示浅灰色

if (!CalendarUtil.compare(myDate, calToday.getTime())) {

itemLayout.setBackgroundColor(Color.argb(0xff, 0xee, 0xee, 0xee));

textDay.setTextColor(Color.argb(0xff, 0xc0, 0xc0, 0xc0));

chineseDay.setTextColor(Color.argb(0xff, 0xc0, 0xc0, 0xc0));

} else {

chineseDay.setTextColor(Color.argb(0xff, 0xc2, 0xa5, 0x3d));

chineseDay.setTextColor(Color.argb(0xff, 0x60, 0x3b, 0x07));

// 设置背景颜色

if (equalsDate(calSelected.getTime(), myDate)) {

// 选择的

itemLayout.setBackgroundColor(Color.argb(0xff, 0xdc, 0xe2, 0xff));

} else {

if (equalsDate(calToday.getTime(), myDate)) {

// 当前日期faedda

itemLayout.setBackgroundColor(Color.argb(0xff, 0xfa, 0xed, 0xda));

}

}

}

/** 设置标注日期颜色 */

if (markDates != null) {

final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);

for (Date date : markDates) {

if (format.format(myDate).equals(format.format(date))) {

itemLayout.setBackgroundColor(Color.argb(0xff, 0xd3, 0x3a, 0x3a));

break;

}

}

}

return itemLayout;

}

@Override

public void notifyDataSetChanged() {

super.notifyDataSetChanged();

}

@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;

}

}

// 根据改变的日期更新日历

// 填充日历控件用

private void UpdateStartDateForMonth() {

calStartDate.set(Calendar.DATE, 1); // 设置成当月第一天

// 星期一是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);// 周日第一位

}

public void setSelectedDate(Calendar cal) {

calSelected = cal;

}

}

/**

* 用于生成日历展示的GridView布局

*/

class CalendarGridView extends GridView {

/**

* 当前操作的上下文对象

*/

private Context mContext;

/**

* CalendarGridView 构造器

*

* @param context

* 当前操作的上下文对象

*/

public CalendarGridView(Context context) {

super(context);

mContext = context;

initGirdView();

}

/**

* 初始化gridView 控件的布局

*/

private void initGirdView() {

LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(

LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);

setLayoutParams(params);

setNumColumns(7);// 设置每行列数

setGravity(Gravity.CENTER_VERTICAL);// 位置居中

setVerticalSpacing(1);// 垂直间隔

setHorizontalSpacing(1);// 水平间隔

setBackgroundColor(Color.argb(0xff, 0xe3, 0xee, 0xf4));

int i = mContext.getResources().getDisplayMetrics().widthPixels / 7;

int j = mContext.getResources().getDisplayMetrics().widthPixels

- (i * 7);

int x = j / 2;

setPadding(x, 0, 0, 0);// 居中

}

}

/**

* 把公历时间处理成农历时间

*

*/

class CalendarUtil {

/**

* 用于保存中文的月份

*/

private final static String CHINESE_NUMBER[] = { "一", "二", "三", "四", "五",

"六", "七", "八", "九", "十", "十一", "腊" };

/**

* 用于保存展示周几使用

*/

private final static String WEEK_NUMBER[] = { "日", "一", "二", "三", "四", "五",

"六" };

private final static long[] LUNAR_INFO = new long[] { 0x04bd8, 0x04ae0,

0x0a570, 0x054d5, 0x0d260, 0x0d950, 0x16554, 0x056a0, 0x09ad0,

0x055d2, 0x04ae0, 0x0a5b6, 0x0a4d0, 0x0d250, 0x1d255, 0x0b540,

0x0d6a0, 0x0ada2, 0x095b0, 0x14977, 0x04970, 0x0a4b0, 0x0b4b5,

0x06a50, 0x06d40, 0x1ab54, 0x02b60, 0x09570, 0x052f2, 0x04970,

0x06566, 0x0d4a0, 0x0ea50, 0x06e95, 0x05ad0, 0x02b60, 0x186e3,

0x092e0, 0x1c8d7, 0x0c950, 0x0d4a0, 0x1d8a6, 0x0b550, 0x056a0,

0x1a5b4, 0x025d0, 0x092d0, 0x0d2b2, 0x0a950, 0x0b557, 0x06ca0,

0x0b550, 0x15355, 0x04da0, 0x0a5d0, 0x14573, 0x052d0, 0x0a9a8,

0x0e950, 0x06aa0, 0x0aea6, 0x0ab50, 0x04b60, 0x0aae4, 0x0a570,

0x05260, 0x0f263, 0x0d950, 0x05b57, 0x056a0, 0x096d0, 0x04dd5,

0x04ad0, 0x0a4d0, 0x0d4d4, 0x0d250, 0x0d558, 0x0b540, 0x0b5a0,

0x195a6, 0x095b0, 0x049b0, 0x0a974, 0x0a4b0, 0x0b27a, 0x06a50,

0x06d40, 0x0af46, 0x0ab60, 0x09570, 0x04af5, 0x04970, 0x064b0,

0x074a3, 0x0ea50, 0x06b58, 0x055c0, 0x0ab60, 0x096d5, 0x092e0,

0x0c960, 0x0d954, 0x0d4a0, 0x0da50, 0x07552, 0x056a0, 0x0abb7,

0x025d0, 0x092d0, 0x0cab5, 0x0a950, 0x0b4a0, 0x0baa4, 0x0ad50,

0x055d9, 0x04ba0, 0x0a5b0, 0x15176, 0x052b0, 0x0a930, 0x07954,

0x06aa0, 0x0ad50, 0x05b52, 0x04b60, 0x0a6e6, 0x0a4e0, 0x0d260,

0x0ea65, 0x0d530, 0x05aa0, 0x076a3, 0x096d0, 0x04bd7, 0x04ad0,

0x0a4d0, 0x1d0b6, 0x0d250, 0x0d520, 0x0dd45, 0x0b5a0, 0x056d0,

0x055b2, 0x049b0, 0x0a577, 0x0a4b0, 0x0aa50, 0x1b255, 0x06d20,

0x0ada0 };

/**

* 转换为2012年11月22日格式

*/

private static SimpleDateFormat chineseDateFormat = new SimpleDateFormat(

"yyyy年MM月dd日");

/**

* 转换为2012-11-22格式

*/

private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat(

"yyyy-MM-dd");

/**

* 计算得到农历的年份

*/

private int mLuchYear;

/**

* 计算得到农历的月份

*/

private int mLuchMonth;

/**

* 计算得到农历的日期

*/

private int mLuchDay;

/**

* 用于标识是事为闰年

*/

private boolean isLoap;

/**

* 用于记录当前处理的时间

*/

private Calendar mCurrenCalendar;

/**

* 传回农历 year年的总天数

*

* @param year

* 将要计算的年份

* @return 返回传入年份的总天数

*/

private static int yearDays(int year) {

int i, sum = 348;

for (i = 0x8000; i > 0x8; i >>= 1) {

if ((LUNAR_INFO[year - 1900] & i) != 0)

sum += 1;

}

return (sum + leapDays(year));

}

/**

* 传回农历 year年闰月的天数

*

* @param year

* 将要计算的年份

* @return 返回 农历 year年闰月的天数

*/

private static int leapDays(int year) {

if (leapMonth(year) != 0) {

if ((LUNAR_INFO[year - 1900] & 0x10000) != 0)

return 30;

else

return 29;

} else

return 0;

}

/**

* 传回农历 year年闰哪个月 1-12 , 没闰传回 0

*

* @param year

* 将要计算的年份

* @return 传回农历 year年闰哪个月 1-12 , 没闰传回 0

*/

private static int leapMonth(int year) {

return (int) (LUNAR_INFO[year - 1900] & 0xf);

}

/**

* 传回农历 year年month月的总天数

*

* @param year

* 将要计算的年份

* @param month

* 将要计算的月份

* @return 传回农历 year年month月的总天数

*/

private static int monthDays(int year, int month) {

if ((LUNAR_INFO[year - 1900] & (0x10000 >> month)) == 0)

return 29;

else

return 30;

}

/**

* 传回农历 y年的生肖

*

* @return 传回农历 y年的生肖

*/

public String animalsYear() {

final String[] Animals = new String[] { "鼠", "牛", "虎", "兔", "龙", "蛇",

"马", "羊", "猴", "鸡", "狗", "猪" };

return Animals[(mLuchYear - 4) % 12];

}

// ====== 传入 月日的offset 传回干支, 0=甲子

private static String cyclicalm(int num) {

final String[] Gan = new String[] { "甲", "乙", "丙", "丁", "戊", "己", "庚",

"辛", "壬", "癸" };

final String[] Zhi = new String[] { "子", "丑", "寅", "卯", "辰", "巳", "午",

"未", "申", "酉", "戌", "亥" };

return (Gan[num % 10] + Zhi[num % 12]);

}

// ====== 传入 offset 传回干支, 0=甲子

public String cyclical() {

int num = mLuchYear - 1900 + 36;

return (cyclicalm(num));

}

/**

* 传出y年m月d日对应的农历. yearCyl3:农历年与1864的相差数 ? monCyl4:从1900年1月31日以来,闰月数

* dayCyl5:与1900年1月31日相差的天数,再加40 ?

*

* @param cal

* @return

*/

public CalendarUtil(Calendar cal) {

mCurrenCalendar = cal;

int leapMonth = 0;

Date baseDate = null;

try {

baseDate = chineseDateFormat.parse("1900年1月31日");

} catch (ParseException e) {

e.printStackTrace(); // To change body of catch statement use

// Options | File Templates.

}

// 求出和1900年1月31日相差的天数

int offset = (int) ((cal.getTime().getTime() - baseDate.getTime()) / 86400000L);

// 用offset减去每农历年的天数

// 计算当天是农历第几天

// i最终结果是农历的年份

// offset是当年的第几天

int iYear, daysOfYear = 0;

for (iYear = 1900; iYear < 2050 && offset > 0; iYear++) {

daysOfYear = yearDays(iYear);

offset -= daysOfYear;

}

if (offset < 0) {

offset += daysOfYear;

iYear--;

}

// 农历年份

mLuchYear = iYear;

leapMonth = leapMonth(iYear); // 闰哪个月,1-12

isLoap = false;

// 用当年的天数offset,逐个减去每月(农历)的天数,求出当天是本月的第几天

int iMonth, daysOfMonth = 0;

for (iMonth = 1; iMonth < 13 && offset > 0; iMonth++) {

// 闰月

if (leapMonth > 0 && iMonth == (leapMonth + 1) && !isLoap) {

--iMonth;

isLoap = true;

daysOfMonth = leapDays(mLuchYear);

} else

daysOfMonth = monthDays(mLuchYear, iMonth);

offset -= daysOfMonth;

// 解除闰月

if (isLoap && iMonth == (leapMonth + 1))

isLoap = false;

if (!isLoap) {

}

}

// offset为0时,并且刚才计算的月份是闰月,要校正

if (offset == 0 && leapMonth > 0 && iMonth == leapMonth + 1) {

if (isLoap) {

isLoap = false;

} else {

isLoap = true;

--iMonth;

}

}

// offset小于0时,也要校正

if (offset < 0) {

offset += daysOfMonth;

--iMonth;

}

mLuchMonth = iMonth;

mLuchDay = offset + 1;

}

/**

* 返化成中文格式

*

* @param day

* @return

*/

public static String getChinaDayString(int day) {

String chineseTen[] = { "初", "十", "廿", "卅" };

int n = day % 10 == 0 ? 9 : day % 10 - 1;

if (day > 30)

return "";

if (day == 10)

return "初十";

else

return chineseTen[day / 10] + CHINESE_NUMBER[n];

}

/**

* 用于显示农历的初几这种格式

*

* @return 农历的日期

*/

public String toString() {

String message = "";

// int n = mLuchDay % 10 == 0 ? 9 : mLuchDay % 10 - 1;

message = getChinaCalendarMsg(mLuchYear, mLuchMonth, mLuchDay);

if (StringUtil.isNullOrEmpty(message)) {

String solarMsg = new SolarTermsUtil(mCurrenCalendar)

.getSolartermsMsg();

// 判断当前日期是否为节气

if (!StringUtil.isNullOrEmpty(solarMsg)) {

message = solarMsg;

} else {

/**

* 判断当前日期是否为公历节日

*/

String gremessage = new GregorianUtil(mCurrenCalendar)

.getGremessage();

if (!StringUtil.isNullOrEmpty(gremessage)) {

message = gremessage;

} else if (mLuchDay == 1) {

message = CHINESE_NUMBER[mLuchMonth - 1] + "月";

} else {

message = getChinaDayString(mLuchDay);

}

}

}

return message;

}

/**

* 返回农历的年月日

*

* @return 农历的年月日格式

*/

public String getDay() {

return (isLoap ? "闰" : "") + CHINESE_NUMBER[mLuchMonth - 1] + "月"

+ getChinaDayString(mLuchDay);

}

/**

* 把calendar转化为当前年月日

*

* @param calendar

* Calendar

* @return 返回成转换好的 年月日格式

*/

public static String getDay(Calendar calendar) {

return simpleDateFormat.format(calendar.getTime());

}

/**

* 用于比对二个日期的大小

*

* @param compareDate

* 将要比对的时间

* @param currentDate

* 当前时间

* @return true 表示大于当前时间 false 表示小于当前时间

*/

public static boolean compare(Date compareDate, Date currentDate) {

return chineseDateFormat.format(compareDate).compareTo(

chineseDateFormat.format(currentDate)) >= 0;

}

/**

* 获取当前周几

*

* @param calendar

* @return

*/

public static String getWeek(Calendar calendar) {

return "周" + WEEK_NUMBER[calendar.get(Calendar.DAY_OF_WEEK) - 1] + "";

}

/**

* 将当前时间转换成要展示的形式

*

* @param calendar

* @return

*/

public static String getCurrentDay(Calendar calendar) {

return getDay(calendar) + " 农历" + new CalendarUtil(calendar).getDay()

+ " " + getWeek(calendar);

}

/**

* 用于获取中国的传统节日

*

* @param month

* 农历的月

* @param day

* 农历日

* @return 中国传统节日

*/

private String getChinaCalendarMsg(int year, int month, int day) {

String message = "";

if (((month) == 1) && day == 1) {

message = "春节";

} else if (((month) == 1) && day == 15) {

message = "元宵";

} else if (((month) == 5) && day == 5) {

message = "端午";

} else if ((month == 7) && day == 7) {

message = "七夕";

} else if (((month) == 8) && day == 15) {

message = "中秋";

} else if ((month == 9) && day == 9) {

message = "重阳";

} else if ((month == 12) && day == 8) {

message = "腊八";

} else {

if (month == 12) {

if ((((monthDays(year, month) == 29) && day == 29))

|| ((((monthDays(year, month) == 30) && day == 30)))) {

message = "除夕";

}

}

}

return message;

}

}

/**

* 字符串的处理类

*/

class StringUtil {

/**

* 判断是否为null或空值

*

* @param str

* String

* @return true or false

*/

public static boolean isNullOrEmpty(String str) {

return str == null || str.trim().length() == 0;

}

/**

* 判断str1和str2是否相同

*

* @param str1

* str1

* @param str2

* str2

* @return true or false

*/

public static boolean equals(String str1, String str2) {

return str1 == str2 || str1 != null && str1.equals(str2);

}

/**

* 判断str1和str2是否相同(不区分大小写)

*

* @param str1

* str1

* @param str2

* str2

* @return true or false

*/

public static boolean equalsIgnoreCase(String str1, String str2) {

return str1 != null && str1.equalsIgnoreCase(str2);

}

/**

* 判断字符串str1是否包含字符串str2

*

* @param str1

* 源字符串

* @param str2

* 指定字符串

* @return true源字符串包含指定字符串,false源字符串不包含指定字符串

*/

public static boolean contains(String str1, String str2) {

return str1 != null && str1.contains(str2);

}

/**

* 判断字符串是否为空,为空则返回一个空值,不为空则返回原字符串

*

* @param str

* 待判断字符串

* @return 判断后的字符串

*/

public static String getString(String str) {

return str == null ? "" : str;

}

}

/**

* 主要用于把公历日期处理成24节气

*/

class SolarTermsUtil {

/**

* 计算得到公历的年份

*/

private int gregorianYear;

/**

* 计算得到公历的月份

*/

private int gregorianMonth;

/**

* 用于计算得到公历的日期

*/

private int gregorianDate;

private int chineseYear;

private int chineseMonth;

private int chineseDate;

// 初始日,公历农历对应日期:

// 公历 1901 年 1 月 1 日,对应农历 4598 年 11 月 11 日

private static int baseYear = 1901;

private static int baseMonth = 1;

private static int baseDate = 1;

private static int baseIndex = 0;

private static int baseChineseYear = 4598 - 1;

private static int baseChineseMonth = 11;

private static int baseChineseDate = 11;

private static char[] daysInGregorianMonth = { 31, 28, 31, 30, 31, 30, 31,

31, 30, 31, 30, 31 };

private int sectionalTerm;

private int principleTerm;

private static char[][] sectionalTermMap = {

{ 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 5, 5,

5, 5, 5, 4, 5, 5 },

{ 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 3,

3, 4, 4, 3, 3, 3 },

{ 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5,

5, 5, 4, 5, 5, 5, 5 },

{ 5, 5, 6, 6, 5, 5, 5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 4, 4, 5, 5, 4, 4,

4, 5, 4, 4, 4, 4, 5 },

{ 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5, 5, 6, 5, 5,

5, 5, 4, 5, 5, 5, 5 },

{ 6, 6, 7, 7, 6, 6, 6, 7, 6, 6, 6, 6, 5, 6, 6, 6, 5, 5, 6, 6, 5, 5,

5, 6, 5, 5, 5, 5, 4, 5, 5, 5, 5 },

{ 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6,

7, 7, 6, 6, 6, 7, 7 },

{ 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7,

7, 7, 6, 7, 7, 7, 6, 6, 7, 7, 7 },

{ 8, 8, 8, 9, 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7,

7, 7, 6, 7, 7, 7, 7 },

{ 9, 9, 9, 9, 8, 9, 9, 9, 8, 8, 9, 9, 8, 8, 8, 9, 8, 8, 8, 8, 7, 8,

8, 8, 7, 7, 8, 8, 8 },

{ 8, 8, 8, 8, 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7,

7, 7, 6, 6, 7, 7, 7 },

{ 7, 8, 8, 8, 7, 7, 8, 8, 7, 7, 7, 8, 7, 7, 7, 7, 6, 7, 7, 7, 6, 6,

7, 7, 6, 6, 6, 7, 7 } };

private static char[][] sectionalTermYear = {

{ 13, 49, 85, 117, 149, 185, 201, 250, 250 },

{ 13, 45, 81, 117, 149, 185, 201, 250, 250 },

{ 13, 48, 84, 112, 148, 184, 200, 201, 250 },

{ 13, 45, 76, 108, 140, 172, 200, 201, 250 },

{ 13, 44, 72, 104, 132, 168, 200, 201, 250 },

{ 5, 33, 68, 96, 124, 152, 188, 200, 201 },

{ 29, 57, 85, 120, 148, 176, 200, 201, 250 },

{ 13, 48, 76, 104, 132, 168, 196, 200, 201 },

{ 25, 60, 88, 120, 148, 184, 200, 201, 250 },

{ 16, 44, 76, 108, 144, 172, 200, 201, 250 },

{ 28, 60, 92, 124, 160, 192, 200, 201, 250 },

{ 17, 53, 85, 124, 156, 188, 200, 201, 250 } };

private static char[][] principleTermMap = {

{ 21, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20,

20, 20, 20, 20, 20, 19, 20, 20, 20, 19, 19, 20 },

{ 20, 19, 19, 20, 20, 19, 19, 19, 19, 19, 19, 19, 19, 18, 19, 19,

19, 18, 18, 19, 19, 18, 18, 18, 18, 18, 18, 18 },

{ 21, 21, 21, 22, 21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21,

20, 20, 20, 21, 20, 20, 20, 20, 19, 20, 20, 20, 20 },

{ 20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 20, 20, 20, 20,

19, 20, 20, 20, 19, 19, 20, 20, 19, 19, 19, 20, 20 },

{ 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21,

20, 21, 21, 21, 20, 20, 21, 21, 20, 20, 20, 21, 21 },

{ 22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 21, 21, 21, 22,

21, 21, 21, 21, 20, 21, 21, 21, 20, 20, 21, 21, 21 },

{ 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23, 22, 23, 23, 23,

22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 23 },

{ 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23,

22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23 },

{ 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24, 23, 23, 23, 23,

22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23, 23 },

{ 24, 24, 24, 24, 23, 24, 24, 24, 23, 23, 24, 24, 23, 23, 23, 24,

23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 23 },

{ 23, 23, 23, 23, 22, 23, 23, 23, 22, 22, 23, 23, 22, 22, 22, 23,

22, 22, 22, 22, 21, 22, 22, 22, 21, 21, 22, 22, 22 },

{ 22, 22, 23, 23, 22, 22, 22, 23, 22, 22, 22, 22, 21, 22, 22, 22,

21, 21, 22, 22, 21, 21, 21, 22, 21, 21, 21, 21, 22 } };

private static char[][] principleTermYear = {

{ 13, 45, 81, 113, 149, 185, 201 },

{ 21, 57, 93, 125, 161, 193, 201 },

{ 21, 56, 88, 120, 152, 188, 200, 201 },

{ 21, 49, 81, 116, 144, 176, 200, 201 },

{ 17, 49, 77, 112, 140, 168, 200, 201 },

{ 28, 60, 88, 116, 148, 180, 200, 201 },

{ 25, 53, 84, 112, 144, 172, 200, 201 },

{ 29, 57, 89, 120, 148, 180, 200, 201 },

{ 17, 45, 73, 108, 140, 168, 200, 201 },

{ 28, 60, 92, 124, 160, 192, 200, 201 },

{ 16, 44, 80, 112, 148, 180, 200, 201 },

{ 17, 53, 88, 120, 156, 188, 200, 201 } };

private static char[] chineseMonths = {

// 农历月份大小压缩表,两个字节表示一年。两个字节共十六个二进制位数,

// 前四个位数表示闰月月份,后十二个位数表示十二个农历月份的大小。

0x00, 0x04, 0xad, 0x08, 0x5a, 0x01, 0xd5, 0x54, 0xb4, 0x09, 0x64,

0x05, 0x59, 0x45, 0x95, 0x0a, 0xa6, 0x04, 0x55, 0x24, 0xad, 0x08,

0x5a, 0x62, 0xda, 0x04, 0xb4, 0x05, 0xb4, 0x55, 0x52, 0x0d, 0x94,

0x0a, 0x4a, 0x2a, 0x56, 0x02, 0x6d, 0x71, 0x6d, 0x01, 0xda, 0x02,

0xd2, 0x52, 0xa9, 0x05, 0x49, 0x0d, 0x2a, 0x45, 0x2b, 0x09, 0x56,

0x01, 0xb5, 0x20, 0x6d, 0x01, 0x59, 0x69, 0xd4, 0x0a, 0xa8, 0x05,

0xa9, 0x56, 0xa5, 0x04, 0x2b, 0x09, 0x9e, 0x38, 0xb6, 0x08, 0xec,

0x74, 0x6c, 0x05, 0xd4, 0x0a, 0xe4, 0x6a, 0x52, 0x05, 0x95, 0x0a,

0x5a, 0x42, 0x5b, 0x04, 0xb6, 0x04, 0xb4, 0x22, 0x6a, 0x05, 0x52,

0x75, 0xc9, 0x0a, 0x52, 0x05, 0x35, 0x55, 0x4d, 0x0a, 0x5a, 0x02,

0x5d, 0x31, 0xb5, 0x02, 0x6a, 0x8a, 0x68, 0x05, 0xa9, 0x0a, 0x8a,

0x6a, 0x2a, 0x05, 0x2d, 0x09, 0xaa, 0x48, 0x5a, 0x01, 0xb5, 0x09,

0xb0, 0x39, 0x64, 0x05, 0x25, 0x75, 0x95, 0x0a, 0x96, 0x04, 0x4d,

0x54, 0xad, 0x04, 0xda, 0x04, 0xd4, 0x44, 0xb4, 0x05, 0x54, 0x85,

0x52, 0x0d, 0x92, 0x0a, 0x56, 0x6a, 0x56, 0x02, 0x6d, 0x02, 0x6a,

0x41, 0xda, 0x02, 0xb2, 0xa1, 0xa9, 0x05, 0x49, 0x0d, 0x0a, 0x6d,

0x2a, 0x09, 0x56, 0x01, 0xad, 0x50, 0x6d, 0x01, 0xd9, 0x02, 0xd1,

0x3a, 0xa8, 0x05, 0x29, 0x85, 0xa5, 0x0c, 0x2a, 0x09, 0x96, 0x54,

0xb6, 0x08, 0x6c, 0x09, 0x64, 0x45, 0xd4, 0x0a, 0xa4, 0x05, 0x51,

0x25, 0x95, 0x0a, 0x2a, 0x72, 0x5b, 0x04, 0xb6, 0x04, 0xac, 0x52,

0x6a, 0x05, 0xd2, 0x0a, 0xa2, 0x4a, 0x4a, 0x05, 0x55, 0x94, 0x2d,

0x0a, 0x5a, 0x02, 0x75, 0x61, 0xb5, 0x02, 0x6a, 0x03, 0x61, 0x45,

0xa9, 0x0a, 0x4a, 0x05, 0x25, 0x25, 0x2d, 0x09, 0x9a, 0x68, 0xda,

0x08, 0xb4, 0x09, 0xa8, 0x59, 0x54, 0x03, 0xa5, 0x0a, 0x91, 0x3a,

0x96, 0x04, 0xad, 0xb0, 0xad, 0x04, 0xda, 0x04, 0xf4, 0x62, 0xb4,

0x05, 0x54, 0x0b, 0x44, 0x5d, 0x52, 0x0a, 0x95, 0x04, 0x55, 0x22,

0x6d, 0x02, 0x5a, 0x71, 0xda, 0x02, 0xaa, 0x05, 0xb2, 0x55, 0x49,

0x0b, 0x4a, 0x0a, 0x2d, 0x39, 0x36, 0x01, 0x6d, 0x80, 0x6d, 0x01,

0xd9, 0x02, 0xe9, 0x6a, 0xa8, 0x05, 0x29, 0x0b, 0x9a, 0x4c, 0xaa,

0x08, 0xb6, 0x08, 0xb4, 0x38, 0x6c, 0x09, 0x54, 0x75, 0xd4, 0x0a,

0xa4, 0x05, 0x45, 0x55, 0x95, 0x0a, 0x9a, 0x04, 0x55, 0x44, 0xb5,

0x04, 0x6a, 0x82, 0x6a, 0x05, 0xd2, 0x0a, 0x92, 0x6a, 0x4a, 0x05,

0x55, 0x0a, 0x2a, 0x4a, 0x5a, 0x02, 0xb5, 0x02, 0xb2, 0x31, 0x69,

0x03, 0x31, 0x73, 0xa9, 0x0a, 0x4a, 0x05, 0x2d, 0x55, 0x2d, 0x09,

0x5a, 0x01, 0xd5, 0x48, 0xb4, 0x09, 0x68, 0x89, 0x54, 0x0b, 0xa4,

0x0a, 0xa5, 0x6a, 0x95, 0x04, 0xad, 0x08, 0x6a, 0x44, 0xda, 0x04,

0x74, 0x05, 0xb0, 0x25, 0x54, 0x03 };

/**

* 用于保存24节气

*/

private static String[] principleTermNames = { "大寒", "雨水", "春分", "谷雨",

"小满", "夏至", "大暑", "处暑", "秋分", "霜降", "小雪", "冬至" };

/**

* 用于保存24节气

*/

private static String[] sectionalTermNames = { "小寒", "立春", "惊蛰", "清明",

"立夏", "芒种", "小暑", "立秋", "白露", "寒露", "立冬", "大雪" };

public SolarTermsUtil(Calendar calendar) {

gregorianYear = calendar.get(Calendar.YEAR);

gregorianMonth = calendar.get(Calendar.MONTH) + 1;

gregorianDate = calendar.get(Calendar.DATE);

computeChineseFields();

computeSolarTerms();

}

public int computeChineseFields() {

if (gregorianYear < 1901 || gregorianYear > 2100)

return 1;

int startYear = baseYear;

int startMonth = baseMonth;

int startDate = baseDate;

chineseYear = baseChineseYear;

chineseMonth = baseChineseMonth;

chineseDate = baseChineseDate;

// 第二个对应日,用以提高计算效率

// 公历 2000 年 1 月 1 日,对应农历 4697 年 11 月 25 日

if (gregorianYear >= 2000) {

startYear = baseYear + 99;

startMonth = 1;

startDate = 1;

chineseYear = baseChineseYear + 99;

chineseMonth = 11;

chineseDate = 25;

}

int daysDiff = 0;

for (int i = startYear; i < gregorianYear; i++) {

daysDiff += 365;

if (isGregorianLeapYear(i))

daysDiff += 1; // leap year

}

for (int i = startMonth; i < gregorianMonth; i++) {

daysDiff += daysInGregorianMonth(gregorianYear, i);

}

daysDiff += gregorianDate - startDate;

chineseDate += daysDiff;

int lastDate = daysInChineseMonth(chineseYear, chineseMonth);

int nextMonth = nextChineseMonth(chineseYear, chineseMonth);

while (chineseDate > lastDate) {

if (Math.abs(nextMonth) < Math.abs(chineseMonth))

chineseYear++;

chineseMonth = nextMonth;

chineseDate -= lastDate;

lastDate = daysInChineseMonth(chineseYear, chineseMonth);

nextMonth = nextChineseMonth(chineseYear, chineseMonth);

}

return 0;

}

public int computeSolarTerms() {

if (gregorianYear < 1901 || gregorianYear > 2100)

return 1;

sectionalTerm = sectionalTerm(gregorianYear, gregorianMonth);

principleTerm = principleTerm(gregorianYear, gregorianMonth);

return 0;

}

public static int sectionalTerm(int y, int m) {

if (y < 1901 || y > 2100)

return 0;

int index = 0;

int ry = y - baseYear + 1;

while (ry >= sectionalTermYear[m - 1][index])

index++;

int term = sectionalTermMap[m - 1][4 * index + ry % 4];

if ((ry == 121) && (m == 4))

term = 5;

if ((ry == 132) && (m == 4))

term = 5;

if ((ry == 194) && (m == 6))

term = 6;

return term;

}

public static int principleTerm(int y, int m) {

if (y < 1901 || y > 2100)

return 0;

int index = 0;

int ry = y - baseYear + 1;

while (ry >= principleTermYear[m - 1][index])

index++;

int term = principleTermMap[m - 1][4 * index + ry % 4];

if ((ry == 171) && (m == 3))

term = 21;

if ((ry == 181) && (m == 5))

term = 21;

return term;

}

/**

* 用于判断输入的年份是否为闰年

*

* @param year

* 输入的年份

* @return true 表示闰年

*/

public static boolean isGregorianLeapYear(int year) {

boolean isLeap = false;

if (year % 4 == 0)

isLeap = true;

if (year % 100 == 0)

isLeap = false;

if (year % 400 == 0)

isLeap = true;

return isLeap;

}

public static int daysInGregorianMonth(int y, int m) {

int d = daysInGregorianMonth[m - 1];

if (m == 2 && isGregorianLeapYear(y))

d++; // 公历闰年二月多一天

return d;

}

public static int daysInChineseMonth(int y, int m) {

// 注意:闰月 m < 0

int index = y - baseChineseYear + baseIndex;

int v = 0;

int l = 0;

int d = 30;

if (1 <= m && m <= 8) {

v = chineseMonths[2 * index];

l = m - 1;

if (((v >> l) & 0x01) == 1)

d = 29;

} else if (9 <= m && m <= 12) {

v = chineseMonths[2 * index + 1];

l = m - 9;

if (((v >> l) & 0x01) == 1)

d = 29;

} else {

v = chineseMonths[2 * index + 1];

v = (v >> 4) & 0x0F;

if (v != Math.abs(m)) {

d = 0;

} else {

d = 29;

for (int i = 0; i < bigLeapMonthYears.length; i++) {

if (bigLeapMonthYears[i] == index) {

d = 30;

break;

}

}

}

}

return d;

}

public static int nextChineseMonth(int y, int m) {

int n = Math.abs(m) + 1;

if (m > 0) {

int index = y - baseChineseYear + baseIndex;

int v = chineseMonths[2 * index + 1];

v = (v >> 4) & 0x0F;

if (v == m)

n = -m;

}

if (n == 13)

n = 1;

return n;

}

// 大闰月的闰年年份

private static int[] bigLeapMonthYears = { 6, 14, 19, 25, 33, 36, 38, 41,

44, 52, 55, 79, 117, 136, 147, 150, 155, 158, 185, 193 };

/**

* 用于获取24节气的值

*

* @return 24节气的值

*/

public String getSolartermsMsg() {

String str = "";

String gm = String.valueOf(gregorianMonth);

if (gm.length() == 1)

gm = ' ' + gm;

String cm = String.valueOf(Math.abs(chineseMonth));

if (cm.length() == 1)

cm = ' ' + cm;

String gd = String.valueOf(gregorianDate);

if (gd.length() == 1)

gd = ' ' + gd;

String cd = String.valueOf(chineseDate);

if (cd.length() == 1)

cd = ' ' + cd;

if (gregorianDate == sectionalTerm) {

str = " " + sectionalTermNames[gregorianMonth - 1];

} else if (gregorianDate == principleTerm) {

str = " " + principleTermNames[gregorianMonth - 1];

}

return str;

}

}

/**

* 对公历日期的处理类

*/

class GregorianUtil {

private final static String[][] GRE_FESTVIAL = {

// 一月

{ "元旦", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },

// 二月

{ "", "", "", "", "", "", "", "", "", "", "", "", "", "情人", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "" },

// 三月

{ "", "", "", "", "", "", "", "妇女", "", "", "", "植树", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",

"" },

// 四月

{ "愚人", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },

// 五月

{ "劳动", "", "", "青年", "", "", "", "", "", "", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "",

"" },

// 六月

{ "儿童", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },

// 七月

{ "建党", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },

// 八月

{ "建军", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },

// 九月

{ "", "", "", "", "", "", "", "", "", "教师", "", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },

// 十月

{ "国庆", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },

// 十一月

{ "", "", "", "", "", "", "", "", "", "", "光棍", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "", "", "", "", "", "" },

// 十二月

{ "艾滋病", "", "", "", "", "", "", "", "", "", "", "", "", "", "",

"", "", "", "", "", "", "", "", "", "圣诞", "", "", "", "",

"", "" }, };

private int mMonth;

private int mDay;

public GregorianUtil(Calendar calendar) {

mMonth = calendar.get(Calendar.MONTH);

mDay = calendar.get(Calendar.DATE);

}

public String getGremessage() {

return GRE_FESTVIAL[mMonth][mDay - 1];

}

}

class NumberHelper {

public static String LeftPad_Tow_Zero(int str) {

java.text.DecimalFormat format = new java.text.DecimalFormat("00");

return format.format(str);

}

}

/*****************将代码拷贝到一个文件中(end)***********************/

//辅助类

package cc.util.android.view;

import android.content.Context;

import android.content.res.Resources;

import android.view.View;

import android.view.ViewGroup;

import android.view.ViewGroup.MarginLayoutParams;

import android.widget.AbsListView;

import android.widget.GridView;

import android.widget.ListAdapter;

import android.widget.ListView;

/**

* @author wangcccong

* @version 1.140122

* create at:2014-02-26

*/

public class ViewUtil {

/**

* 获取屏幕的宽度

* @param context

* @return

*/

public int getScreenWidth(Context context) {

Resources res = context.getResources();

return res.getDisplayMetrics().widthPixels;

}

/**

* 获取屏幕高度

* @param context

* @return

*/

public int getScreenHeight(Context context) {

Resources res = context.getResources();

return res.getDisplayMetrics().heightPixels;

}

/**

* 描述:根据分辨率获得字体大小.

*

* @param screenWidth the screen width

* @param screenHeight the screen height

* @param textSize the text size

* @return the int

*/

public static int resizeTextSize(int screenWidth,int screenHeight,int textSize){

float ratio = 1;

try {

float ratioWidth = (float)screenWidth / 480;

float ratioHeight = (float)screenHeight / 800;

ratio = Math.min(ratioWidth, ratioHeight);

} catch (Exception e) {

}

return Math.round(textSize * ratio);

}

/**

*

* 描述:dip转换为px

* @param context

* @param dipValue

* @return

* @throws

*/

public static int dip2px(Context context, float dipValue) {

final float scale = context.getResources().getDisplayMetrics().density;

return Math.round(dipValue * scale);

}

/**

*

* 描述:px转换为dip

* @param context

* @param pxValue

* @return

* @throws

*/

public static int px2dip(Context context, float pxValue) {

final float scale = context.getResources().getDisplayMetrics().density;

return Math.round(pxValue / scale);

}

/**

*

* 描述:px转换为sp

* @param context

* @param pxValue

* @return

* @throws

*/

public static int px2sp(Context context, float pxValue) {

final float scale = context.getResources().getDisplayMetrics().scaledDensity;

return Math.round(pxValue / scale);

}

/**

*

* 描述:sp转换为px

* @param context

* @param spValue

* @return

* @throws

*/

public static int sp2px(Context context, float spValue) {

final float scale = context.getResources().getDisplayMetrics().scaledDensity;

return Math.round(spValue * scale);

}

}

//使用方法

//在xml中添加控件

android:id="@+id/calendar"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:background="@color/white"/>

//在代码中

CalendarView calendarView = (CalendarView) findViewById(R.id.calendar);

//设置标注日期

List markDates = new ArrayList();

markDates.add(new Date());

calendarView.setMarkDates(markDates);

//设置点击操作

calendarView.setOnCalendarViewListener(new OnCalendarViewListener() {

@Override

public void onCalendarItemClick(CalendarView view, Date date) {

// TODO Auto-generated method stub

final SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日", Locale.CHINA);

Toast.makeText(MainActivity.this, format.format(date), Toast.LENGTH_SHORT).show();

}

});

所需图片:

以上所述就是本文的全部内容了,希望大家能够喜欢。

Android中自定义农历日历,Android实现自定义日历相关推荐

  1. android中edittext设置密码格式,Android 自定义EditText(带清理、密码可见、不可见)...

    实际开发中经常会遇到输入框,各种不同的需求,在一般情况下,清除内容,以及密码可见与不可见基本很常见,那么不废话直接上代码! 在res\values\attrs.xml中 .java import an ...

  2. 【译】Android中的安全数据— Android中的加密(第2部分)

    目录 锁屏 选择一个钥匙 密钥存储 密钥生成 密钥管理 加密与解密 使用范例 下一步是什么 安全提示 锁屏 如果要保护数据,请保护设备. 为了更加安全,在提供对任何应用程序功能的访问权限之前,我们可以 ...

  3. 【译】Android中的安全数据— Android中的加密(第1部分)

    目录 Java密码体系结构 Android Key Store 样例项目 下一步是什么 安全提示 Java密码体系结构 Android建立在Java密码体系结构(JCA)的基础上,该体系结构提供了用于 ...

  4. android中私有方法 继承,Android项目实战系列—基于博学谷(五)个人资料

    由于这个模块内容较多,篇幅较长,请耐心阅读. 个人资料模块分为两个部分 [x] [个人资料]() [x] [资料修改]() 一.个人资料 1.个人资料界面 (1).创建个人资料界面 在com.buxu ...

  5. android中录音断点播放,Android实现暂停--继续录音(AudioRecord)

    Android提供了两个API用于录音的实现:MediaRecorder 和 AudioRecord,各有优劣. 1.MediaRecorder 已经集成了录音.编码.压缩等,支持少量的录音音频格式, ...

  6. android中的progressbar,解析android中ProgressBar的用法

    范例说明Android的Widget,有许多是为了与User交互而特别设计的,但也有部分是作为程序提示.显示程序运行状态的Widget.现在介绍的范例,与前一章介绍过的ProgressDialog对话 ...

  7. android中的广播大全,android中的广播

    1系统广播(关闭,锁并,声音,电话,信号,等系统提供的广播)(例如信号) 广播一般是在一个类中直接写出来而不用这样单独写出到一个类中,这样方便在监听到结果时处理数据 import android.co ...

  8. android中开启wifi,打开android系统设置,连接wifi

    打开android系统设置,连接wifi wifi信号强度:得到的值是一个0到-100的区间值,是一个int型数据,其中0到-50表示信号最好,-50到-70表示信号偏差,小于-70表示最差,有可能连 ...

  9. android中怎么网络判断,Android中判断网络是否连接实例详解

    Android中判断网络是否连接实例详解 在android中,如何监测网络的状态呢,这个有的时候也是十分重要的,方法如下: public class ConnectionDetector { priv ...

  10. android中自适应布局教程,Android自适应布局设计技巧

    由于目前在做的一款app需要适配手机和平板,所以我在研究怎么构建可适应所有屏幕尺寸的布局方法. 在web的自适应布局上我有很多经验,比如使用网格流,CSS3中的media queries属性等等,这些 ...

最新文章

  1. 综述 | 语言分析技术在社会计算中的应用
  2. SAP RETAIL WB02 为门店激活物料分类账报错 - Distribution chain NMI1 00 not valid for retail price determination -
  3. 删除input框type=number时,默认的上下小箭头
  4. Unity UI和引用的管理中心
  5. (转载)Hadoop2.7.1配置
  6. 虚拟机(VMware Workstation Pro)安装多台Linux
  7. 【研发管理】结构化流程框架
  8. 四十五、Stata检验方法,回归分析与生存分析
  9. VTK:相互作用之MouseEvents
  10. 【Python面试】谈谈对 Python 和其他语言的区别?​
  11. 最火的抓包工具winpcap使用教程
  12. use 在php 用法中的总结
  13. 内衬纸缺陷在线检测系统
  14. 2020,新年快乐!
  15. 电脑主板线路连接图解_机箱线怎么接主板 DIY电脑机箱跳线与主板连接图解(2)...
  16. oracle导出数据库dmp文件
  17. ospfdr选举规则_OSPF的DR选举
  18. for循环与range方法
  19. 大作业系列之体育课 | 从NBA中看篮球精神
  20. cie规定的标准光源_标准光源介绍

热门文章

  1. JQuery插件库和17素材——免费下载
  2. 统计学 |辛普森悖论
  3. lay-ui里修改表格自动换行
  4. 腾讯云弹性微服务TEM
  5. 菜哥学知识图谱(通过“基于医疗知识图谱的问答系统”)(三)(代码分析)
  6. MAtlab wavefront,这是张小飞的阵列信号的全部MATLAB代码 传统的高分辨波达方向(DOA)估计算法中 - 下载 - 搜珍网...
  7. win7怎样在线升级到win10 win7直接升级win10详细教程
  8. Dell笔记本电脑如何升级win10、如何恢复原装win8.1
  9. 自动化办公--通过BOM表输出原材料状态(第一版)
  10. 移动数字化平台原来可以这样帮企业打造协同生态链