自定义可滑动日历
先放上效果图,可左右滑动切换月份,默认会显示当前月份,并且会高亮当前日期。有一个类似iphone日历的按下效果。
一、设计思路
整个控件是一个LinearLayout,在其中分为三个部分:1、最上端显示月份,会随着中间日历的滑动改变,用一个TextView实现。2、接着一行显示星期,用自定义View实现。3、主体显示日期,可以通过左右滑动切换月份。通过ViewPager实现左右滑页,每一页的内容为自定义view。其中日期部分想到了两种思路,一种是将日期填充至GridView,一种是自定义view的方式,本文采用了后者。
二、实现
1、星期部分
这一行是静态的,我是通过一个自定义View实现的,当然也可以放7个TextView,宽度平均分一下就好了。
新建CustomWeekView.java继承自View。
在构造函数中初始化画笔Paint。在设置TextSize的时候,使用了一个固定值乘了一个density,主要是为了适配不同机型不同分辨率的。
private void initPaint() {
float density = getContext().getApplicationContext().getResources().getDisplayMetrics().density;
mTtPaint = new Paint();
mTtPaint.setTextSize(12 * density);
mTtPaint.setColor(Color.GRAY);
mTtPaint.setAntiAlias(true);
}
重写onMeasure(),指定控件的宽和高。调用Math.round()方法将得到的heightSize进行四舍五入取整。高度要确保可以将所有的内容显示出来。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec); //获取宽的尺寸
float heightSize = FontUtil.getFontHeight(mTtPaint);//保证week显示区域可以容下最高的字母
mOneWidth = widthSize / 7;
setMeasuredDimension(widthSize, Math.round(heightSize));
}
重写OnDraw(),在for循环中每次调用Canvas.drawText()进行绘制。
private final String[] WEEK_ARRAY = new String[]{
"日", "一", "二", "三", "四", "五", "六"};
@Override
protected void onDraw(Canvas canvas) {
for(int i = 0; i < WEEK_ARRAY.length; i++){
int len = (int)FontUtil.getFontlength(mTtPaint, WEEK_ARRAY[i]);
int x = i * mOneWidth + (mOneWidth - len) / 2;
canvas.drawText(WEEK_ARRAY[i], x, FontUtil.getFontLeading(mTtPaint), mTtPaint);
}
}
这一块很容易实现,内容也不多,接下来是重点部分了。
2、日期部分
首先确定高度,因为按每行7天计算,有的月份需要5行,有的需要6行,为了统一,我们将整个高度设为每行高度 x 6,这样既能保证任何月份都可显示全,也能避免换页的时候页面高度来回改变。而每行高度设为背景圆圈直径加上间距。接着通过for循环来画这个月所有的日期,如果为当前月,当前日期会画一个背景圈圈,在选择日期时会有一个按下效果。最后在onTouchEvent()中计算这个按下效果。
新建CustomDateView.java,继承自View。
在构造函数中获取一些自定义的属性参数。mMinSlop这个参数可能现在看着有点懵,它的含义会在后面写onTouchEvent()的时候说明。
public CustomDateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
float density = context.getApplicationContext().getResources().getDisplayMetrics().density;
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomDateView, defStyleAttr, 0);
mNormalTextColor = a.getColor(R.styleable.CustomDateView_mTextColorDay, Color.BLACK);
mSelectTextColor = a.getColor(R.styleable.CustomDateView_mSelectTextColor, Color.BLACK);
mCurrentTextColor = a.getColor(R.styleable.CustomDateView_mCurrentTextColor, getResources().getColor(R.color.colorCurrentText));
mTextSize = a.getDimension(R.styleable.CustomDateView_mTextSizeDay, density * 14);
mCurrentBgd = a.getColor(R.styleable.CustomDateView_mCurrentBg, getResources()