参考了一些网上的资料,针对自己需求做了一些修改。没有难点,只是细节特别多。
package xxx.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
/**
* 自定义日历控件
* Created with Android Studio
* Author:
* Date:2017/12/21
*/
public class MyCalendar extends View {
private static final int SINGLE_SELECT_TYPE = 1;//单选模式
private static final int DOUBLE_SELECT_TYPE = 2;//多选模式
public static final String FORMAT_DATE_DIVIDE = "/";
private static final int RANGE_START = 1;
private static final int RANGE_END = 2;
private static final int RANGE_INSIDE = 3;
private static final int RANGE_OUTSIDE = 4;
private int mTitleTextColor;//标题的颜色
private int mSubTitleTextColor;//小标题的颜色
private float mTitleTextSize;//标题的字体大小
private float mSubTitleTextSize;//小标题的字体大小
private int mTitleArrowLeftId, mTitleArrowRightId;
private float mMonthHorizontalSpace;
private float mTitleVerticalSpac;
private float mSubTitleVerticalSpac;
private int mTextColorWeek;//星期的颜色
private float mTextSizeWeek;//星期的字体大小
private int mPastDayTxtColor;//过去的日期文本的颜色
private int mDayTextColor;//日期文本的颜色
private float mTextSizeDay;//日期文本大小
private int mSelectTextColor;//选中的文本的颜色
private int mSelectBgColor;//选中背景
private int mSelectRangeBgColor;//选中区间背景色
private float mSelectRadius;//日期圆形背景的半径
private float mLineSpac;//行间距
private Paint mPaint = new Paint();//文字画笔
private Paint mBgPaint = new Paint();//背景画笔
private Paint mArrowPaint = new Paint();//画箭头画笔
private float mTitleHeight;//顶部标题高度
private float mWeekHeight;//星期高度
private float mSubTitleHeight;//年月小标题高度
private float mDayHeight;//日期高度
private float oneHeight;//一行日期的高度,包含间距
private int mColumnWidth;//每列宽度
private Date mUpdateMonthDate; //当前的月份
private boolean isCurrentMonth;//展示的月份是否是当前月
private int mCurrentDay;//当前日
private int mUpdateYear;//当前日历所在年份
private int mUpdateMonth;//当前日历所在月份
private int mLastSelectDay;//上一次选中的日期(避免造成重复回调请求)
private int mSelectDay;//选中的日期
private int mDayOfMonth;//月份天数
private int mFirstDayIdx;//当月第一天位置索引,第一天是不同星期,起点也就不同
private int mFirstLineNum, mLastLineNum; //第一行、最后一行能展示多少日期
private int mLineNum;//日期行数
private int mArrowLeftStart;//左箭头响应触摸的起始位置
private int mArrowRightStart;//右箭头响应触摸的起始位置
private int mArrowWidth;//箭头图标宽度
private String[] mWeekArray = new String[]{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
private long mStartMills;//选中区域的起始点
private long mEndMills;//选中区域的结束点
private IClickListener mListener;
private boolean showTitle;//是否显示标题
private boolean showWeek;//是否显示星期
private boolean showSubTitle;//是否显示年月小标题
private float mPadTop, mPadBottom;
private GestureDetector mGestureDetector;
private int mType = SINGLE_SELECT_TYPE;
public MyCalendar(Context context) {
this(context, null);
}
public MyCalendar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyCalendar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context
.obtainStyledAttributes(attrs, R.styleable.MyCalendar, defStyleAttr, 0);
mTitleArrowLeftId = a.getResourceId(R.styleable.MyCalendar_arrowLeftResId, 0);
showTitle = a.getBoolean(R.styleable.MyCalendar_showTitle, true);
showWeek = a.getBoolean(R.styleable.MyCalendar_showWeek, true);
showSubTitle = a.getBoolean(R.styleable.MyCalendar_showSubTitle, false);
mTitleArrowRightId = a.getResourceId(R.styleable.MyCalendar_arrowRightResId, 0);
mMonthHorizontalSpace = a.getDimension(R.styleable.MyCalendar_titleHozSpace, 20);
mTitleVerticalSpac = a.getDimension(R.styleable.MyCalendar_titleVerticalSpace, 20);
mSubTitleVerticalSpac = a
.getDimension(R.styleable.MyCalendar_subTitleVerticalSpace, 20);
mTitleTextColor = a.getColor(R.styleable.MyCalendar_titleTextColor, Color.BLACK);
mSubTitleTextColor = a.getColor(R.styleable.MyCalendar_subTitleTextColor, Color.BLACK);
mTitleTextSize = a.getDimension(R.styleable.MyCalendar_titleTextSize, 100);
mPadTop = a.getDimension(R.styleable.MyCalendar_padTop, 10);
mPadBottom = a.getDimension(R.styleable.MyCalendar_padBottom, 10);
mSubTitleTextSize = a.getDimension(R.styleable.MyCalendar_subTitleTextSize, 100);
mTextColorWeek = a.getColor(R.styleable.MyCalendar_weekTextColor, Color.BLACK);
mTextSizeWeek = a.getDimension(R.styleable.MyCalendar_weekTextSize, 70);
mDayTextColor = a.getColor(R.styleable.MyCalendar_dayTextColor, Color.GRAY);
mPastDayTxtColor = a.getColor(R.styleable.MyCalendar_pastDayTextColor, Color.GRAY);
mTextSizeDay = a.getDimension(R.styleable.MyCalendar_dayTextSize, 70);
mSelectTextColor = a.getColor(R.styleable.MyCalendar_selectTextColor, Color.YELLOW);
mSelectBgColor = a.getColor(R.styleable.MyCalendar_selectBgColor, Color.YELLOW);
mSelectRangeBgColor = a.getColor(R.styleable.MyCalendar_selectRangeBgColor, Color.YELLOW);
mSelectRadius = a.getDimension(R.styleable.MyCalendar_selectRadius, 20);
mLineSpac = a.getDimension(R.styleable.MyCalendar_daylineSpace, 20);
a.recycle();
init();
}
public void setType(int type) {
mType = type;
}
/** 计算相关常量,构造方法中调用 */
private void init() {
mGestureDetector = new GestureDetector(getContext(), new GestureCallback());
mPaint.setAntiAlias(true); //抗锯齿
mBgPaint.setAntiAlias(true); //抗锯齿
mPaint.setTextSize(mTitleTextSize);
mTitleHeight = getFontHeight(mPaint) + 2 * mTitleVerticalSpac;//标题高度
mPaint.setTextSize(mTextSizeWeek);
mWeekHeight = getFontHeight(mPaint);//星期高度
mPaint.setTextSize(mSubTitleTextSize);
mSubTitleHeight = getFontHeight(mPaint) + 2 * mSubTitleVerticalSpac;//小标题高度
mPaint.setTextSize(mTextSizeDay);
mDayHeight = getFontHeight(mPaint);//单行日期高度
oneHeight = mLineSpac + mDayHeight;/*每行高度 = 行间距 + 日期字体高度*/
updateMonth(new Date());//默认当前月份
}
private void computeRowsAndColumns(Calendar calendar) {
mUpdateYear = calendar.get(Calendar.YEAR);
mUpdateMonth = calendar.get(Calendar.MONTH) + 1;
mDayOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);/*该月天数*/
mFirstDayIdx = calendar.get(Calendar.DAY_OF_WEEK) - 1;/*第一行1号显示在什么位置(星期几)*/
mLineNum = 1;
mFirstLineNum = 7 - mFirstDayIdx;/*第一行能展示的天数*/
mLastLineNum = 0;/*最后一行能展示的天数*/
int remainDays = mDayOfMonth - mFirstLineNum;
while (remainDays > 7) {
mLineNum++;
remainDays -= 7;
}
if (remainDays > 0) {
mLineNum++;
mLastLineNum = remainDays;
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);//获取宽的尺寸,宽度 = 填充父窗体
mColumnWidth = widthSize / 7;
int height = (int) (mLineNum * oneHeight + mPadTop + mPadBottom);
height = (int) computeY(height);
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), height);
}
@Override
protected void onDraw(Canvas canvas) {
if (showTitle) {
drawTitle(canvas);
}
if (showWeek) {
drawWeek(canvas);
}
if (showSubTitle) {
drawSubTitle(canvas);
}
drawDay(canvas);
}
/** 画年月小标题 */
private void drawSubTitle(Canvas canvas) {
mPaint.setTextSize(mSubTitleTextSize);
mPaint.setColor(mSubTitleTextColor);
float titleStart = getWidth() / 14;
float y = mSubTitleVerticalSpac + getFontLeading(mPaint);
if (showTitle) {
y += mTitleHeight;
}
if (showWeek) {
y += mWeekHeight;
}
String subTitle = getMonthYear(mUpdateMonthDate);
canvas.drawText(subTitle, titleStart, y, mPaint);//画年月标题
}
/** 绘制年月、左右箭头 */
private void drawTitle(Canvas canvas) {
mPaint.setTextSize(mTitleTextSize);
mPaint.setColor(mTitleTextColor);
float textLen = getFontlength(mPaint, getMonthStr(mUpdateMonthDate));
float titleStart = (getWidth() - textLen) / 2;
float y = mPadTop + mTitleVerticalSpac + getFontLeading(mPaint);
canvas.drawText(getMonthStr(mUpdateMonthDate), titleStart, y, mPaint);//画年月标题
if (mTitleArrowLeftId != 0) {//画左箭头
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), mTitleArrowLeftId);
int arrowHeight = bitmap.getHeight();
mArrowWidth = bitmap.getWidth();
mArrowLeftStart = (int) (titleStart - 2 * mMonthHorizontalSpace - mArrowWidth);
float left = mArrowLeftStart + mMonthHorizontalSpace;
float top = mPadTop + (mTitleHeight - arrowHeight) / 2;
canvas.drawBitmap(bitmap, left, top, mArrowPaint);
}
if (mTitleArrowRightId != 0) {//画右箭头
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), mTitleArrowRightId);
int arrowHeight = bitmap.getHeight();
mArrowRightStart = (int) (titleStart + textLen);
float left = mArrowRightStart + mMonthHorizontalSpace;
float top = mPadTop + (mTitleHeight - arrowHeight) / 2;
canvas.drawBitmap(bitmap, left, top, mArrowPaint);
}
}
/** 绘制星期 */
private void drawWeek(Canvas canvas) {
mPaint.setTextSize(mTextSizeWeek);
mPaint.setColor(mTextColorWeek);
float y = mPadTop + getFontLeading(mPaint);
if (showTitle) {
y += mTitleHeight;
}
for (int i = 0; i < mWeekArray.length; i++) {
int len = (int) getFontlength(mPaint, mWeekArray[i]);
float x = i * mColumnWidth + (mColumnWidth - len) / 2;
canvas.drawText(mWeekArray[i], x, y, mPaint);
}
}
/** 绘制日期 */
private void drawDay(Canvas canvas) {
float lineTop = computeY(mPadTop);//某行开始绘制的Y坐标,第一行开始的y坐标为标题高度+星期部分高度
for (int line = 0; line < mLineNum; line++) {
if (line == 0) {//第一行
drawDay(canvas, lineTop, mFirstLineNum, 0, mFirstDayIdx);
} else if (line == mLineNum - 1) {//最后一行
lineTop += oneHeight;
int overDay = mFirstLineNum + (line - 1) * 7;
drawDay(canvas, lineTop, mLastLineNum, overDay, 0);
} else {//满行
lineTop += oneHeight;
int overDay = mFirstLineNum + (line - 1) * 7;
drawDay(canvas, lineTop, 7, overDay, 0);
}
}
}
private float computeY(float y) {
if (showTitle) {
y += mTitleHeight;
}
if (showWeek) {
y += mWeekHeight;
}
if (showSubTitle) {
y += mSubTitleHeight;
}
return y;
}
/**
* 绘制某一行的日期
*
* @param top 顶部坐标
* @param count 此行需要绘制的日期数量
* @param overDay 已经绘制过的日期,从overDay+1开始绘制
* @param startIndex 此行第一个日期的星期索引
*/
private void drawDay(Canvas canvas, float top, int count, int overDay, int startIndex) {
mPaint.setTextSize(mTextSizeDay);
float dayTextLeading = getFontLeading(mPaint);
for (int i = 0; i < count; i++) {
int left = (startIndex + i) * mColumnWidth;
int day = (overDay + i + 1);
float centerX = left + mColumnWidth / 2;
float centerY = top + mLineSpac + mDayHeight / 2;
drawSelectRange(canvas, centerX, centerY, day, left);
String dayStr = day + "";
int dayTxtLen = (int) getFontlength(mPaint, dayStr);
int x = left + (mColumnWidth - dayTxtLen) / 2;
canvas.drawText(dayStr, x, top + mLineSpac + dayTextLeading, mPaint);
}
}
/** 画选中状态 */
private void drawSelectRange(Canvas canvas, float centerX, float centerY, int day, int left) {
switch (beyondRange(day)) {
case RANGE_START:
if (mEndMills > mStartMills) {
mBgPaint.setColor(mSelectRangeBgColor);
Path startPath = new Path();
float startY = centerY + mSelectRadius;
startPath.moveTo(centerX, startY);
RectF startRect = new RectF(centerX - mSelectRadius, centerY - mSelectRadius,
centerX + mSelectRadius, centerY + mSelectRadius);
startPath.arcTo(startRect, 90, 180);
startPath.lineTo(centerX + mColumnWidth / 2, centerY - mSelectRadius);
startPath.lineTo(centerX + mColumnWidth / 2, centerY + mSelectRadius);
startPath.close();
canvas.drawPath(startPath, mBgPaint);
}
mBgPaint.setColor(mSelectBgColor);
canvas.drawCircle(centerX, centerY, mSelectRadius, mBgPaint);
mPaint.setColor(mSelectTextColor);
break;
case RANGE_END:
mBgPaint.setColor(mSelectRangeBgColor);
Path endPath = new Path();
float endY = centerY - mSelectRadius;
endPath.moveTo(centerX, endY);
RectF endRect = new RectF(centerX - mSelectRadius, centerY - mSelectRadius,
centerX + mSelectRadius, centerY + mSelectRadius);
endPath.arcTo(endRect, -90, 180);
endPath.lineTo(centerX - mColumnWidth / 2, centerY + mSelectRadius);
endPath.lineTo(centerX - mColumnWidth / 2, centerY - mSelectRadius);
endPath.close();
canvas.drawPath(endPath, mBgPaint);
mBgPaint.setColor(mSelectBgColor);
canvas.drawCircle(centerX, centerY, mSelectRadius, mBgPaint);
mPaint.setColor(mSelectTextColor);
break;
case RANGE_INSIDE:
mBgPaint.setColor(mSelectRangeBgColor);
RectF rect = new RectF(left, centerY - mSelectRadius, left + mColumnWidth,
centerY + mSelectRadius);
canvas.drawRect(rect, mBgPaint);
mPaint.setColor(mSelectTextColor);
break;
default:
mPaint.setColor(mDayTextColor);
if (isCurrentMonth && day < mCurrentDay) {/*不可选的日期颜色(今天之前的日期),按需求展示本月及之后12个月份,那么当前月为最小的月份,如果不是当前月,那么一定是今天之后的日期*/
mPaint.setColor(mPastDayTxtColor);
} else {//普通日期文字颜色
mPaint.setColor(mDayTextColor);
}
if (mSelectDay == day) {//绘制选中的日期
mPaint.setColor(mSelectTextColor);
mBgPaint.setColor(mSelectBgColor);
canvas.drawCircle(centerX, centerY, mSelectRadius, mBgPaint);
}
break;
}
}
/** 相对于选中区间的位置(在区间内、区间外、区间头部、区间尾部) */
private int beyondRange(int day) {
Date todayDate = dayStr2Date(
mUpdateYear + FORMAT_DATE_DIVIDE + mUpdateMonth + FORMAT_DATE_DIVIDE + day);
if (todayDate == null) {
return RANGE_OUTSIDE;
}
long todayMills = todayDate.getTime();
if (mStartMills == todayMills) {
return RANGE_START;
} else if (mStartMills > todayMills) {
return RANGE_OUTSIDE;
} else {
if (mEndMills < todayMills) {
return RANGE_OUTSIDE;
} else if (mEndMills == todayMills) {
return RANGE_END;
} else {
return RANGE_INSIDE;
}
}
}
/** 获取月份标题 */
private String getMonthStr(Date month) {
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM", Locale.getDefault());
return df.format(month);
}
private Date str2Date(String str) {
try {
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM", Locale.getDefault());
return df.parse(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private Date dayStr2Date(String str) {
try {
SimpleDateFormat df = new SimpleDateFormat("yyyy/MM/dd", Locale.getDefault());
return df.parse(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
/** 焦点滑动 */
private void touchFocusMove(final PointF point, boolean isEndEvent) {
if (isTouchTitle(point)) {//事件在标题上
if (!isEndEvent || mListener == null) {//标题只有在事件结束后才响应
return;
}
if (isTouchLeftArrow(point)) {//点击左箭头
monthChange(-1);
} else if (isTouchRightArrow(point)) {//点击右箭头
monthChange(1);
}
} else if (isTouchDay(point)) {//触摸的是日期
if (!isEndEvent) {
return;
}
touchDay(point, isEndEvent);
}
}
/** 是否触摸的是左箭头 */
private boolean isTouchLeftArrow(final PointF point) {
return point.x >= mArrowLeftStart && point.x < (mArrowLeftStart + 2 * mMonthHorizontalSpace
+ mArrowWidth);
}
/** 是否触摸的是右箭头 */
private boolean isTouchRightArrow(final PointF point) {
return point.x > mArrowRightStart && point.x < (mArrowRightStart + 2 * mMonthHorizontalSpace
+ mArrowWidth);
}
/** 是否触摸的是标题(年月、箭头) */
private boolean isTouchTitle(final PointF point) {
if (!showTitle) {
return false;
}
return point.y > mPadTop && point.y <= mPadTop + mTitleHeight;
}
/** 是否触摸的是日期 */
private boolean isTouchDay(final PointF point) {
return point.y > computeY(mPadTop);
}
/** 事件点在 日期区域 范围内 */
private void touchDay(final PointF point, boolean isEndEvent) {
float top = computeY(mPadTop);
float diffY = point.y - top;
int focusLine = (int) (diffY / oneHeight);
if (diffY % oneHeight > 0) {
focusLine++;
}
boolean availability = focusLine <= mLineNum;//触摸是否在日期范围内
if (availability) {
int xIdx = (int) Math.ceil(point.x / mColumnWidth);//根据X坐标找到具体的焦点日期
if (xIdx <= 0) {
xIdx = 1;
}
if (xIdx > 7) {
xIdx = 7;
}
if (focusLine == 1) {//第一行
if (xIdx <= mFirstDayIdx) {//到开始空位
updateSelectedDay(mSelectDay, true);
} else {
updateSelectedDay(xIdx - mFirstDayIdx, isEndEvent);
}
} else if (focusLine == mLineNum) {//最后一行
if (xIdx > mLastLineNum) {//到结尾空位
updateSelectedDay(mSelectDay, true);
} else {
updateSelectedDay(mFirstLineNum + (focusLine - 2) * 7 + xIdx, isEndEvent);
}
} else {
updateSelectedDay(mFirstLineNum + (focusLine - 2) * 7 + xIdx, isEndEvent);
}
} else {//超出日期区域后,视为事件结束,响应最后一个选择日期的回调
updateSelectedDay(mSelectDay, true);
}
}
/** 设置选中的日期 */
private void updateSelectedDay(int day, boolean eventEnd) {
if (isCurrentMonth && day < mCurrentDay) {//所在月份是当前月,且触摸的日期是今天之前,则不可选中
return;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(mUpdateMonthDate);
int year = calendar.get(Calendar.YEAR);
int month = calendar.get(Calendar.MONTH) + 1;
Date date = dayStr2Date(year + FORMAT_DATE_DIVIDE + month + FORMAT_DATE_DIVIDE + day);
if (date == null) {
return;
}
if (mType == SINGLE_SELECT_TYPE) {
mSelectDay = day;
invalidate();
if (mListener != null && eventEnd && mLastSelectDay != mSelectDay) {
mLastSelectDay = mSelectDay;
mListener.onDayClick(date.getTime());
}
} else {
if (mStartMills != 0) {
if (date.getTime() < mStartMills) {
mStartMills = date.getTime();
} else {
mEndMills = date.getTime();
}
invalidate();
} /*else {
mStartMills = date.getTime();
invalidate();
}*/
}
}
public void updateSelectedDay(long selectMills) {
if (selectMills == 0) {
return;
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date(selectMills));
mSelectDay = calendar.get(Calendar.DAY_OF_MONTH);
invalidate();
}
/** 月份增减 */
private void monthChange(int change) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(mUpdateMonthDate);
calendar.add(Calendar.MONTH, change);
updateMonth(calendar.getTime());
invalidate();
}
private float getFontlength(Paint paint, String str) {
return paint.measureText(str);
}
/** 返回指定笔的文字高度 */
private float getFontHeight(Paint paint) {
Paint.FontMetrics fm = paint.getFontMetrics();
return fm.descent - fm.ascent;
}
/** 返回指定笔离文字顶部的基准距离 */
private float getFontLeading(Paint paint) {
Paint.FontMetrics fm = paint.getFontMetrics();
return fm.leading - fm.ascent;
}
/** 设置月份 */
public void updateMonth(Date updateMonthDate) {
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
mCurrentDay = calendar.get(Calendar.DAY_OF_MONTH);//当前日期
Date currentMonthDate = dayStr2Date(day2Str(new Date()));//当前月份
mUpdateMonthDate = dayStr2Date(day2Str(updateMonthDate));
if (currentMonthDate != null && currentMonthDate.getTime() == mUpdateMonthDate.getTime()) {
isCurrentMonth = true;
mSelectDay = mCurrentDay;//当月默认选中当前日
} else {
isCurrentMonth = false;
mSelectDay = 0;
}
calendar.setTime(mUpdateMonthDate);
computeRowsAndColumns(calendar);
}
private String day2Str(Date date) {
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd", Locale.getDefault());
return format.format(date);
}
public void clearSelect() {
mSelectDay = 0;
mLastSelectDay = 0;
invalidate();
}
public void setSelectRange(long startMills, long endMills) {
if (startMills > endMills) {
return;
}
mStartMills = startMills;
mEndMills = endMills;
invalidate();
}
public void showWeek(boolean showWeek) {
this.showWeek = showWeek;
invalidate();
}
public void setStartMills(long startMills) {
mStartMills = startMills;
invalidate();
}
public void setEndMills(long endMills) {
mEndMills = endMills;
invalidate();
}
public long getStartMills() {
return mStartMills;
}
public long getEndMills() {
return mEndMills;
}
public boolean isStartMills() {
return mStartMills == 0;
}
public void setOnClickListener(IClickListener listener) {
this.mListener = listener;
}
public class GestureCallback extends GestureDetector.SimpleOnGestureListener {
private PointF mFocusPoint = new PointF();//焦点坐标
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
mFocusPoint.set(e.getX(), e.getY());
touchFocusMove(mFocusPoint, true);
return super.onSingleTapConfirmed(e);
}
@Override
public boolean onDown(MotionEvent e) {
return true;//true,否则无法触发onSingleTap、onFling等方法
}
}
/** Desc 2017*/
public static String getMonthYear(Date date) {
if (date == null) {
date = new Date();
}
long countryId = LocaleManager.Country.ID;
CountryItemInfo country = DefaultCountryManager.getInstance().getCurrentCountryInfo();
if (country != null) {
countryId = country.id;
}
Locale locale = LocaleManager.getLocale(countryId);
DateFormat df = new SimpleDateFormat("MMM", locale);
String month = df.format(date);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int year = calendar.get(Calendar.YEAR);
return month + " " + year;
}
/** Desc 28,2017*/
public static String getMonthDayYear(Date date) {
if (date == null) {
date = new Date();
}
long countryId = LocaleManager.Country.ID;
CountryItemInfo country = DefaultCountryManager.getInstance().getCurrentCountryInfo();
if (country != null) {
countryId = country.id;
}
Locale locale = LocaleManager.getLocale(countryId);
DateFormat df = new SimpleDateFormat("MMM dd,yyyy", locale);
return df.format(date);
}
public interface IClickListener {
void onDayClick(long mills);
}
}
attr.xml
效果图:单选效果、多选效果