(上一篇)//www.greatytc.com/p/2b9bdd5c2949介绍了怎么画星期名。
这部介绍画月的天数。
思路:
1.获得今天的日期,画对应的日期名字下。
2.计算出当前日期左边右边的值,并画出
3.处理一些特殊情况,比如计算的天数不在当前月,两位数和一位数的位置等
**4.按照距离关系,设定点击事件。
实现:
老规矩,重写View
的构造方法以及onMeasure
,onDraw
方法, 为了点击事件重写onTouch
方法.
1.定义需要的变量。
/**
* M paint
*/
private lateinit var mPaint: Paint
private lateinit var cPaint: Paint
/**
* Current 当前天
*/
private var current: Int? = null
/**
* Today 当前日期
*/
private var today: Int by Delegates.notNull()
/**
* Start 开始数字
*/
private var start: Int? = null
/**
* Month 当前月
*/
private var month: Int by Delegates.notNull()
/**
*本年
*/
private var year by Delegates.notNull<Int>()
/**
* Last month max 上月总天数
*/
private var lastMonthMax by Delegates.notNull<Int>()
/**
* Current month max 本月总天数
*/
private var currentMonthMax by Delegates.notNull<Int>()
/**
*负责点击事件的处理。
**/
- 为了处理点击事件,添加接口
/**
* Add on date click listener
* 点击事件
* @constructor Create empty Add on date click listener
*/
interface AddOnDateClickListener {
fun singleClick(position: Int)
}
- 初始化变量。
private fun initView() {
//获取今天的数据
val calendar = Calendar.getInstance()
//时区
calendar.timeZone = TimeZone.getTimeZone("GMT+8")
year = calendar.get(Calendar.YEAR)
//注:月从0开始的。
month = calendar.get(Calendar.MONTH) + 1
//今天
today = calendar.get(Calendar.DAY_OF_MONTH)
//周数
if (current == null) {
//注意:开始是从周日
current =if (calendar.get(Calendar.DAY_OF_WEEK)==7){
0
}else{
calendar.get(Calendar.DAY_OF_WEEK)-1
}
}
//比较周,然后计算出开始日期.
if (start == null) {
start=today- current!! +1
}
//获取上个月的天数。
//如果不再本年。
with(month - 1) {
lastMonthMax = if (this == 0) {
//12月的总数永远是31天,所以不需要从Calendar获取。
31
} else {
getMonthLastDay(year, this)
}
}
//获取本月最大天数.
currentMonthMax = getMonthLastDay(year, month)
mPaint = Paint()
mPaint.textSize = DisplayUtils.dip2px(14F).toFloat()
mPaint.color = Color.parseColor("#3E3E3F")
mPaint.isAntiAlias = true
cPaint = Paint()
cPaint.color = Color.parseColor("#005BAB")
cPaint.isAntiAlias = true
}
- 重写
onMeasure
方法,并且进行Padding
值的运算
//写死宽度,高度最少37dp并且添加左右Padding值。
setMeasuredDimension(
widthMeasureSpec,
(DisplayUtils.dip2px(37F) + DisplayUtils.dip2Px(paddingBottom+paddingTop)).toInt()
)
5.重写onDraw
方法
//index (索引) 0...6, value (值) -1...6(取决于当前的日期)
for ((index, value: Int) in (start!!..start!! + 6).withIndex()) {
mPaint.color = Color.parseColor("#3E3E3F")
//要画的数字(天数,可能是上月的,也可能是下个月的。)
var tempPrintValue = value
//如果是当天,画圆形,画天数文字。
if (current!! - 1 == index) {
//判断
//如果低于本月。
if (value <= 0) {
tempPrintValue = lastMonthMax + value
}
//如果超过本月
if (value > currentMonthMax) {
tempPrintValue = value - currentMonthMax
}
mPaint.color = Color.WHITE
//画园。
canvas?.drawCircle(
(index * width) / 7F + DisplayUtils.dip2px(
if (tempPrintValue > 9) {
31F
} else {
27F
}
),
((height/2).toFloat()),
DisplayUtils.dip2px(12F).toFloat(),
cPaint
)
//描绘天数.
canvas?.drawText(
tempPrintValue.toString(),
(index * width) / 7F + DisplayUtils.dip2px(
if (index.toString().length > 1) {
18F
} else {
23F
}
),
(height/2)+DisplayUtils.dip2Px(5),mPaint
)
} else {
//判断
//如果低于本月。
if (value <= 0) {
tempPrintValue = lastMonthMax + value
mPaint.color = Color.parseColor("#7E7E7E")
}
//如果超过本月
if (value > currentMonthMax) {
tempPrintValue = value - currentMonthMax
mPaint.color = Color.parseColor("#7E7E7E")
}
//描绘天数.
canvas?.drawText(
tempPrintValue.toString(),
(index * width) / 7F + DisplayUtils.dip2px(
if (tempPrintValue.toString().length > 1) {
18F
} else {
23F
}
),
(height/2)+DisplayUtils.dip2Px(5),
// DisplayUtils.dip2px(24F).toFloat(),
mPaint
)
}
}
canvas?.save()
注:onDraw
里面处理了一位数和两位数的时候的圆形的位置。
6.点击事件的处理。
主要思路:把宽度等7分,然后不同的区域给对应的值。
更改当前选定的日期,并且重绘,高亮。
/**
* 点击事件的处理。
*/
override fun onTouchEvent(event: MotionEvent?): Boolean {
val x = event!!.x
//注意:只处理点(down),不处理up,move等,
if (event.action == MotionEvent.ACTION_DOWN) {
when (x.toInt()) {
in 0..width / 7 -> {
this.singleClick(1)
current = 1
}
in width * 1 / 7..width * 2 / 7 -> {
this.singleClick(2)
current = 2
}
in width * 2 / 7..width * 3 / 7 -> {
this.singleClick(3)
current = 3
}
in width * 3 / 7..width * 4 / 7 -> {
this.singleClick(4)
current = 4
}
in width * 4 / 7..width * 5 / 7 -> {
this.singleClick(5)
current = 5
}
in width * 5 / 7..width * 6 / 7 -> {
this.singleClick(6)
current = 6
}
in width * 6 / 7..width -> {
this.singleClick(7)
current = 7
}
}
//参数重新初始化。
initView()
//重绘
postInvalidate()
}
return true
}
- 使用的Utils。
/**
* 得到指定月的天数
*/
private fun getMonthLastDay(year: Int, month: Int): Int {
val a = Calendar.getInstance()
a[Calendar.YEAR] = year
a[Calendar.MONTH] = month - 1
a[Calendar.DATE] = 1 //把日期设置为当月第一天
a.roll(Calendar.DATE, -1) //日期回滚一天,也就是最后一天
return a[Calendar.DATE]
}
/**
* dp转px
*
* @param dipValue
* @return
*/
fun dip2px(dipValue: Float): Int {
val scale: Float = Resources.getSystem().displayMetrics.density
return (dipValue * scale + 0.5f).toInt()
}
/**
*点击事件的处理。
**/
override fun singleClick(position: Int) {
Toast.makeText(context,"选中${start!!+position-1}", Toast.LENGTH_LONG).show()
}
最后跟上一篇的星期名结合。
完美,收工。