1. 程式人生 > >android實現不同樣式的日曆控制元件(MaterialCalendarView的改造工程)

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這個編輯器怎麼這麼難用。