概述:
聽(tīng)過(guò)PullToRefreshListView,聽(tīng)過(guò)PinnedSectionListView,那你應(yīng)該沒(méi)聽(tīng)過(guò)CalendarListView,什么是CalendarListView呢畜号,ListView和Calendar扯上什么關(guān)系呢,我們先來(lái)看下Demo(動(dòng)畫(huà)效果會(huì)稍微有點(diǎn)卡頓,真實(shí)效果會(huì)比較流暢认罩,大家可以到我GitHub下載apk自己試用一下,效果還不錯(cuò)!)续捂。
CalendarListView 是一個(gè)ListView 和 CalendarView 結(jié)合并互相聯(lián)動(dòng)的控件垦垂,日歷可以伸縮擴(kuò)展宦搬,列表可以上拉下沉, 日歷的選擇會(huì)讓ListView 滑動(dòng)到指定的位置劫拗,ListView的滑動(dòng)同時(shí)也會(huì)帶動(dòng)日歷滑到指定位置并能同時(shí)自動(dòng)切換月份间校。如果我們的應(yīng)用涉及到聊天記錄、筆記页慷、訂單記錄憔足、天氣、日?qǐng)?bào)等和時(shí)間關(guān)系比較緊的業(yè)務(wù)場(chǎng)景酒繁,這樣的控件要比簡(jiǎn)單的ListView 來(lái)得更清晰一些滓彰,也更炫一些。如果你喜歡欲逃,可以先收藏很多業(yè)務(wù)場(chǎng)景都可以使用找蜜。
功能簡(jiǎn)介:
可以參照上面的動(dòng)畫(huà),我安裝上面演示的順序說(shuō)明:
1稳析、CalendarListView 的上部分是常規(guī)的日歷模塊洗做,在日歷不收縮的情況下上下滑動(dòng)可以切換月份
2、在日歷不收縮的情況彰居,選擇日歷某一天诚纸,ListView的滑到指定日期的那一條。
3陈惰、在日歷不收縮的情況畦徘,選擇日歷某一天,選完之后抬闯,把ListView往上拉井辆,這時(shí)候會(huì)根據(jù)日歷選中日期(紅色框)的高度,計(jì)算出日歷的滑動(dòng)速率溶握,從而使整體滑到頂部的時(shí)候杯缺,日歷日期選中的那一行是可見(jiàn)的。
4睡榆、在日歷收縮的情況下萍肆,按住日歷往下拉,這時(shí)候和上面一樣經(jīng)過(guò)計(jì)算胀屿,使控件能夠平滑的展開(kāi)塘揣。
5、在日歷執(zhí)行展開(kāi)或者收縮過(guò)程中宿崭,用手在拖動(dòng)中亲铡,如果拖動(dòng)的距離超過(guò)一半放手了,會(huì)有動(dòng)畫(huà)執(zhí)行剩下的下滑或者上拉操作,如果拖動(dòng)沒(méi)有超過(guò)一半奖蔓,會(huì)自動(dòng)回到原來(lái)的位置琅摩。
6、在日歷收縮的情況下锭硼,滑動(dòng)ListView,這時(shí)候日期當(dāng)前ListView的section的日期變化了蜕劝,那么日歷會(huì)自動(dòng)選中當(dāng)前pin住的那個(gè)header的日期檀头,ListView上下滑動(dòng)都會(huì)牽動(dòng)日歷日期的變更(日歷會(huì)上下滑動(dòng)同時(shí)選中header的日期)
7、ListView 往下滑岖沛,到底的時(shí)候會(huì)自動(dòng)觸發(fā)LoadMore操作暑始,當(dāng)從1月份滑到二月份的時(shí)候,日歷會(huì)自動(dòng)切換2月份同時(shí)選中指定的日期婴削。
8廊镜、ListView 往上滑,到最頂部時(shí)候會(huì)自動(dòng)觸發(fā)Refresh操作唉俗,當(dāng)從1月份滑到去年12月份的時(shí)候嗤朴,日歷會(huì)自動(dòng)切換到去年12月份同時(shí)選中指定的日期。
9虫溜、ListView 快速滑動(dòng)試雹姊,日歷跟隨的日期仍能不會(huì)錯(cuò)
10、在日歷收縮的情況衡楞,選擇日歷某一天吱雏,ListView的依然滑到指定日期的那一條。
如何使用
compile 'com.kelin.mvvmlight:library:1.0.0'
CalendarListView 接口的設(shè)計(jì)使得用戶完全可以定制想要的UI和各種響應(yīng)的事件的支持
1瘾境、自定義CalendarView的樣式(在小格子里添加價(jià)格歧杏,tag,圖標(biāo)等)
//繼承BaseCalendarItemModel添加你想要的額外的字段迷守,比較價(jià)格犬绒,是否收藏,數(shù)量等
public class CustomCalendarItemModel extends BaseCalendarItemModel{
//這一天有多少條數(shù)據(jù)
private int count;
//是否收藏(如Demo 日歷上有沒(méi)有愛(ài)心)
private boolean isFav;
//get set
...
...
}
// 繼承BaseCalendarItemAdapter<T> (T 為你自定義的Model extendsBaseCalendarItemModel)盒犹,
// 重寫(xiě) getView方法自定義CalendarView Item 的樣式和數(shù)據(jù)
public class CalendarItemAdapter extends BaseCalendarItemAdapter<CustomCalendarItemModel>{
//date 是時(shí)間懂更,樣式“yyyy-MM-dd”
@Override
public View getView(String date, CustomCalendarItemModel model, View convertView, ViewGroup parent) {
//也可以從dayModelList 根據(jù)date獲取指定時(shí)間的model(dayModelList是基類的變量) CustomCalendarItemModel model = dayModelList.get(date);
....
ViewGroup view = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.custom_calendar_item, null);
TextView dayNum = (TextView) view.findViewById(R.id.day_num);
dayNum.setText(model.getDayNumber());
....
//從model里面獲取數(shù)據(jù)自定義想要的UI
....
....
}
}
注:如果不需要再日歷頁(yè)面添加自定義的元素,也可以直接使用BaseCalendarItemAdapter 急膀,這樣日歷的視圖只會(huì)有日期沮协,依然是可用的。
2卓嫂、自定義ListView的樣式慷暂,和傳統(tǒng)的BaseAdapter 差不多,重寫(xiě)getSectionHeaderView自定義SectionHeader的樣式,重寫(xiě)getItemView自定義每個(gè)Item的樣式行瑞。
public class ListItemAdapter extends BaseCalendarListAdapter<ListModel> {
//date 是時(shí)間奸腺,樣式“yyyy-MM-dd”
@Override
public View getSectionHeaderView(String date, View convertView, ViewGroup parent) {
List<ListModel> modelList = dateDataMap.get(date);
.....
.....//根據(jù)數(shù)據(jù)模型自定義ListView SectionHeader的樣式
.....
}
//date 是時(shí)間,樣式“yyyy-MM-dd”
@Override
public View getItemView(ListModel model,String date, int pos, View convertView, ViewGroup parent) {
//通過(guò)基類BaseCalendarListAdapter的成員變量dateDataMap可以獲取當(dāng)前date的包含的數(shù)據(jù)列表
//List<ListModel> modelList = dateDataMap.get(date);
//model = modelList.get(pos) 也可以獲取model
.....
.....//根據(jù)數(shù)據(jù)模型model自定義ListView Item的樣式
.....
}
}
3血久、初始化CalendarListView 并且設(shè)置CalendarItemAdapter和ListItemAdapter
<com.kelin.calendarlistview.library.calendar.CalendarListView
android:id="@+id/calendar_listview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.kelin.calendarlistview.library.calendar.CalendarListView>
//在onCreate中分別創(chuàng)建兩個(gè)Adapter的實(shí)例突照,并且設(shè)置到CalendarListView里面
@Override
protected void onCreate(Bundle savedInstanceState) {
//獲取calendarListView
calendarListView = (CalendarListView) findViewById(R.id.calendar_listview);
//聲明CalendarView和ListView的Adapter,分別為上面1氧吐、2步自定義的樣式的Adapter
listItemAdapter = new ListItemAdapter(this);
calendarItemAdapter = new CalendarItemAdapter(this);
//給calendarListView設(shè)置Adapter
calendarListView.setCalendarListViewAdapter(calendarItemAdapter, listItemAdapter);
}
4讹蘑、去服務(wù)器獲取日歷和列表的數(shù)據(jù)(建議接口按月份來(lái))獲取每個(gè)月份的數(shù)據(jù),在獲取完數(shù)據(jù)更新日歷和列表
- 對(duì)于CalendarView的數(shù)據(jù)更新
private void onCalendarDataLoadFinish(List<Data> datas){
....
....
//calendarItemAdapter.getDayModelList()可以獲取當(dāng)前月份的所有數(shù)據(jù)列表
//它是一個(gè)TreeMap<String, T>筑舅,key是“yyyy-MM-dd”座慰,value 是當(dāng)天的數(shù)據(jù)模型
TreeMap<String, CustomCalendarItemModel> dateMap=calendarItemAdapter.getDayModelList();
....
//獲取指定日期的Model,date的格式是yyyy-MM-dd
CustomCalendarItemModel customCalendarItemModel = dateMap.get(date);
//更新數(shù)據(jù)模型的數(shù)據(jù)
customCalendarItemModel.setXXX(data.getXXX());
....
....
//通知日歷更新UI
calendarItemAdapter.notifyDataSetChanged();
}
- 對(duì)于ListView的數(shù)據(jù)更新
//建議聲明一個(gè)TreeMap<String, List<ListModel>>的成員變量用來(lái)保持每一天下面的數(shù)據(jù)列表
//key:date "yyyy-mm-dd" format.
private TreeMap<String, List<ListModel>> listTreeMap = new TreeMap<>();
private void onListDataLoadFinish(List<Data> datas){
....
....
for(Data item:datas) {
//獲取數(shù)據(jù)的日期
String day=item.getDate();
//給listTreeMap 添加數(shù)據(jù)
if (listTreeMap.get(day) != null) {
List<NewsService.News.StoriesBean> list = listTreeMap.get(day);
list.add(i);
} else {
List<NewsService.News.StoriesBean> list = new ArrayList<NewsService.News.StoriesBean>();
list.add(i);
listTreeMap.put(day, list);
}
}
....
....
//更新數(shù)據(jù),通知更新UI
listItemAdapter.setDateDataMap(listTreeMap);
listItemAdapter.notifyDataSetChanged();
}
5翠拣、CalendarView的事件支持
- 日期選擇
calendarListView.setOnCalendarViewItemClickListener(new CalendarListView.OnCalendarViewItemClickListener() {
//具體參數(shù)看注釋版仔,寫(xiě)得比較詳細(xì)
@Override
public void onDateSelected(View View, String selectedDate, int listSection) {
//do something....
}
});
- 月份改變
calendarListView.setOnMonthChangedListener(new CalendarListView.OnMonthChangedListener() {
@Override
public void onMonthChanged(String yearMonth) {
//yearMonth:"yyyy-MM-dd"
}
});
- 下拉刷新,上拉加載更多
calendarListView.setOnListPullListener(new CalendarListView.onListPullListener() {
@Override
public void onRefresh() {
}
@Override
public void onLoadMore() {
}
});
6误墓、CalendarView的選中框樣式顏色蛮粮、上方的week bar 的樣式都是支持自定義的。
備注
1谜慌、控件部分交互有些小復(fù)雜蝉揍,可能存在一些Bug,歡迎issue和PR畦娄!
2又沾、源碼涉及較多事件分發(fā)的處理,如果你有看過(guò)我的另一篇文章《圖解Android事件分發(fā)機(jī)制》熙卡,那么源碼應(yīng)該是比較好的實(shí)踐杖刷,可以去讀一下。
3驳癌、任何控件上的問(wèn)題或者使用上的問(wèn)題滑燃,可以給我留言或私信。
4颓鲜、最后表窘,喜歡可以收藏哦!O(∩_∩)O~~
![Uploading calendarListView_247688.jpg . . .]