為什么要自定義日歷?
在日常的工作中濒生,很多時(shí)候的需求不是一個(gè)默認(rèn)日歷能夠勝任的佩耳,雖然很多時(shí)候可以去GitHub上面搜索相關(guān)的庫,但是總是會(huì)有一些局限性真椿,這個(gè)時(shí)候就想到了自己來寫一個(gè)日歷控件鹃答,這樣又方便還符合自己APP的主題,兩全其美突硝。
廢話不多說测摔,先上圖:
需要使用哪些工具?
1解恰、ViewPager肯定是首要的锋八,因?yàn)槲覀兊娜諝v需要能夠左右滑動(dòng)切換
2、最最重要的當(dāng)然是Calendar啦护盈,它能夠很好的幫助我們獲取需要的時(shí)間
介紹一下Calendar的幾個(gè)重要的方法
1挟纱、set方法:通過名字我們也知道這是一個(gè)賦值的方法,那么怎么使用呢腐宋?
val a = Calendar.getInstance()
//a.set(field:Int,value:Int) 參數(shù)一是我們需要賦值的類型 參數(shù)二是我們需要賦值的值
比方說我現(xiàn)在要把當(dāng)前的日期設(shè)置為1號(hào)
a.set(Calendar.DATE,1) //這樣就把日期改為了1號(hào)
其他的類推就行紊服。
通過設(shè)置我們可以獲得當(dāng)月1號(hào)是星期幾
val week = a.get(Calendar.DAY_OF_WEEK)
這樣我們就知道從哪個(gè)位置開始啦
2檀轨、getActualMaximum:獲取給定日歷字段的可能最大值
我們需要獲取當(dāng)前月最大天數(shù),如果不用這個(gè)方法欺嗤,我們需要去判斷當(dāng)前月是大月還是小月参萄,今年是閏年還是平年,有了這個(gè)方法就不需要啦
val a = Calendar.getInstance()
val days = a.getActualMaximum(Calendar.DATE)
3煎饼、add方法:添加
這個(gè)方法也是很實(shí)用的一個(gè)方法讹挎,比方說我們現(xiàn)在是1號(hào)我需要知道2號(hào)的時(shí)間戳,最笨的方法當(dāng)然是拿之前的時(shí)間戳+24*3600吆玖,有了add方法就不需要了筒溃,我們只需要
a.add(Calendar.DATE, 1)
這樣就把時(shí)間戳往后加了一天,是不是很方便衰伯。
Calendar里面還有一個(gè)同類的方法roll
a.roll(Calendar.DATE,1)兩者都能往后一天
但是兩個(gè)是有區(qū)別的
比方說現(xiàn)在是2018年1月31號(hào)
a.add(Calendar.DATE, 1)得出的會(huì)是2018年2月1號(hào)
而
a.roll(Calendar.DATE,1)得出的會(huì)是2018年1月1號(hào)
也就是說add會(huì)影響整個(gè)時(shí)間戳铡羡,而roll只會(huì)影響當(dāng)前這個(gè)量級(jí)
現(xiàn)在我們知道了1號(hào)需要的位置和總天數(shù)积蔚,那么數(shù)據(jù)源就有了
val mDatas = ArrayList()
for (i in 1 until getWeekOfFirstDayInMonth()) {
????????mDatas.add(DatePickerBean2(0, 0))
}
val b = Calendar.getInstance()
b.timeInMillis = timeMillis.toLong() * 1000
b.set(Calendar.DATE, 1)
for (i in 0 until getDaysOfMonth(timeMillis)) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mDatas.add(DatePickerBean2((b.timeInMillis / 1000).toInt(), 0))
b.add(Calendar.DATE, 1)
}
一個(gè)簡單的日歷就有了意鲸,通過Calendar類,我們可以很方便的得到我們想要的數(shù)據(jù)
class DatePickerDialog2 : BaseActivity() {
private var timeMillis = 0
private var mViews = ArrayList()
private var pAdapter: MyAdapter? = null
private var isStart = 0
private var isEnd = 0
companion object {
const val REQUEST_CODE = 1718
fun show(context: Activity) {
val intent = Intent(context, DatePickerDialog2::class.java) context.startActivityForResult(intent, REQUEST_CODE)
}
}
?override fun bindlayout(): Int = R.layout.fragment_date_picker2
override fun initListener() {
tvPre.setOnClickListener {
if (mPager.currentItem > 0) {
mPager.setCurrentItem(mPager.currentItem - 1, true)
}
}
tvNext.setOnClickListener {
mPager.setCurrentItem(mPager.currentItem + 1, true)
}
tvCancel.setOnClickListener { finish() }
tvConfirm.setOnClickListener {
if (isStart == 0) {
toast("請(qǐng)選擇開始日期") return@setOnClickListener
}
if (isEnd == 0) {
toast("請(qǐng)選擇結(jié)束日期")
return@setOnClickListener
}
val intent = Intent()
intent.putExtra("start", isStart)
intent.putExtra("end", isEnd)
setResult(Activity.RESULT_OK, intent)
finish()
}
}
override fun init() {
timeMillis = (Calendar.getInstance().timeInMillis / 1000).toInt() tvDate.bindText(TimeUtils.formatDate("yyyy年MM月", timeMillis.toString())) initAdapter()
mPager.addOnPageChangeListener(object :ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) { tvDate.bindText(TimeUtils.formatDate("yyyy年MM月",mViews[position].timeMillis.toString()))
if (position == mViews.size - 1) {
val a = Calendar.getInstance()
a.timeInMillis = timeMillis.toLong() * 1000
a.add(Calendar.MONTH, 1)
timeMillis = (a.timeInMillis / 1000).toInt()
initAdapter()
}
}
}) }
private fun initAdapter() {
val mDatas = ArrayList()
for (i in 1 until getWeekOfFirstDayInMonth()) {
mDatas.add(DatePickerBean2(0, 0))
}
val b = Calendar.getInstance()
b.timeInMillis = timeMillis.toLong() * 1000
b.set(Calendar.DATE, 1)
for (i in 0 until getDaysOfMonth(timeMillis)) { mDatas.add(DatePickerBean2((b.timeInMillis / 1000).toInt(), 0))
b.add(Calendar.DATE, 1)
}
val aadapter = DatePickerAdapter2(this@DatePickerDialog2, mDatas)
val contents = RecyclerView(this@DatePickerDialog2)
contents.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
contents.apply {
layoutManager = GridLayoutManager(this@DatePickerDialog2, 7) setHasFixedSize(true)
adapter = aadapter
}
aadapter.setOnItemClickListener {
when (mDatas[it].selectType) {
0 ->
{
if (isStart == 0) {
if (isEnd == 0 || mDatas[it].timeMillis < isEnd) {
mDatas[it].selectType = 1 isStart = mDatas[it].timeMillis
} else {
toast("開始日期不能在結(jié)束日期之后哦")
}
} else if (isEnd == 0) {
if (isStart == 0 || isStart < mDatas[it].timeMillis) {
mDatas[it].selectType = 2
isEnd = mDatas[it].timeMillis
} else {
toast("結(jié)束日期不能在開始日期之前哦")
}
}
}
1 -> {
mDatas[it].selectType = 0
isStart = 0
}
2 -> {
mDatas[it].selectType = 0
isEnd = 0
}
}
aadapter.refresh(mDatas).notifyItemChanged(it)
}
if (pAdapter == null) {
pAdapter = MyAdapter()
mViews.add(MyView(contents, timeMillis))
mPager.adapter = pAdapter
if (mPager.currentItem == mViews.size - 1) {
val a = Calendar.getInstance()
a.timeInMillis = timeMillis.toLong() * 1000
a.add(Calendar.MONTH, 1)
timeMillis = (a.timeInMillis / 1000).toInt()
initAdapter()
}
} else {
mViews.add(MyView(contents, timeMillis))
mPager.adapter.notifyDataSetChanged()
}
}
private inner class MyAdapter : PagerAdapter() {
override fun isViewFromObject(view: View?, obj: Any?): Boolean = view == obj
override fun getCount(): Int = mViews.size
override fun instantiateItem(container: ViewGroup, position: Int): Any { container.addView(mViews[position].view)
return mViews[position].view }
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any?) { container.removeView(mViews[position].view)
}
}
private fun getWeekOfFirstDayInMonth(): Int {
val a = Calendar.getInstance()
a.timeInMillis = timeMillis.toLong() * 1000
a.set(Calendar.DATE, 1)
return a.get(Calendar.DAY_OF_WEEK)
}
data class MyView(val view: View, val timeMillis: Int)
private fun getDaysOfMonth(timeMillis: Int): Int {
val a = Calendar.getInstance()
a.timeInMillis = timeMillis.toLong() * 1000
return a.getActualMaximum(Calendar.DATE)
}
}