android實現不同樣式的日曆控制元件(MaterialCalendarView的改造工程)
本來以為吃透了MaterialCalendarView這個開源控制元件,為了做個考勤,心力憔悴啊!!!
MaterialCalendarView 這個控制元件雖然可以自定樣式,但是樣式卻是所有的日期都是一種樣式。這個就搞的有點尷尬了!!!
我現在的需求是每一個天數需要顯示三種樣式,正常的話,則日期下面顯示正常兩個字,異常的話則顯示異常兩個字,還有一種情況就是沒有記錄,
週六日不需要考勤,則日期下面顯示空白!!!
如果有這種需求的小夥伴,還在糾結的話,不妨參考我改寫的MaterialCalendarView.今天遇到了月切換載入資料的時候日曆控制元件切換卡頓的情況。好蛋疼!!
搞了一天總算是可以交代了。
下面介紹用法,不介紹實現的原理。
其實原理很簡單,自定義一個viewgroup 顯示日曆的一個頁面,用viewpager去顯示這個頁面,實現滑動的效果。viewpager adapter返回一個很大的數,利用這個數
轉換成年月日。
下面介紹我改造的思路的原理
寫一個Textspan類實現LineBackgroundSpan介面設定所有你需要的樣式。
public TextSpan(String mode){
this.mode = mode;
if(this.mode.equals(EXCEPTION)){
this.color = Color.parseColor("#fe8604") ;
this.mText = "異常";
}else if(this.mode.equals(NORMAL)){
this.color = Color.BLACK;
this.mText = "正常";
}
}
我做的就是 給textspan設定一個mode 如果是"0"就設定文字正常 是"1"設定文字正常 是"-1"正常顯示控制元件.在dayview類中applyFacadeGAC方法中 你只需要根據你的mode 設定 樣式就可以了 void applyFacadeGAC(String mode,boolea visible){ setTodayColor(); if(!visible){ setTextColor(getResources().getColor (R.color.calendartextcor0)); setEnabled(false); } if(mode.equals("0") || mode.equals("1")){ String label = getLabel(); SpannableString formattedLabel = new SpannableString(getLabel()); formattedLabel.setSpan(new TextSpan(mode), 0, label.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); setText(formattedLabel); }else{ setText(getLabel()); } } 給EventDecortor類傳入一個Map<String,String>集合key 日期字串,mode 需要設定的樣式,這樣你就可以給不同的日期設定不同的樣式了
EventDecortor類中有一個方法
public String shouldDecorateGAC(CalendarDay day) {
String currentMode = -1+”“;
String str = DateUtils.getDateStr(day.getDate());
if(hashMap == null){ //Log.e("gac","hashmap is null"); return "-1"; } Log.e("gac","date:"+str); if(hashMap.containsKey(str)){ Log.e("gac","currentMode:"+currentMode); currentMode = hashMap.get(str); } return currentMode; } 這個方法主要在CalendarPagerView類裡面呼叫,CalendarPagerView 遍歷當前顯示的月份的日期集合,並且呼叫applayDecorateGac方法。把每一個日期傳給引數day EventDecortor類中設定一個Map<String,String>型別的集合,第一個key存取日期字串,第二個key存取你需要設定樣式的mode值。 如果Map集合中的日期 和傳入的引數day日期相等,則把mode值返回給CalendarPagerView,CalendarPagerView根據這個mode值設定樣式。 下面介紹使用方法, 在佈局檔案中新增這個控制元件 <com.gac.calendarviewdemo.CalendarView.MaterialCalendarView android:id="@+id/calendar" android:layout_width="match_parent" android:layout_height="wrap_content"> </com.gac.calendarviewdemo.CalendarView.MaterialCalendarView> 然後再acitvity初始化 public class MainActivity extends AppCompatActivity implements MaterialCalendarView.OnDateSelectedListener,MaterialCalendarView.OnMonthChangedListener 實現OnDateSelecteListener介面 點選日期的時候觸發的事件 OnMonthChangedListener 滑動日曆切換月份的時候觸發的事件 初始化資料集合 public EventDecorator decorator; private Map<String,String> getMap(){ Map<String,String> map = new HashMap<>(); map.put("2016-04-13",1+""); map.put("2016-04-14",1+""); map.put("2016-04-15",0+""); map.put("2016-04-19",0+""); return map; } private Map<String,String> getMap1(String month){ Map<String,String> map = new HashMap<>(); map.put("2016-0"+month+"-13", 1+""); map.put("2016-0"+month+"-14", 0+""); map.put("2016-0"+month+"-12", 1+""); map.put("2016-0"+month+"-18", 0+""); map.put("2016-0"+month+"-23", 1+""); map.put("2016-0"+month+"-21", 0+""); map.put("2016-0"+month+"-20", 1+""); return map; } 初始化日曆控制元件 calendar = (MaterialCalendarView)findViewById(R.id.calendar); calendar.setOnMonthChangedListener(this); calendar.setOnDateChangedListener(this); decorator = new EventDecorator(getMap()); calendar.addDecoratorGAC(decorator); 此時在OnMonthChangeListener介面中呼叫decorator.setMap(getMap1(str));方法就可以動態的去改變日曆控制元件的樣式了。 @Override public void onMonthChanged(MaterialCalendarView widget, CalendarDay date) { String str = (date.getMonth()+1)+""; print(str); decorator.setMap(getMap1(str)); } 原始碼地址:見評論欄: 我擦,csdn這個編輯器怎麼這麼難用。