案例:在主页面的后下角,绘制一个图片按钮,点击跳转到日历页面
-
添加依赖:
//noinspection NotInterpolated
implementation 'com.prolificinteractive:material-calendarview:1.4.0'
-
需要的util 工具类
1、CircularAnimUtil.java
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.widget.ImageView;
/**
* Created on 2019/4/18 18:36
*
* @author Q.PeterGuo
* @version 1.0.0
* @Description
*/
public class CircularAnimUtil {
public static final long PERFECT_MILLS = 618;
public static final int MINI_RADIUS = 0;
/**
* 向四周伸张,直到完成显示。
*/
@SuppressLint("NewApi")
public static void show(View myView, float startRadius, long durationMills) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
myView.setVisibility(View.VISIBLE);
return;
}
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
int w = myView.getWidth();
int h = myView.getHeight();
// 勾股定理 & 进一法
int finalRadius = (int) Math.sqrt(w * w + h * h) + 1;
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, startRadius, finalRadius);
myView.setVisibility(View.VISIBLE);
anim.setDuration(durationMills);
anim.start();
}
/**
* 由满向中间收缩,直到隐藏。
*/
@SuppressLint("NewApi")
public static void hide(final View myView, float endRadius, long durationMills) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
myView.setVisibility(View.INVISIBLE);
return;
}
int cx = (myView.getLeft() + myView.getRight()) / 2;
int cy = (myView.getTop() + myView.getBottom()) / 2;
int w = myView.getWidth();
int h = myView.getHeight();
// 勾股定理 & 进一法
int initialRadius = (int) Math.sqrt(w * w + h * h) + 1;
Animator anim =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, endRadius);
anim.setDuration(durationMills);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
myView.setVisibility(View.INVISIBLE);
}
});
anim.start();
}
/**
* 从指定View开始向四周伸张(伸张颜色或图片为colorOrImageRes), 然后进入另一个Activity,
* 返回至 @thisActivity 后显示收缩动画。
*/
@SuppressLint("NewApi")
public static void startActivityForResult(
final Activity thisActivity, final Intent intent, final Integer requestCode, final Bundle bundle,
final View triggerView, int colorOrImageRes, long durationMills) {
if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.LOLLIPOP) {
thisActivity.startActivity(intent);
return;
}
int[] location = new int[2];
triggerView.getLocationInWindow(location);
final int cx = location[0] + triggerView.getWidth() / 2;
final int cy = location[1] + triggerView.getHeight() / 2;
final ImageView view = new ImageView(thisActivity);
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setImageResource(colorOrImageRes);
final ViewGroup decorView = (ViewGroup) thisActivity.getWindow().getDecorView();
int w = decorView.getWidth();
int h = decorView.getHeight();
decorView.addView(view, w, h);
// 计算中心点至view边界的最大距离
int maxW = Math.max(cx, w - cx);
int maxH = Math.max(cy, h - cy);
final int finalRadius = (int) Math.sqrt(maxW * maxW + maxH * maxH) + 1;
Animator
anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, 0, finalRadius);
int maxRadius = (int) Math.sqrt(w * w + h * h) + 1;
// 若使用默认时长,则需要根据水波扩散的距离来计算实际时间
if (durationMills == PERFECT_MILLS) {
// 算出实际边距与最大边距的比率
double rate = 1d * finalRadius / maxRadius;
// 水波扩散的距离与扩散时间成正比
durationMills = (long) (PERFECT_MILLS * rate);
}
final long finalDuration = durationMills;
anim.setDuration(finalDuration);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if (requestCode == null)
thisActivity.startActivity(intent);
else if (bundle == null)
thisActivity.startActivityForResult(intent, requestCode);
else
thisActivity.startActivityForResult(intent, requestCode, bundle);
// 默认渐隐过渡动画.
thisActivity.overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
// 默认显示返回至当前Activity的动画.
triggerView.postDelayed(new Runnable() {
@Override
public void run() {
Animator anim =
ViewAnimationUtils.createCircularReveal(view, cx, cy, finalRadius, 0);
anim.setDuration(finalDuration);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
try {
decorView.removeView(view);
} catch (Exception e) {
e.printStackTrace();
}
}
});
anim.start();
}
}, 1000);
}
});
anim.start();
}
/*下面的方法全是重载,用简化上面方法的构建*/
public static void startActivityForResult(
Activity thisActivity, Intent intent, Integer requestCode, View triggerView, int colorOrImageRes) {
startActivityForResult(thisActivity, intent, requestCode, null, triggerView, colorOrImageRes, PERFECT_MILLS);
}
public static void startActivity(
Activity thisActivity, Intent intent, View triggerView, int colorOrImageRes, long durationMills) {
startActivityForResult(thisActivity, intent, null, null, triggerView, colorOrImageRes, durationMills);
}
public static void startActivity(
Activity thisActivity, Intent intent, View triggerView, int colorOrImageRes) {
startActivity(thisActivity, intent, triggerView, colorOrImageRes, PERFECT_MILLS);
}
public static void startActivity(Activity thisActivity, Class<?> targetClass, View triggerView, int colorOrImageRes) {
startActivity(thisActivity, new Intent(thisActivity, targetClass), triggerView, colorOrImageRes, PERFECT_MILLS);
}
public static void show(View myView) {
show(myView, MINI_RADIUS, PERFECT_MILLS);
}
public static void hide(View myView) {
hide(myView, MINI_RADIUS, PERFECT_MILLS);
}
}
2、DateUtil.java
import android.support.annotation.Nullable;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import static java.lang.System.currentTimeMillis;
/**
* Created on 2019/4/18 19:19
*
* @author Q.PeterGuo
* @version 1.0.0
* @Description
*/
public class DateUtil {
/**
* 获取当前日期
* @return
*/
public static String getCurrentDate() {
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
return df.format(new Date());
}
/**
* 获取当前日期
* @return
*/
public static String getTomorrowDate() {
SimpleDateFormat df = new SimpleDateFormat("yyyyMMdd");
return String.valueOf(Integer.valueOf(df.format(new Date())) + 1);
}
/**
* 获取当前日期字符串
* @return
*/
public static String getCurrentDateString() {
SimpleDateFormat df = new SimpleDateFormat("yyyy年MM月dd日");
return df.format(new Date());
}
/**
* 获取当前年
* @return
*/
public static int getCurrentYear() {
Calendar cal=Calendar.getInstance();
return cal.get(Calendar.YEAR);
}
/**
* 获取当前月
* @return
*/
public static int getCurrentMonth() {
Calendar cal=Calendar.getInstance();
return cal.get(Calendar.MONTH);
}
/**
* 获取当前日
* @return
*/
public static int getCurrentDay() {
Calendar cal=Calendar.getInstance();
return cal.get(Calendar.DATE);
}
/**
* 切割标准时间
* @param time
* @return
*/
@Nullable
public static String subStandardTime(String time) {
int idx = time.indexOf(".");
if (idx > 0) {
return time.substring(0, idx).replace("T"," ");
}
return null;
}
/**
* 将时间戳转化为字符串
* @param showTime
* @return
*/
public static String formatTime2String(long showTime) {
return formatTime2String(showTime,false);
}
public static String formatTime2String(long showTime , boolean haveYear) {
String str = "";
long distance = currentTimeMillis()/1000 - showTime;
if(distance < 300){
str = "刚刚";
}else if(distance >= 300 && distance < 600){
str = "5分钟前";
}else if(distance >= 600 && distance < 1200){
str = "10分钟前";
}else if(distance >= 1200 && distance < 1800){
str = "20分钟前";
}else if(distance >= 1800 && distance < 2700){
str = "半小时前";
}else if(distance >= 2700){
Date date = new Date(showTime * 1000);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
str = formatDateTime(sdf.format(date) , haveYear);
}
return str;
}
public static String formatDate2String(String time) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if(time == null){
return "未知";
}
try {
long createTime = format.parse(time).getTime() / 1000;
long currentTime = currentTimeMillis() / 1000;
if (currentTime - createTime - 24 * 3600 > 0) { //超出一天
return (currentTime - createTime) / (24 * 3600) + "天前";
} else {
return (currentTime - createTime) / 3600 + "小时前";
}
} catch (ParseException e) {
e.printStackTrace();
}
return "未知";
}
public static String formatDateTime(String time ,boolean haveYear) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if(time == null){
return "";
}
Date date;
try {
date = format.parse(time);
} catch (ParseException e) {
e.printStackTrace();
return "";
}
Calendar current = Calendar.getInstance();
Calendar today = Calendar.getInstance();
today.set(Calendar.YEAR, current.get(Calendar.YEAR));
today.set(Calendar.MONTH, current.get(Calendar.MONTH));
today.set(Calendar.DAY_OF_MONTH, current.get(Calendar.DAY_OF_MONTH));
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
Calendar yesterday = Calendar.getInstance();
yesterday.set(Calendar.YEAR, current.get(Calendar.YEAR));
yesterday.set(Calendar.MONTH, current.get(Calendar.MONTH));
yesterday.set(Calendar.DAY_OF_MONTH, current.get(Calendar.DAY_OF_MONTH)-1);
yesterday.set(Calendar.HOUR_OF_DAY, 0);
yesterday.set(Calendar.MINUTE, 0);
yesterday.set(Calendar.SECOND, 0);
current.setTime(date);
if(current.after(today)){
return "今天 "+time.split(" ")[1];
}else if(current.before(today) && current.after(yesterday)){
return "昨天 "+time.split(" ")[1];
}else{
if(haveYear) {
int index = time.indexOf(" ");
return time.substring(0,index);
}else {
int yearIndex = time.indexOf("-")+1;
int index = time.indexOf(" ");
return time.substring(yearIndex,time.length()).substring(0,index);
}
}
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/rlv"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_calender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="20dp"
android:background="@color/fab_bg"
android:src="@mipmap/ic_fab_calendar"
app:borderWidth="0dp" />
</FrameLayout>
activity_calendar.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".CalendarActivity">
<com.prolificinteractive.materialcalendarview.MaterialCalendarView xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/view_calender"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:mcv_selectionColor="@color/colorPrimary"
app:mcv_showOtherDates="all" />
<TextView
android:id="@+id/tv_calender_enter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:layout_margin="20dp"
android:text="确定"
android:textColor="@color/colorPrimary" />
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private RecyclerView mRlv;
private FloatingActionButton mFabCalender;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mRlv = (RecyclerView) findViewById(R.id.rlv);
mFabCalender = (FloatingActionButton) findViewById(R.id.fab_calender);
mFabCalender.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
default:
break;
case R.id.fab_calender:
Intent intent = new Intent();
intent.setClass(MainActivity.this, CalendarActivity.class);
CircularAnimUtil.startActivity(MainActivity.this, intent, mFabCalender, R.color.colorPrimary);
break;
}
}
}
CalendarActivity.java
public class CalendarActivity extends AppCompatActivity implements View.OnClickListener {
private MaterialCalendarView mViewCalender;
/**
* 确定
*/
private TextView mTvCalenderEnter;
CalendarDay mDate;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calendar);
initView();
initEventAndData();
}
private void initView() {
mViewCalender = (MaterialCalendarView) findViewById(R.id.view_calender);
mTvCalenderEnter = (TextView) findViewById(R.id.tv_calender_enter);
mTvCalenderEnter.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
default:
break;
case R.id.tv_calender_enter:
finish();
break;
}
}
public void initEventAndData() {
mViewCalender.state().edit()
.setFirstDayOfWeek(Calendar.WEDNESDAY)
.setMinimumDate(CalendarDay.from(2013, 5, 20))
.setMaximumDate(CalendarDay.from(DateUtil.getCurrentYear(), DateUtil.getCurrentMonth(), DateUtil.getCurrentDay()))
.setCalendarDisplayMode(CalendarMode.MONTHS)
.commit();
mViewCalender.setOnDateChangedListener(new OnDateSelectedListener() {
@Override
public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) {
mDate = date;
}
});
}
}
需要加的图片
image.png
需要添加的背景颜色:
<color name="fab_bg">#FF4081</color>
网友评论