赞
踩
Android 的 CalendarView 的 Material Design 后端端口。 目标是拥有 Material 的外观和感觉,而不是 100% 与平台的实现相同。
1. 添加依赖:
allprojects {
repositories {
google()
mavenCentral()
maven { url 'https://jitpack.io' }
jcenter() // Warning: this repository is going to shut down soon
}
}
---------------------------------------------------------
implementation 'com.github.prolificinteractive:material-calendarview:1.6.0'
2. dialog_material_calendar.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent"
android:gravity="center">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_margin="@dimen/material_calendar_dialog_margin"
android:background="#ffffff">
<!-- 展现选中的日期区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/material_calendar_dialog_paddingTB"
android:paddingBottom="@dimen/material_calendar_dialog_paddingTB"
android:paddingLeft="@dimen/material_calendar_dialog_paddingLR"
android:paddingRight="@dimen/material_calendar_dialog_paddingLR"
android:background="@color/materialcalendar_selected_color">
<!-- 年份 -->
<TextView
android:id="@+id/tv_year"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="2021年"
android:textSize="@dimen/material_calendar_dialog_year_textsize"
android:textColor="#ffffff"
/>
<!-- 月日星期 -->
<TextView
android:id="@+id/tv_monthday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="5月24日 周日"
android:textSize="@dimen/material_calendar_dialog_monthday_textsize"
android:textColor="#ffffff"
/>
</LinearLayout>
<!-- 日历控件 -->
<com.prolificinteractive.materialcalendarview.MaterialCalendarView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/calendarView"
android:layout_width="wrap_content"
android:layout_height="0.0dp"
android:layout_weight="1"
app:mcv_showOtherDates="all"
/>
<!-- 底部按钮区域 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="right|center_vertical"
android:padding="@dimen/material_calendar_dialog_paddingTB">
<!-- 取消 -->
<TextView
android:id="@+id/tv_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消"
android:textSize="18sp"
android:textColor="@color/materialcalendar_selected_color"
android:paddingRight="@dimen/material_calendar_dialog_paddingLR"/>
<!-- 确定 -->
<TextView
android:id="@+id/tv_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确定"
android:textSize="18sp"
android:textColor="@color/materialcalendar_selected_color"
android:paddingLeft="@dimen/material_calendar_dialog_paddingTB"
android:paddingRight="@dimen/material_calendar_dialog_paddingTB"/>
</LinearLayout>
</LinearLayout>
</RelativeLayout>
3. material_calendar_decorator_selected_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:exitFadeDuration="@android:integer/config_shortAnimTime">
<item android:state_checked="true">
<shape android:shape="oval">
<solid android:color="@color/materialcalendar_selected_color"></solid>
</shape>
</item>
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="@color/materialcalendar_selected_color"></solid>
</shape>
</item>
<item android:drawable="@android:color/transparent"/>
</selector>
decorators/TodayDecorator.java
(今天的日期的文本特殊显示(加粗、加大字号))
public class TodayDecorator implements DayViewDecorator {
private final CalendarDay today;
private ForegroundColorSpan span;//文本颜色
public TodayDecorator(Context mContext) {
today = CalendarDay.today();
span = new ForegroundColorSpan(mContext.getResources().getColor(R.color.materialcalendar_today_border_color));
}
@Override
public boolean shouldDecorate(CalendarDay day) {
return today.equals(day);
}
@Override
public void decorate(DayViewFacade view) {
view.addSpan(span);
view.addSpan(new StyleSpan(Typeface.BOLD));
view.addSpan(new RelativeSizeSpan(1.4f));
}
}
decorators/SelectedDayDecorator.java
public class SelectedDayDecorator implements DayViewDecorator {
private CalendarDay selectedDate = null;
public SelectedDayDecorator() {
selectedDate = CalendarDay.today();
}
@Override
public boolean shouldDecorate(CalendarDay day) {
return selectedDate != null && day.equals(selectedDate) && !day.equals(CalendarDay.today());
}
@Override
public void decorate(DayViewFacade view) {
view.addSpan(new RelativeSizeSpan(1.4f));
view.addSpan(new StyleSpan(Typeface.BOLD));
}
/**
*
*/
public void setDate(Date date) {
this.selectedDate = CalendarDay.from(date);
}
}
decorators/CustomDecorator.java
public class CustomDecorator implements DayViewDecorator {
private final Drawable mDrawable;
public CustomDecorator(Context context) {
mDrawable = context.getResources().getDrawable(R.drawable.material_calendar_decorator_selected_bg);
}
@Override
public boolean shouldDecorate(CalendarDay day) {
return true;
}
@Override
public void decorate(DayViewFacade view) {
view.setSelectionDrawable(mDrawable);
}
}
MaterialCalendarDialog.java
public class MaterialCalendarDialog extends DialogFragment {
private static final String TAG = MaterialCalendarDialog.class.getSimpleName();
/**View实例*/
private View myView;
/**context实例*/
private Context mContext;
/**标记:用来代表是从哪个界面打开的这个对话框*/
private String mTag;
//年份文本
private TextView mYear;
//月日星期文本
private TextView mMonthDay;
//日历控件
private MaterialCalendarView mCalendarView;
//取消文本
private TextView mCancleBtn;
//确定文本
private TextView mOkBtn;
private Date selectedDate;//选中的日期
private final SelectedDayDecorator selectedDayDecorator = new SelectedDayDecorator();
public static MaterialCalendarDialog getInstance(Context mContext, Date selectedDate){
MaterialCalendarDialog dialog = new MaterialCalendarDialog();
dialog.mContext = mContext;
if(selectedDate == null){
Calendar calendar = Calendar.getInstance();
selectedDate = calendar.getTime();
}
dialog.selectedDate = selectedDate;
return dialog;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NORMAL, android.R.style.Theme_NoTitleBar_Fullscreen);//全屏
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#80000000")));//设置背景为半透明,并且没有标题
getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏
//设置窗体全屏
getDialog().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
myView = inflater.inflate(R.layout.dialog_material_calendar, container, false);
return myView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
//初始化控件以及设置初始数据和监听事件
initView();
//初始化数据
initData();
//初始化监听事件
initEvent();
}
/**
* 设置宽度和高度值,以及打开的动画效果
*/
@Override
public void onStart() {
super.onStart();
//设置对话框的宽高,必须在onStart中
DisplayMetrics metrics = new DisplayMetrics();
this.getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
Window window = this.getDialog().getWindow();
window.setLayout(metrics.widthPixels, metrics.heightPixels - getStatusBarHeight(mContext));
window.setGravity(Gravity.BOTTOM);//设置在底部
//打开的动画效果--缩放+渐隐
}
/**获取状态栏的高度*/
private int getStatusBarHeight(Context context) {
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
return context.getResources().getDimensionPixelSize(resourceId);
}
/**实例化控件*/
private void initView() {
mYear = (TextView) myView.findViewById(R.id.tv_year);
mMonthDay = (TextView) myView.findViewById(R.id.tv_monthday);
mCalendarView = (MaterialCalendarView) myView.findViewById(R.id.calendarView);
mCancleBtn = (TextView) myView.findViewById(R.id.tv_cancel);
mOkBtn = (TextView) myView.findViewById(R.id.tv_ok);
}
private void initData() {
mTag = this.getTag();
Log.e(TAG, "mTag="+mTag);
parseDateToYearMonthDayWeek(selectedDate);//显示默认的日期文本
mCalendarView.setSelectedDate(selectedDate);//设置选中的日期
mCalendarView.setCurrentDate(selectedDate);//实现定位到选中日期的当月
mCalendarView.setArrowColor(Color.parseColor("#1A78EC"));//设置切换月份的箭头的颜色值【没有起作用】
//设置最小和最大日期
try {
Date minDate = DateTimeHelper.parseStringToDate("1970-01-01");
Date maxDate = DateTimeHelper.parseStringToDate("2070-01-01");
mCalendarView.state().edit()
// .setFirstDayOfWeek(Calendar.MONDAY) //设置每周开始的第一天
.setMinimumDate(minDate)
.setMaximumDate(maxDate)
// .setCalendarDisplayMode(CalendarMode.MONTHS)//设置显示模式,可以显示月的模式,也可以显示周的模式
.commit();
} catch (ParseException e) {
e.printStackTrace();
}
// mCalendarView.state().edit().setMaximumDate(maxDate).commit();
mCalendarView.addDecorators(new CustomDecorator(mContext),
selectedDayDecorator,
new TodayDecorator(mContext));
}
//初始化监听事件
private void initEvent() {
//日历控件的点击事件
mCalendarView.setOnDateChangedListener(new OnDateSelectedListener() {
@Override
public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) {
selectedDate = date.getDate();
parseDateToYearMonthDayWeek(selectedDate);
//刷新选中的状态
selectedDayDecorator.setDate(selectedDate);
widget.invalidateDecorators();
}
});
//取消按钮的点击事件
mCancleBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
}
});
//确定按钮的点击事件
mOkBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
dismiss();
if(OnokClickLitener != null){
OnokClickLitener.onOkClick(selectedDate);
}
}
});
}
/*=====================OnOkClickLitener================================*/
public interface OnOkClickLitener
{
/**确定按钮的点击事件*/
void onOkClick(Date date);
}
private OnOkClickLitener OnokClickLitener;
public void setOnOkClickLitener(OnOkClickLitener OnokClickLitener)
{
this.OnokClickLitener = OnokClickLitener;
}
/**解析日期,获取年月日星期*/
private void parseDateToYearMonthDayWeek(Date date){
//获取默认选中的日期的年月日星期的值,并赋值
Calendar calendar = Calendar.getInstance();//日历对象
calendar.setTime(date);//设置当前日期
String yearStr = calendar.get(Calendar.YEAR)+"";//获取年份
int month = calendar.get(Calendar.MONTH) + 1;//获取月份
String monthStr = month < 10 ? "0" + month : month + "";
int day = calendar.get(Calendar.DATE);//获取日
String dayStr = day < 10 ? "0" + day : day + "";
int week = calendar.get(Calendar.DAY_OF_WEEK);
String weekStr = "";
switch (week) {
case 1:
weekStr = "周日";
break;
case 2:
weekStr = "周一";
break;
case 3:
weekStr = "周二";
break;
case 4:
weekStr = "周三";
break;
case 5:
weekStr = "周四";
break;
case 6:
weekStr = "周五";
break;
case 7:
weekStr = "周六";
break;
default:
break;
}
Log.e(TAG, yearStr + "年" + monthStr + "月" + dayStr + "日" + " " + weekStr);
mYear.setText(yearStr + "年");
String formatStr = "%1$s月%2$s日 %3$s";
mMonthDay.setText(String.format(formatStr,monthStr,dayStr,weekStr));
}
}
DateTimeHelper.java
public class DateTimeHelper {
public static final String FORMAT_24 = "yyyy-MM-dd HH:mm:ss";//24小时制
public static final String FORMAT_12 = "yyyy-MM-dd hh:mm:ss";//12小时制
public static final String FORMAT_TEXT_24 = "yyyy年MM月dd日 HH时mm分ss秒";
public static final String FORMAT_TEXT_12 = "yyyy年MM月dd日 hh时mm分ss秒";
public static final String FORMAT_DAY = "yyyy-MM-dd";//显示年月日
/**
* 将未指定格式的字符串转换成日期类型
* @param date - 20151123 或者 2015/11/23 或者2015-11-23
* @return Mon Nov 23 00:00:00 GMT+08:00 2015
*/
public static Date parseStringToDate(String date) throws ParseException {
Date result = null;
String parse = date;
parse = parse.replaceFirst("^[0-9]{4}([^0-9]?)", "yyyy$1");
parse = parse.replaceFirst("^[0-9]{2}([^0-9]?)", "yy$1");
parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}([^0-9]?)", "$1MM$2");
parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}( ?)", "$1dd$2");
parse = parse.replaceFirst("( )[0-9]{1,2}([^0-9]?)", "$1HH$2");
parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}([^0-9]?)", "$1mm$2");
parse = parse.replaceFirst("([^0-9]?)[0-9]{1,2}([^0-9]?)", "$1ss$2");
SimpleDateFormat format = new SimpleDateFormat(parse, Locale.CHINA);
result = format.parse(date);
return result;
}
/**
* 将日期以指定格式输出
* @param date - new Date()
* @param format - "yyyy-MM-dd"
* @return 2015-11-23
*/
public static String formatToString(Date date, String format) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(format,Locale.CHINA);
return sdf.format(date);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* 将日期格式的字符串以指定格式输出
* @param date - "2015/11/23"
* @param format - "yyyy-MM-dd"
* @return 2015-11-23
*/
public static String formatToString(String date, String format) {
try {
Date dt = DateTimeHelper.parseStringToDate(date);
SimpleDateFormat sdf = new SimpleDateFormat(format,Locale.CHINA);
return sdf.format(dt);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
/**
* 将时间戳转化为固定格式的日期字符串 (yyyy-MM-dd HH:mm:ss)
* @param time - new Date().getTime()+""
* @return 2015-11-23 14:05:20
*/
public static String getStrTime(String time) {
if (time.trim().equals("") || time == null)
return "";
String strTime = null;
time = time.substring(0, 10);
SimpleDateFormat mFormat = new SimpleDateFormat(FORMAT_24,Locale.CHINA);
long ltime = Long.valueOf(time);
strTime = mFormat.format(new Date(ltime * 1000L));
return strTime;
}
/**
* 将时间戳转化为指定格式日期的字符串
* @param time - new Date().getTime()+""
* @param format - "yyyy年MM月dd日 hh时mm分ss秒"
* @return 2015年11月23日 02时05分36秒
*/
public static String getStrTime(String time, String format) {
if (time.trim().equals("") || time == null || time.equals("null"))
return "";
String strTime = null;
time = time.substring(0, 10);
SimpleDateFormat mFormat = new SimpleDateFormat(format, Locale.CHINA);
long ltime = Long.valueOf(time);
strTime = mFormat.format(new Date(ltime * 1000L));
return strTime;
}
/**
* 当前时间提前一个月
* @return 2015-10-23
*/
public static String getPerMonthDate(){
Date date = new Date();//当前日期
SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_DAY,Locale.CHINA);//格式化对象
Calendar calendar = Calendar.getInstance();//日历对象
calendar.setTime(date); //设置当前日期
calendar.add(Calendar.MONTH, -1); //月份减一
return sdf.format(calendar.getTime());
}
/**
* 当前时间延后一个月
* @return 2015-12-23
*/
public static String getLastMonthDate(){
Date date = new Date();//当前日期
SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_DAY,Locale.CHINA);//格式化对象
Calendar calendar = Calendar.getInstance();//日历对象
calendar.setTime(date); //设置当前日期
calendar.add(Calendar.MONTH, 1); //月份加一
return sdf.format(calendar.getTime());
}
/**
* 计算时间差(单位:天)
* @param startDate - "2015-11-23"
* @param endDate - "2015-12-20"
* @return 27(天)
*/
public static String getTimeDifferenceDate(String startDate, String endDate) {
try {
Date d1 = parseStringToDate(endDate);
Date d2 = parseStringToDate(startDate);
long diff = d1.getTime() - d2.getTime();
long days = diff / (1000 * 60 * 60 * 24);
return days + "";
} catch (Exception e) {
}
return "";
}
/**
* 计算两个日期型的时间相差多少时间
* @param startDate - DateTimeHelper.parseStringToDate("2015-11-23")
* @param endDate - DateTimeHelper.parseStringToDate("2015-12-20")
* @return 3周前
*/
public static String twoDateDistance(Date startDate, Date endDate) {
if (startDate == null || endDate == null) {
return null;
}
long timeLong = endDate.getTime() - startDate.getTime();
if (timeLong < 60 * 1000l)
return timeLong / 1000 + "秒前";
else if (timeLong < 60 * 60 * 1000l) {
timeLong = timeLong / 1000 / 60;
return timeLong + "分钟前";
} else if (timeLong < 24 * 60 * 60 * 1000l) {
timeLong = timeLong / 60 / 60 / 1000;
return timeLong + "小时前";
} else if (timeLong < 7 * 24 * 60 * 60 * 1000l) {
timeLong = timeLong / 1000 / 60 / 60 / 24;
return timeLong + "天前";
} else if (timeLong < 4 * 7 * 24 * 60 * 60 * 1000l) {
timeLong = timeLong / 1000 / 60 / 60 / 24 / 7;
return timeLong + "周前";
} else {
SimpleDateFormat sdf = new SimpleDateFormat(FORMAT_DAY,Locale.CHINA);
sdf.setTimeZone(TimeZone.getTimeZone("GMT+08:00"));
return sdf.format(startDate);
}
}
/**
* 判断两个日期的大小
*
* @param DATE1 -- "2015-11-23
* @param DATE2 --"2015-12-20"
* @return true 默认第一个比第二个时间小,所以如果第一个大于第二个,返回false
*/
public static boolean compare_date(String DATE1, String DATE2) {
//DateFormat df = new SimpleDateFormat();
//getDateInstance方法——获取日期格式器 2015-11-23
//getDateTimeInstance方法——获取日期/时间格式器 2015-11-23 09:37:50
//getInstance方法用于获取为日期和时间使用SHORT风格的默认日期/时间格式器
DateFormat df = DateFormat.getDateInstance();
try {
Date dt1 = parseStringToDate(DATE1);
Date dt2 = parseStringToDate(DATE2);
if (dt1.getTime() >= dt2.getTime()) {
return false;
} else if (dt1.getTime() < dt2.getTime()) {
return true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return false;
}
/**
* 将时间time字符串转化为Date对象
* @param strTime - 1448208000000
* @return Mon Nov 23 00:00:00 GMT+08:00 2015
*/
public static Date parseFormatTimeToDate(String strTime) {
Date date = new Date();
try{
date.setTime(Long.parseLong(strTime));
}
catch(NumberFormatException nfe){
nfe.printStackTrace();
}
return date;
}
/**
* 获取格式化后Date字符串的Time值
* @param dateStr 20151123 或者 2015/11/23 或者2015-11-23
* @return 1448208000000
* */
public static long getParseDateTime(String dateStr){
long daterTime = 0;
try {
Date dt1 = parseStringToDate(dateStr);
daterTime = dt1.getTime();
} catch (Exception exception) {
exception.printStackTrace();
}
return daterTime;
}
/**
* 当前时间延后一个星期
* @param startDate 2016-03-16
* @return 2015-03-23
*/
public static String getLastWeekDate(String startDate){
String endDate = "";
try {
Date date = parseStringToDate(startDate);
long startTime = date.getTime();
long endTime = startTime + 7 * 24 * 60 * 60 * 1000;
endDate = getStrTime(endTime+"",FORMAT_DAY);
} catch (Exception e) {
}
return endDate;
}
/**
* 判断是否同一天【一般用来判断是否是今天】
* @param date new Date()
* @param sameDate DateTimeHelper.parseStringToDate("2015-12-20")
* @return boolean false
*/
public static boolean isSameDay(Date date, Date sameDate) {
if (null == date || null == sameDate) {
return false;
}
Calendar nowCalendar = Calendar.getInstance();
nowCalendar.setTime(sameDate);
Calendar dateCalendar = Calendar.getInstance();
dateCalendar.setTime(date);
if (nowCalendar.get(Calendar.YEAR) == dateCalendar.get(Calendar.YEAR)
&& nowCalendar.get(Calendar.MONTH) == dateCalendar.get(Calendar.MONTH)
&& nowCalendar.get(Calendar.DATE) == dateCalendar.get(Calendar.DATE)) {
return true;
}
return false;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private EditText edt_starttime;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initDatas();
initEvents();
}
private void initViews() {
edt_starttime = (EditText) findViewById(R.id.edt_starttime);
}
private void initDatas() {
}
private void initEvents() {
//开始日期输入框的点击事件监听
edt_starttime.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Date todayDate = Calendar.getInstance().getTime();
if(! TextUtils.isEmpty(edt_starttime.getText().toString())){
try {
todayDate = DateTimeHelper.parseStringToDate(edt_starttime.getText().toString());
} catch (ParseException e) {
e.printStackTrace();
}
}
//显示日历对话框
MaterialCalendarDialog calendarDialog = MaterialCalendarDialog.getInstance(MainActivity.this,todayDate);
calendarDialog.setOnOkClickLitener(new MaterialCalendarDialog.OnOkClickLitener() {
@Override
public void onOkClick(Date date) {
edt_starttime.setText(DateTimeHelper.formatToString(date,"yyyy-MM-dd"));
}
});
calendarDialog.show(getSupportFragmentManager(),TAG);
}
});
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。