月曆控件有很多,但是如果要實作在月曆上标注文字或者圖檔,該如何實作呢,小菜鳥一枚,下面寫寫我在項目裡用到的一個控件--MaterialCalendarView, 基于MaterailDesign風格De月曆,據說最早是由外國人寫的,然後開源出來了,之是以會選中這個是他可以較友善的在月曆上添加标記,而且MaterailDesign風格的很受大家好評,做項目的時候網上找了好些資料,也找了發過類似文章的大神支援。好了下面是我的項目的demo跟效果圖
這個是我項目中一個子產品的截圖,下面那部分月曆就是效果圖啦。
1.布局檔案
<com.prolificinteractive.materialcalendarview.MaterialCalendarView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:mcv_tileSize="45dp"
app:mcv_dateTextAppearance="@style/dateTextAppeararent"
app:mcv_weekDayTextAppearance="@style/monthTextAppeararent"
app:mcv_headerTextAppearance="@style/headerTextAppeararent"
app:mcv_weekDayLabels="@array/custom_myweekdays"
app:mcv_monthLabels="@array/custom_mymonths"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
可以以添加類庫的方式導入,但是最好是以導入類庫的方式導入AS,這樣有了源代碼你就可以根據你自己的需要更改UI或者源代碼了,在這裡就不提供github的第三方庫下載下傳位址了,直接去github上搜 MaterialCalendarView就有了。
僅提供那兩個array/custom_myweekdays 和 array/custom_mymonths寫在Strings.xml裡,剩下的在類庫裡都有了
<string-array name="custom_myweekdays">
<item>日</item>
<item>一</item>
<item>二</item>
<item>三</item>
<item>四</item>
<item>五</item>
<item>六</item>
</string-array>
<string-array name="custom_mymonths">
<item>一月</item>
<item>二月</item>
<item>三月</item>
<item>四月</item>
<item>五月</item>
<item>六月</item>
<item>七月</item>
<item>八月</item>
<item>九月</item>
<item>十月</item>
<item>十一月</item>
<item>十二月</item>
</string-array>
2.接下來是Activity
<span style="font-size:14px;"> private MaterialCalendarView calendarView;
private Calendar calendar;
private OneDayDecorator oneDayDecorator= new OneDayDecorator();</span>
<pre name="code" class="java">@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.orders_everyday_frag, container, false);
calendarView= (MaterialCalendarView) view.findViewById(R.id.calendarView);
calendarView.setOnDateChangedListener(this);
calendarView.setOnMonthChangedListener(this);
calendar = Calendar.getInstance();
calendarView.setFirstDayOfWeek(calendar.SUNDAY);//設定一周起始日
calendarView.setSelectedDate(calendar.getTime());//當日選中
//系統目前日期的顔色
calendarView.addDecorators(new MyBackgroundDecorator(getActivity(), R.drawable.my_selector_orange,
CalendarDay.from(calendar.getTime())));
//選中日期的顔色
calendarView.addDecorators(new MySelectorDecorator(getActivity(), R.drawable.my_selector_blue),
oneDayDecorator);
//在日期上添加标記或者圖檔,需要用到實體類-->EventDecorator.class
list.add(new EventDecorator(getContext(),new int[]{1,orderSchedule.getServiceOrderCount() ,orderSchedule.getNewOrderCount()},strTranCalendar(orderSchedule.getWorkDate())));
//setData(systemTime);更新ui
return view;
}
public CalendarDay strTranCalendar(String str){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try {
Date date = dateFormat.parse(str);
calendar.setTime(date);
CalendarDay calendarDay = CalendarDay.from(calendar);
return calendarDay;
} catch (ParseException e) {
e.printStackTrace();return null;
}
}
//這個方法是,選中某個日期以後執行的方法,注意date的格式需要根據自己的需要處理一下
@Override
public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) {
if (selected){
String substring = date.toString().substring(0, date.toString().length() - 1);
String[] split = substring.split("[{]");//特殊字元,需要轉義2015-0-8
//....此處省略部分代碼
}
}
//這個方法是,當左右滑動切換月份時,執行的方法
@Override
public void onMonthChanged(MaterialCalendarView widget, CalendarDay date) {
String s = DateFormatUtils.getFormatDate(date, true);//滑動後顯示的月份
String curMonth = systemTime.substring(0, 7);//目前月:2015-02
}
除此之外,你還需要這幾個類
其中MypointSpan是繪圖的核心代碼,其他幾個類是類庫裡本身就有的,如果有需要可以在自定義一下,下面講一下MyPointSpan.class:
public class MyPointSpan implements LineBackgroundSpan {
private Context context;
public static final float DEFAULT_RADIUS = 3;
private final float radius;
//預先定義好的顔色
private final int[] color=new int[]{1,2,3,4};
//接收過來的資料
private final int[] data;
public MyPointSpan() {
this.radius = DEFAULT_RADIUS;
this.data = null;
}
public MyPointSpan(int[] color) {
this.radius = DEFAULT_RADIUS;
this.data = color;
}
public MyPointSpan(float radius) {
this.radius = radius;
this.data = null;
}
public MyPointSpan(Context context,float radius, int[] data) {
this.context=context;
this.radius = radius;
this.data = data;
}
@Override
public void drawBackground(
Canvas canvas, Paint paint,
int left, int right, int top, int baseline, int bottom,
CharSequence charSequence,
int start, int end, int lineNum
) {
Resources res = context.getResources();
float common_font_sw320dp_of_10 = res.getDimension(R.dimen.common_font_sw320dp_of_10);//引用dimen檔案,友善螢幕适配
int oldColor = paint.getColor();
//新加
float oldTextSize = paint.getTextSize();
paint.setTextAlign(Paint.Align.LEFT);
if(data.length!= 0&&!data.equals(null)) {
String text1;
String text2;
//清除畫布
/*paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPaint(paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));*/
switch (data[0]){
case 1:
//目前日期及其目前日期之後的---區分顯示--1
<span style="white-space:pre"> </span> //服務中訂單
paint.setColor(getColor(color[0]));
paint.setTextSize(common_font_sw320dp_of_10);
canvas.drawText(data[2] + "/", (left + right) / 4 - radius, bottom + top + radius + 12, paint);
//新增訂單
paint.setColor(getColor(color[2]));
paint.setTextSize(common_font_sw320dp_of_10);
canvas.drawText(data[1]+"", (left + right) / 2+ radius, bottom+top + radius+12, paint);
paint.setTextSize(oldTextSize);
paint.setColor(oldColor);
paint.setTextAlign(Paint.Align.LEFT);
break;
}
}
paint.setColor(oldColor);
}
public int getColor(int colorNum){
int circleColor=0;
switch (colorNum){
case 1:
int i = Color.parseColor("#fc7c0f");
circleColor=i;break; //閑
case 2:circleColor= Color.GRAY;break; //過去的日期顯示灰色
case 3:
int j=Color.parseColor("#1eb9cf");
circleColor=j;break; //忙
case 4:circleColor=Color.BLACK;
break; //分割線
}
return circleColor;
}
}
}
</pre><br /><pre name="code" class="java">當需要在畫布上重新繪制标記的時候,想到的有兩種方式:一是清除畫布,但是有個很緻命的缺陷就是,畫布的背景色會變成黑色,試了好多種方法都沒有效果
清除畫布的代碼:
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
canvas.drawPaint(paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
</pre><pre name="code" class="java">第二種方式是:設定畫筆的背景色background是白色,實驗證明,确實有效果,但是别忘了,月曆上目前日期是有圓形的背景圖的,這個background會覆寫掉他。。。
最好不得已,隻能讓他的生命周期重新走一遍,然後重新繪制,在這裡征求大家的心得,有沒有更好的方式!
</pre><pre name="code" class="java">小菜鳥一枚,具體的代碼剖析還請看-->http://blog.csdn.net/miss_qz14/article/details/50014617 感謝大神的幫助~