廢話不多說(shuō),先直接上最終的效果圖(完整代碼鏈接在底部)
實(shí)現(xiàn)思路
首先缤弦,我們將效果圖實(shí)現(xiàn)的過程坦冠,拆分:
1形耗,將整個(gè)布局進(jìn)行拆分,分別實(shí)現(xiàn)
2辙浑,用系統(tǒng)calendar類實(shí)現(xiàn)數(shù)據(jù)填充
3激涤,附屬數(shù)據(jù)的填充(比如日消費(fèi)什么的)
第一步,界面鋪設(shè)
瞄一眼判呕,就很容易得出該日歷由三個(gè)部分組成倦踢,
a.月份標(biāo)題
b.星期數(shù)
c.日歷數(shù)據(jù)
以下是我的實(shí)現(xiàn)布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp">
<ImageView
android:id="@+id/btn_calendar_pre"
android:layout_width="60dp"
android:layout_height="30dp"
android:layout_centerVertical="true"
android:src="@mipmap/arrow_pre" />
<TextView
android:id="@+id/tv_calendar_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="5月18"
android:textColor="#000000"
android:textSize="20sp" />
<ImageView
android:id="@+id/btn_calendar_next"
android:layout_width="60dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:src="@mipmap/arrow_next" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_weight="1"
android:gravity="center"
android:text="日"
android:textColor="#000"
android:textSize="16sp" />
//..........
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recy_calendar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
效果如下,主要功能在日歷數(shù)據(jù)的展示上面侠草,我采用的是recycleview布局
第二步辱挥,日歷數(shù)據(jù)的填充
private void initData(Context context) {
dateList.clear();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy - MM");
//年月--設(shè)置標(biāo)題欄的數(shù)據(jù)
String dateTitle = sdf.format(mCalendar.getTime());
tvDateTitle.setText(dateTitle);
//表格中的數(shù)據(jù)
Calendar calendar = (Calendar) mCalendar.clone();
calendar.set(Calendar.DAY_OF_MONTH, 1); //設(shè)置時(shí)間到當(dāng)前月份的第一天
//1---代表周日 2---代表周一
int firstDay = calendar.get(Calendar.DAY_OF_WEEK);//獲取日期的偏移量
int preDays = firstDay - 1; //因?yàn)榻菢?biāo)是從0開始的
//僅僅美觀操作,下面代碼可加可不加 效果參見pc系統(tǒng)的日歷月份調(diào)至 2018-4
preDays = preDays == 0 ? 7 : preDays; //為了保證第一行一定是 上個(gè)月+這個(gè)月(可能沒有) 的數(shù)據(jù) ,
//最后一行一定是 這個(gè)月(可能沒有)+下個(gè)月 的數(shù)據(jù)
calendar.add(Calendar.DAY_OF_MONTH, -preDays);//將偏移量移至上個(gè)月边涕,把上個(gè)月的幾天添加到本月的日歷中
int maxDays = 6 * 7;//直接寫死晤碘,6行7列,至于為什么功蜓,請(qǐng)參考pc右下角日歷
ClendarInfo clendarInfo;
Date time = null;
sdf = new SimpleDateFormat("yyyy-MM-dd");
boolean needDoThing = dataMap.size() > 0; //表示當(dāng)月有數(shù)據(jù)
for (int i = 0; i < maxDays; i++) {
time = calendar.getTime();
clendarInfo = new ClendarInfo();
//-------第三步----------添加附屬數(shù)據(jù)開始----------------------------
String key = sdf.format(new Date(time.getYear(), time.getMonth() + 1, time.getDate()));
if (needDoThing && dataMap.containsKey(key)) { //將本月需要做的事添加到集合中,而且的當(dāng)前月份
String thing = dataMap.get(key);
if (!TextUtils.isEmpty(thing))
clendarInfo.setDoThing(thing);
}
//-------第三步----------添加附屬數(shù)據(jù)結(jié)束----------------------------
clendarInfo.setDate(time);
dateList.add(clendarInfo);
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
// Log.i("TAG", "dataMap=" + dataMap.toString());
//將日歷數(shù)據(jù)填充到recycleview中
if (adapter == null) {
adapter = new DateAdapter(context, R.layout.item_calendar_layout, dateList);
adapter.setOnItemClickListener(this);
recyclerView.setAdapter(adapter);
} else {
adapter.notifyDataSetChanged();
}
}
第二步中园爷,主要的要注意的地方是:
a.星期天的角標(biāo)是0,
b.一月份的角標(biāo)是0
c.Calendar.add(Calendar.DAY_OF_MONTH, 1);可以理解為在月份中式撼,參數(shù) 1 表示日期往后挪一天童社,-1 表示往前面挪一天。
Calendar.add(Calendar.MONTH, +1); //當(dāng)前月加1端衰,即下個(gè)月
Calendar.add(Calendar.MONTH, -1);//當(dāng)前月減1,即上個(gè)月
以上方法就是生成日歷數(shù)據(jù)的核心代碼了。代碼的注釋也寫的很詳細(xì)甘改,如果還不清楚旅东,可在文末將完整代碼復(fù)制下來(lái),或者在文本末十艾,下載該博客的demo
第三步抵代,添加附屬數(shù)據(jù)
實(shí)現(xiàn)的主要方法,就是步驟二中的代碼中注釋掉的部分了忘嫉。
至于荤牍,不是當(dāng)前月的日期顯示灰色,當(dāng)天日期標(biāo)紅庆冕,當(dāng)前月黑色顯示康吵,就是在recycleview的adapter中實(shí)現(xiàn)了,這些都很簡(jiǎn)單访递,就寫出來(lái)了晦嵌。
Map<String, String> dataMap = new HashMap<>();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
dataMap.put(sdf.format(new Date(2018-1900, 5, 1)), "吃飯");
dataMap.put(sdf.format(new Date(2018-1900, 5, 11)), "睡覺");
dataMap.put(sdf.format(new Date(2018-1900, 5, 16)), "打豆豆");
dataMap.put(sdf.format(new Date(2018-1900, 5, 21)), "繼續(xù)睡覺");
dataMap.put(sdf.format(new Date(2018-1900, 5, 9)), "來(lái)啊,繼續(xù)浪");
dataMap.put(sdf.format(new Date(2018-1900, 5, 30)), "打豆豆");
clendarView.setDataMap(dataMap);
上面這段代碼是從activity中傳入的附屬數(shù)據(jù),具體情況惭载,要按照需求來(lái)決定旱函,僅僅作為參考。最后附上demo地址