package com.haihang.android.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;
public class AutoFitGridView extends GridView {
public AutoFitGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public AutoFitGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AutoFitGridView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}
自定义的gridview
package com.haihang.android.view;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.haihang.android.R;
import com.haihang.android.util.CalendarUtils;
import com.haihang.android.util.Utils;
public class MonthView extends LinearLayout {
private int year;
private int month;
private int day;
private AutoFitGridView gridview;
private TextView month_tv;
private List<Integer> postions;
private LayoutInflater layoutInflater;
// 当前日期
private Date date;
private SimpleDateFormat format;
private int selectDay1;
private int selectCount;
private int unEnableDay;
private int unEnableCount;
private MonthAdapter adapter;
private static final int FONT_SIZE = 12;
private int normalFontSize;
private int smallFontSize;
private OnSelectDateChangeListener onSelectDateChangeListener;
/**
*
* @param year
* @param month
* @param day
* @param count
* 从此日期开始选中几个,0为选中当前的一个
*/
public void setSelectDate(int day, int count) {
this.selectDay1 = day;
this.selectCount = count;
adapter.notifyDataSetChanged();
}
public MonthView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MonthView(Context context) {
super(context);
}
private void init(Context context) {
layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
postions = new ArrayList<Integer>();
normalFontSize = (int) Utils.dpToPixel(getContext(), FONT_SIZE + 4);
smallFontSize = (int) Utils.dpToPixel(getContext(), FONT_SIZE);
date = new Date(System.currentTimeMillis());
format = new SimpleDateFormat("yyyy-MM-dd");
format.format(date);
layoutInflater.inflate(R.layout.month_view, this);
this.gridview = (AutoFitGridView) findViewById(R.id.gridview);
this.month_tv = (TextView) findViewById(R.id.date_label_tv);
this.gridview.setOnItemClickListener(onItemClickListener);
}
public void setDate(int year, int month) {
this.year = year;
this.month = month;
calDatePostion();
}
private void calDatePostion() {
Context context = getContext();
this.month_tv.setText(this.year + context.getString(R.string.year)
+ this.month + context.getString(R.string.month));
GregorianCalendar gCalendar = new GregorianCalendar(this.year,
month - 1, 1);
int fillDataCount = gCalendar.get(Calendar.DAY_OF_WEEK);
for (int i = 1; i < fillDataCount; ++i) {
postions.add(0);
}
for (int i = 1; i < 33; ++i) {
if (gCalendar.get(Calendar.MONTH) != month - 1) {
int count = postions.size();
int yu = count % 7;
if (yu > 0) {
fillDataCount = 7 - yu;
for (int j = 0; j < fillDataCount; ++j) {
postions.add(0);
}
}
break;
}
postions.add(i);
gCalendar.add(Calendar.DAY_OF_YEAR, 1);
}
adapter = new MonthAdapter(context, postions);
this.gridview.setAdapter(adapter);
}
public int getYear() {
return this.year;
}
public int getMonth() {
return this.month;
}
public int getDay() {
return this.day;
}
private class MonthAdapter extends BaseAdapter {
private List<Integer> poses;
public MonthAdapter(Context context, List<Integer> poses) {
this.poses = poses;
}
public int getCount() {
return poses.size();
}
public Object getItem(int arg0) {
return null;
}
public long getItemId(int arg0) {
return 0;
}
public View getView(int arg0, View arg1, ViewGroup arg2) {
TextView textview = null;
if (arg1 == null) {
textview = (TextView) layoutInflater.inflate(
R.layout.month_item, null);
arg1 = textview;
arg1.setTag(textview);
} else {
textview = (TextView) arg1.getTag();
}
// 列表的高度都为40dip
textview.setLayoutParams(new GridView.LayoutParams(
GridView.LayoutParams.FILL_PARENT, (int) Utils.dpToPixel(
getContext(), 40)));
int num = poses.get(arg0);
int color;
String str = parsedText(num);
int orange = getContext().getResources().getColor(R.color.orange);
if (isValid(num)) {
color = Color.BLACK;
if (isSelect(num)) {
textview.setBackgroundColor(orange);
} else {
textview.setBackgroundColor(Color.WHITE);
}
if (str.matches("^[\\u4e00-\\u9fa5]+$")) {
color = orange;
textview.setTextSize(smallFontSize);
} else {
color = Color.BLACK;
textview.setTextSize(normalFontSize);
}
if (isToday(num)) {
color = Color.BLUE;
textview.setTextSize(normalFontSize);
textview.setText(getContext().getString(R.string.today));
}
} else {
color = Color.GRAY;
textview.setTextSize(normalFontSize);
textview.setBackgroundColor(Color.WHITE);
}
textview.setTextColor(color);
textview.setText(0 == num ? "" : str);
return arg1;
}
@Override
public boolean isEnabled(int position) {
return isValid(poses.get(position));
}
}
private String parsedText(int num) {
if(num == 14) {
int i = 1;
i++;
}
long[] chinaCalendar = CalendarUtils.calElement(this.year, this.month,
num);
Context context = getContext();
if (this.month == 1 && num == 1) {
return context.getString(R.string.yuandan);
} else if (chinaCalendar[1] == 1 && chinaCalendar[2] == 15) {
return context.getString(R.string.yuanxiao);
} else if (chinaCalendar[1] == 1 && chinaCalendar[2] == 1) {
return context.getString(R.string.chunjie);
} else if (this.month == 5 && num == 1) {
return context.getString(R.string.wuyi);
} else if (this.month == 10 && num == 1) {
return context.getString(R.string.shiyi);
} else if (this.month == 12 && num == 25) {
return context.getString(R.string.shengdanjie);
} else if (chinaCalendar[1] == 8 && chinaCalendar[2] == 15) {
return context.getString(R.string.zhongtuijie);
} else if (this.month == 2 && num == 14) {
return context.getString(R.string.qingrenjie);
} else {
return String.valueOf(num);
}
}
private boolean isValid(int num) {
if (this.unEnableDay == num) {
return false;
}
if (unEnableCount > 0) {
for (int i = 1; i <= unEnableCount; ++i) {
if (this.unEnableDay + i == num)
return false;
}
}
Calendar calendar = format.getCalendar();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
int day = calendar.get(Calendar.DAY_OF_MONTH);
if (num == 0) {
return false;
}
// 本年
if (year == this.year) {
if (this.month > month) {
return true;
} else if (this.month < month) {
return false;
} else {
return num >= day ? true : false;
}
} else if (year < this.year) {
return true;
} else {
return false;
}
}
private boolean isToday(int num) {
Calendar calendar = format.getCalendar();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
this.day = calendar.get(Calendar.DAY_OF_MONTH);
if (this.year == year && this.month == month && num == this.day) {
return true;
} else {
return false;
}
}
private boolean isSelect(int num) {
if (num == this.selectDay1) {
return true;
}
if (selectCount > 0) {
for (int i = 1; i <= selectCount; ++i) {
if (num == this.selectDay1 + i) {
return true;
}
}
}
return false;
}
// 设置不可选中
public void setUnEnable(int unEnable, int unEnableCount) {
this.unEnableDay = unEnable;
this.unEnableCount = unEnableCount;
adapter.notifyDataSetChanged();
}
public interface OnSelectDateChangeListener {
public void onSelectDateChange(View v, int year, int month, int day);
}
public void setOnSelectDateListener(OnSelectDateChangeListener listener) {
this.onSelectDateChangeListener = listener;
}
private OnItemClickListener onItemClickListener = new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
int selectDay = postions.get(arg2);
MonthView.this.day = selectDay;
setSelectDate(selectDay, 0);
if (onSelectDateChangeListener != null) {
onSelectDateChangeListener.onSelectDateChange(MonthView.this,
MonthView.this.year, MonthView.this.month, selectDay);
}
}
};
}
自定义月份的控件
package com.haihang.android.view;
import java.util.Calendar;
import java.util.GregorianCalendar;
import com.haihang.android.R;
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.LinearLayout;
public class CalenderView extends LinearLayout {
private LayoutInflater layoutInfalter;
private MonthView[] monthViews;
public CalenderView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CalenderView(Context context) {
super(context);
}
private void init(Context context) {
layoutInfalter = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInfalter.inflate(R.layout.calendar_view, this);
monthViews = new MonthView[6];
for(int i = 0;i < 6;i++) {
int id = getResources().getIdentifier("month" + (i + 1), "id", getContext().getPackageName());
monthViews[i] = (MonthView)findViewById(id);
}
initMonthViewsData();
}
private void initMonthViewsData() {
Calendar calendar = Calendar.getInstance();
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH);
GregorianCalendar greCalendar = new GregorianCalendar(year, month, 1);
for(int i = 0;i < 6;++i) {
month = greCalendar.get(Calendar.MONTH) + 1;
monthViews[i].setDate(year,month);
greCalendar.add(Calendar.MONTH, 1);
if(year != greCalendar.get(Calendar.YEAR)) {
year++;
}
}
}
}
自定义日历控件
package com.haihang.android.util;
import java.util.Date;
public class CalendarUtils {
final static long[] lunarInfo = 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 };
final public static int lYearDays(int y) {
int i, sum = 348;
for (i = 0x8000; i > 0x8; i >>= 1) {
if ((lunarInfo[y - 1900] & i) != 0)
sum += 1;
}
return (sum + leapDays(y));
}
final public static int leapDays(int y) {
if (leapMonth(y) != 0) {
if ((lunarInfo[y - 1900] & 0x10000) != 0)
return 30;
else
return 29;
} else
return 0;
}
final public static int leapMonth(int y) {
return (int) (lunarInfo[y - 1900] & 0xf);
}
final public static int monthDays(int y, int m) {
if ((lunarInfo[y - 1900] & (0x10000 >> m)) == 0)
return 29;
else
return 30;
}
final public static long[] calElement(int y, int m, int d) {
long[] nongDate = new long[7];
int i = 0, temp = 0, leap = 0;
Date baseDate = new Date(0, 0, 31);
Date objDate = new Date(y - 1900, m - 1, d);
long offset = (objDate.getTime() - baseDate.getTime()) / 86400000L;
nongDate[5] = offset + 40;
nongDate[4] = 14;
for (i = 1900; i < 2050 && offset > 0; i++) {
temp = lYearDays(i);
offset -= temp;
nongDate[4] += 12;
}
if (offset < 0) {
offset += temp;
i--;
nongDate[4] -= 12;
}
nongDate[0] = i;
nongDate[3] = i - 1864;
leap = leapMonth(i); // 闰哪个月
nongDate[6] = 0;
for (i = 1; i < 13 && offset > 0; i++) {
// 闰月
if (leap > 0 && i == (leap + 1) && nongDate[6] == 0) {
--i;
nongDate[6] = 1;
temp = leapDays((int) nongDate[0]);
} else {
temp = monthDays((int) nongDate[0], i);
}
// 解除闰月
if (nongDate[6] == 1 && i == (leap + 1))
nongDate[6] = 0;
offset -= temp;
if (nongDate[6] == 0)
nongDate[4]++;
}
if (offset == 0 && leap > 0 && i == leap + 1) {
if (nongDate[6] == 1) {
nongDate[6] = 0;
} else {
nongDate[6] = 1;
--i;
--nongDate[4];
}
}
if (offset < 0) {
offset += temp;
--i;
--nongDate[4];
}
nongDate[1] = i;
nongDate[2] = offset + 1;
return nongDate;
}
}
农历的工具类
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/day_tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:background="@android:color/white" >
</TextView>
month_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/date_label_tv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="2012年9月"
android:layout_marginTop="5dip"
android:layout_marginBottom="10dip"
android:textColor="@android:color/darker_gray"
android:textSize="30sp"
android:textStyle="bold"
android:gravity="center"/>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dip"
android:orientation="horizontal">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/sunday"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/monday"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/tuesday"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/thirday"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/thuesday"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/friday"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="@string/staday"/>
</LinearLayout>
<com.haihang.android.view.AutoFitGridView
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/grid_bg"
android:verticalSpacing="1dip"
android:horizontalSpacing="1dip"
android:cacheColorHint="@android:color/transparent"
android:fastScrollEnabled="false"
android:fadingEdge="none"
android:layout_margin="8dip"
android:numColumns="7"
android:fadingEdgeLength="0dip"></com.haihang.android.view.AutoFitGridView>
</LinearLayout>
month_view.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fadeScrollbars="false"
android:fadingEdge="none"
android:fadingEdgeLength="0dip" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<com.haihang.android.view.MonthView
android:id="@+id/month1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<com.haihang.android.view.MonthView
android:id="@+id/month2"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<com.haihang.android.view.MonthView
android:id="@+id/month3"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<com.haihang.android.view.MonthView
android:id="@+id/month4"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<com.haihang.android.view.MonthView
android:id="@+id/month5"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<com.haihang.android.view.MonthView
android:id="@+id/month6"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
calendar_view.xml