公司項(xiàng)目需要一個(gè)功能全面的日歷,然后就在網(wǎng)上找demo,然后根據(jù)demo自己深度定制了一個(gè)日歷,基本滿(mǎn)足了需求,現(xiàn)在把日歷核心代碼共享給大家。源碼下載地址http://download.csdn.net/detail/voidmain_123/9275921
CollapseCalendarView.java
只需要將該控件引入到布局文件中
package com.eroad.widget.calendar;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import org.joda.time.LocalDate;
import org.json.JSONObject;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.eroad.widget.calendar.manager.CalendarManager;
import com.eroad.widget.calendar.manager.CalendarManager.State;
import com.eroad.widget.calendar.manager.Day;
import com.eroad.widget.calendar.manager.Month;
import com.eroad.widget.calendar.manager.ResizeManager;
import com.eroad.widget.calendar.manager.Week;
import com.eroad.widget.calendar.widget.DayView;
import com.eroad.widget.calendar.widget.WeekView;
import com.example.calendarnew.R;
/**
* 日歷View
* @author MaJian
*
*/
@SuppressLint({ “SimpleDateFormat”, “NewApi” }) public class CollapseCalendarView extends LinearLayout implements View.OnClickListener {
public static final String TAG = "CalendarView";private CalendarManager mManager;private TextView mTitleView;
private ImageButton mPrev;
private ImageButton mNext;
private LinearLayout mWeeksView;private final LayoutInflater mInflater;
private final RecycleBin mRecycleBin = new RecycleBin();private OnDateSelect mListener;
private TextView mSelectionText;
private LinearLayout mHeader;
private ResizeManager mResizeManager;
private ImageView mIvPre;
private ImageView mIvNext;
private Animation left_in;
private Animation right_in;
private boolean initialized;
private String[] weeks;
private OnTitleClickListener titleClickListener;private JSONObject dataObject; //日歷數(shù)據(jù)源
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
private boolean showChinaDay = true; //是否顯示農(nóng)歷日期public CollapseCalendarView(Context context) {this(context, null);onFinishInflate();
}public void showChinaDay(boolean showChinaDay){this.showChinaDay = showChinaDay;populateLayout();
}/*** 設(shè)置標(biāo)題點(diǎn)擊監(jiān)聽(tīng)器* @param titleClickListener*/
public void setTitleClickListener(OnTitleClickListener titleClickListener){this.titleClickListener = titleClickListener;
}public CollapseCalendarView(Context context, AttributeSet attrs) {this(context, attrs, R.attr.calendarViewStyle);
}public void setArrayData(JSONObject jsonObject){this.dataObject = jsonObject;
}public interface OnTitleClickListener{public void onTitleClick();
}@SuppressLint("NewApi")
public CollapseCalendarView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);weeks = getResources().getStringArray(R.array.weeks);mInflater = LayoutInflater.from(context);mResizeManager = new ResizeManager(this);inflate(context, R.layout.calendar_layout, this);setOrientation(VERTICAL);setBackgroundColor(getResources().getColor(R.color.cal_color_white));mIvPre = new ImageView(getContext());mIvNext = new ImageView(getContext());RelativeLayout.LayoutParams param = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, android.widget.RelativeLayout.LayoutParams.WRAP_CONTENT);mIvPre.setLayoutParams(param);mIvNext.setLayoutParams(param);initAnim();
}/*** 初始化左右滑動(dòng)動(dòng)畫(huà)*/
private void initAnim(){left_in = AnimationUtils.makeInAnimation(getContext(), true);right_in = AnimationUtils.makeInAnimation(getContext(), false);
}/*** 初始化日歷管理器* @param manager 日歷管理器對(duì)象*/
public void init(CalendarManager manager) {if (manager != null) {mManager = manager;if (mListener != null) {mListener.onDateSelected(mManager.getSelectedDay());}populateLayout();}
}
/*** 切換到指定某天界面* @param date yyyy-MM-dd*/
public void changeDate(String date){if (date.compareTo(mManager.getSelectedDay().toString()) > 0) {this.setAnimation(right_in);right_in.start();} else if (date.compareTo(mManager.getSelectedDay().toString()) < 0) {this.setAnimation(left_in);left_in.start();}try {mManager.init(LocalDate.fromDateFields(sdf.parse(date)));} catch (ParseException e) {// TODO Auto-generated catch blocke.printStackTrace();}init(mManager);
}public CalendarManager getManager() {return mManager;
}@Override
public void onClick(View v) {if (mManager != null) {int id = v.getId();if (id == R.id.prev) {prev();} else if (id == R.id.next) {next();} else if (id == R.id.title) {if (titleClickListener != null) {titleClickListener.onTitleClick();}}}
}@SuppressLint("WrongCall")
@Override
protected void dispatchDraw( Canvas canvas) {mResizeManager.onDraw();super.dispatchDraw(canvas);
}public CalendarManager.State getState() {if (mManager != null) {return mManager.getState();} else {return null;}
}public void setDateSelectListener(OnDateSelect listener) {mListener = listener;
}/*** 設(shè)置日歷標(biāo)題* @param text*/
public void setTitle(String text) {if (TextUtils.isEmpty(text)) {mHeader.setVisibility(View.VISIBLE);mSelectionText.setVisibility(View.GONE);} else {mHeader.setVisibility(View.GONE);mSelectionText.setVisibility(View.VISIBLE);mSelectionText.setText(text);}
}
/*** 顯示日歷自帶標(biāo)題*/
public void showHeader(){mHeader.setVisibility(View.VISIBLE);
}
/*** 隱藏日歷自帶標(biāo)題*/
public void hideHeader(){mHeader.setVisibility(View.GONE);
}@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {return mResizeManager.onInterceptTouchEvent(ev);
}@Override
public boolean onTouchEvent( MotionEvent event) {super.onTouchEvent(event);return mResizeManager.onTouchEvent(event);
}
/*** 周-月*/
public void weekToMonth(){if (mManager.getState() == CalendarManager.State.WEEK) {mManager.toggleView();}
}/*** 月-周*/
public void monthToWeek(){if (mManager.getState() == CalendarManager.State.MONTH) {mManager.toggleView();}
}@Override
protected void onFinishInflate() {super.onFinishInflate();mTitleView = (TextView) findViewById(R.id.title);mTitleView.setOnClickListener(this);mPrev = (ImageButton) findViewById(R.id.prev);mNext = (ImageButton) findViewById(R.id.next);mWeeksView = (LinearLayout) findViewById(R.id.weeks);mHeader = (LinearLayout) findViewById(R.id.header);mSelectionText = (TextView) findViewById(R.id.selection_title);mPrev.setOnClickListener(this);mNext.setOnClickListener(this);populateLayout();
}/*** 繪制日歷周標(biāo)題*/
private void populateDays() {if (!initialized) {CalendarManager manager = getManager();if (manager != null) {LinearLayout layout = (LinearLayout) findViewById(R.id.days);for (int i = 0; i < 7; i++) {TextView textView = (TextView) layout.getChildAt(i);textView.setText(weeks[i]);if (i > 4) {textView.setTextColor(getResources().getColor(R.color.cal_blue_dark));}}initialized = true;}}
}/*** 刷新日歷View*/
public synchronized void populateLayout() {if (mManager != null) {populateDays();if (mPrev != null) {mPrev.setEnabled(mManager.hasPrev());mNext.setEnabled(mManager.hasNext());mTitleView.setText(mManager.getHeaderText());if (mManager.getState() == CalendarManager.State.MONTH) {populateMonthLayout((Month) mManager.getUnits());} else {populateWeekLayout((Week) mManager.getUnits());}}}
}/*** 刷新日歷Month View* @param month 月份*/
private void populateMonthLayout(Month month) {List<Week> weeks = month.getWeeks();int cnt = weeks.size();for (int i = 0; i < cnt; i++) {WeekView weekView = getWeekView(i);populateWeekLayout(weeks.get(i), weekView);}int childCnt = mWeeksView.getChildCount();if (cnt < childCnt) {for (int i = cnt; i < childCnt; i++) {cacheView(i);}}
}/*** 刷新日歷Week View* @param week 周*/
private void populateWeekLayout(Week week) {WeekView weekView = getWeekView(0);populateWeekLayout(week, weekView);int cnt = mWeeksView.getChildCount();if (cnt > 1) {for (int i = cnt - 1; i > 0; i--) {cacheView(i);}}
}private void populateWeekLayout( Week week, WeekView weekView) {List<Day> days = week.getDays();for (int i = 0; i < 7; i++) {final Day day = days.get(i);LinearLayout layout = (LinearLayout) weekView.getChildAt(i);DayView dayView = (DayView) layout.findViewById(R.id.tvDayView);DayView chinaDay = (DayView) layout.findViewById(R.id.tvChina);if (showChinaDay) {chinaDay.setVisibility(View.VISIBLE);} else {chinaDay.setVisibility(View.GONE);}View viewPoint = layout.findViewById(R.id.view_point);TextView tvDayType = (TextView) layout.findViewById(R.id.tv_day_type);//渲染日期上班休假類(lèi)型if (dataObject != null && dataObject.optJSONObject(sdf.format(day.getDate().toDate())) != null) {JSONObject jsonObject = dataObject.optJSONObject(sdf.format(day.getDate().toDate()));if (!TextUtils.isEmpty(jsonObject.optString("type"))) {tvDayType.setText(jsonObject.optString("type"));tvDayType.setVisibility(View.VISIBLE);if (jsonObject.optString("type").equals("假")) {tvDayType.setBackground(getResources().getDrawable(R.drawable.bg_day_type_red));} else if (jsonObject.optString("type").equals("班")) {tvDayType.setBackground(getResources().getDrawable(R.drawable.bg_day_type_blue));}} else {tvDayType.setVisibility(View.GONE);}if (jsonObject.optJSONArray("list") != null && jsonObject.optJSONArray("list").length() >= 0) {viewPoint.setVisibility(View.VISIBLE);} else {viewPoint.setVisibility(View.INVISIBLE);}} else {tvDayType.setVisibility(View.INVISIBLE);viewPoint.setVisibility(View.INVISIBLE);}dayView.setText(day.getText());chinaDay.setText(day.getChinaDate());if (day.getDate().getYear() == mManager.getCurrentMonthDate().getYear() && day.getDate().getMonthOfYear() == mManager.getCurrentMonthDate().getMonthOfYear()|| mManager.getState() == State.WEEK) {//如果日期是當(dāng)前月份if (i > 4) {//周末dayView.setTextColor(getResources().getColor(R.color.cal_blue_dark));chinaDay.setTextColor(getResources().getColor(R.color.cal_blue_dark));} else {//非周末dayView.setTextColor(getResources().getColor(R.color.cal_text_normal));chinaDay.setTextColor(getResources().getColor(R.color.cal_text_normal));}} else {//日期不是當(dāng)前月份if (i > 4) {//周末dayView.setTextColor(getResources().getColor(R.color.cal_blue_light));chinaDay.setTextColor(getResources().getColor(R.color.cal_blue_light));} else {//非周末dayView.setTextColor(getResources().getColor(R.color.cal_line_grey));chinaDay.setTextColor(getResources().getColor(R.color.cal_line_grey));}}layout.setSelected(day.isSelected());if (day.getDate().equals(mManager.getToday()) && day.isSelected()) {//日期對(duì)象是今天,并且被選中if (day.getDate().getYear() == mManager.getCurrentMonthDate().getYear() && day.getDate().getMonthOfYear() == mManager.getCurrentMonthDate().getMonthOfYear()) {//如果日期是當(dāng)前月份if (i > 4) {//周末dayView.setTextColor(getResources().getColorStateList(R.color.text_calendar_week));chinaDay.setTextColor(getResources().getColorStateList(R.color.text_calendar_week));} else {//非周末dayView.setTextColor(getResources().getColorStateList(R.color.text_calendar));chinaDay.setTextColor(getResources().getColorStateList(R.color.text_calendar));}} else {//日期不是當(dāng)前月份if (i > 4) {//周末dayView.setTextColor(getResources().getColorStateList(R.color.text_calendar_week_out_month));chinaDay.setTextColor(getResources().getColorStateList(R.color.text_calendar_week_out_month));} else {//非周末dayView.setTextColor(getResources().getColorStateList(R.color.text_calendar_out_month));chinaDay.setTextColor(getResources().getColorStateList(R.color.text_calendar_out_month));}}layout.setBackground(getResources().getDrawable(R.drawable.bg_btn_calendar_today_selected));viewPoint.setBackground(getResources().getDrawable(R.drawable.bg_calendar_point_white));layout.setSelected(true);} else if (day.getDate().equals(mManager.getToday())) {//日期對(duì)象今天viewPoint.setBackground(getResources().getDrawable(R.drawable.bg_calendar_point_blue));layout.setBackground(getResources().getDrawable(R.drawable.bg_btn_calendar_today));layout.setSelected(true);} else {//日期對(duì)象被選中viewPoint.setBackground(getResources().getDrawable(R.drawable.bg_calendar_point_blue));layout.setBackground(getResources().getDrawable(R.drawable.bg_btn_calendar));}dayView.setCurrent(day.isCurrent());boolean enables = day.isEnabled();dayView.setEnabled(enables);if (enables) { // 解除點(diǎn)擊限制,所有的都可以點(diǎn)擊layout.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {LocalDate date = day.getDate();if (mManager.getState() == State.MONTH) {//判斷當(dāng)前視圖狀態(tài)為月份視圖if (date.getYear() > mManager.getCurrentMonthDate().getYear()) {//選中日期年份大于當(dāng)前顯示年份next();} else if (date.getYear() < mManager.getCurrentMonthDate().getYear()) {//選中日期年份小于當(dāng)前顯示年份prev();} else {//選中日期年份等于當(dāng)前顯示年份if (date.getMonthOfYear() > mManager.getCurrentMonthDate().getMonthOfYear()) {//選中月份大于當(dāng)前月份next();} else if (date.getMonthOfYear() < mManager.getCurrentMonthDate().getMonthOfYear()) {//選中月份小于當(dāng)前月份prev();}}}if (mManager.selectDay(date)) {populateLayout();if (mListener != null) {//執(zhí)行選中回調(diào)mListener.onDateSelected(date);}}}});} else {dayView.setOnClickListener(null);}}}/*** 翻轉(zhuǎn)到前一頁(yè)*/
public void prev(){if (mManager.prev()) {populateLayout();}if (mListener != null) {//執(zhí)行選中回調(diào)mListener.onDateSelected(mManager.getSelectedDay());}this.setAnimation(left_in);left_in.start();
}/*** 翻轉(zhuǎn)到下一頁(yè)*/
public void next(){if (mManager.next()) {populateLayout();}if (mListener != null) {//執(zhí)行選中回調(diào)mListener.onDateSelected(mManager.getSelectedDay());}this.setAnimation(right_in);right_in.start();
}public LinearLayout getWeeksView() {return mWeeksView;
}private WeekView getWeekView(int index) {int cnt = mWeeksView.getChildCount();if(cnt < index + 1) {for (int i = cnt; i < index + 1; i++) {View view = getView();mWeeksView.addView(view);}}return (WeekView) mWeeksView.getChildAt(index);
}private View getView() {View view = mRecycleBin.recycleView();if (view == null) {view = mInflater.inflate(R.layout.week_layout, this, false);} else {view.setVisibility(View.VISIBLE);}return view;
}private void cacheView(int index) {View view = mWeeksView.getChildAt(index);if(view != null) {mWeeksView.removeViewAt(index);mRecycleBin.addView(view);}
}public LocalDate getSelectedDate() {return mManager.getSelectedDay();
}@Override
protected void onDetachedFromWindow() {super.onDetachedFromWindow();mResizeManager.recycle();
}private class RecycleBin {private final Queue<View> mViews = new LinkedList<View>();public View recycleView() {return mViews.poll();}public void addView(View view) {mViews.add(view);}
}public interface OnDateSelect {public void onDateSelected(LocalDate date);
}
}
MainActivity主界面
基本的事件處理以及監(jiān)聽(tīng)器的使用
package com.eroad.widget.calendar;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.joda.time.LocalDate;
import org.json.JSONArray;
import org.json.JSONObject;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Toast;
import com.eroad.widget.calendar.CollapseCalendarView.OnDateSelect;
import com.eroad.widget.calendar.CollapseCalendarView.OnTitleClickListener;
import com.eroad.widget.calendar.manager.CalendarManager;
import com.eroad.widget.calendar.manager.CalendarManager.OnMonthChangeListener;
import com.example.calendarnew.R;
/**
* Main
* @author MaJian
*
*/
public class MainActivity extends Activity {
private CollapseCalendarView calendarView;
private CalendarManager mManager;
private JSONObject json;
private SimpleDateFormat sdf;
private boolean show = false;@Override
protected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.activity_main);sdf = new SimpleDateFormat("yyyy-MM-dd");calendarView = (CollapseCalendarView) findViewById(R.id.calendar);mManager = new CalendarManager(LocalDate.now(),CalendarManager.State.MONTH, LocalDate.now().withYear(100),LocalDate.now().plusYears(100));//月份切換監(jiān)聽(tīng)器mManager.setMonthChangeListener(new OnMonthChangeListener() {@Overridepublic void monthChange(String month, LocalDate mSelected) {// TODO Auto-generated method stubToast.makeText(MainActivity.this, month, Toast.LENGTH_SHORT).show();}});/*** 日期選中監(jiān)聽(tīng)器*/calendarView.setDateSelectListener(new OnDateSelect() {@Overridepublic void onDateSelected(LocalDate date) {// TODO Auto-generated method stubToast.makeText(MainActivity.this, date.toString(), Toast.LENGTH_SHORT).show();}});calendarView.setTitleClickListener(new OnTitleClickListener() {@Overridepublic void onTitleClick() {// TODO Auto-generated method stubToast.makeText(MainActivity.this, "點(diǎn)擊標(biāo)題", Toast.LENGTH_SHORT).show();}});//回到今天findViewById(R.id.btn_today).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubcalendarView.changeDate(LocalDate.now().toString());}});//周月切換findViewById(R.id.btn_changemode).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubmManager.toggleView();calendarView.populateLayout();}});//顯示或者隱藏農(nóng)歷findViewById(R.id.btn_hide).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubcalendarView.showChinaDay(show);show = !show;}});Calendar cal = Calendar.getInstance();cal.set(Calendar.MONTH, 9);cal.set(Calendar.DAY_OF_MONTH, 0);json = new JSONObject();try {for (int i = 0; i < 30; i++) {JSONObject jsonObject2 = new JSONObject();if (i <= 6) {jsonObject2.put("type", "休");} else if ( i > 6 && i< 11) {jsonObject2.put("type", "班");}if (i%3 == 0) {jsonObject2.put("list", new JSONArray());}json.put(sdf.format(cal.getTime()), jsonObject2);cal.add(Calendar.DAY_OF_MONTH, 1);}} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}//設(shè)置數(shù)據(jù)顯示calendarView.setArrayData(json);//初始化日歷管理器calendarView.init(mManager);
}
}
布局文件源碼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><com.eroad.widget.calendar.CollapseCalendarView
android:id="@+id/calendar"android:layout_width="match_parent"android:layout_height="wrap_content" ></com.eroad.widget.calendar.CollapseCalendarView><Button
android:id="@+id/btn_today"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="回到今天" /><Button
android:id="@+id/btn_changemode"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="周月切換" /><Button
android:id="@+id/btn_hide"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="隱藏、顯示農(nóng)歷" /></LinearLayout>
下面給大家分享下效果圖
如果大家比較滿(mǎn)意可以下載完整版demo
鏈接:http://download.csdn.net/detail/voidmain_123/9275921
總結(jié)
以上是生活随笔為你收集整理的Android定制日历,支持周月切换,日期标记,农历显示,节假日的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。