需求是这样的:在日历控件中,每一个日期都有选择和取消两种状态,也就是说每个日期的控件相当于复选框。被选择的日期列表可以获得。也可以设定选择好的列表日期到控件中。其实看起来挺简单的,其实就是把安卓的calendarview的日期单选变成多选,能主动初始化选择项,和取出选择项。但是在实际应用中calendarview实在不能满足各种要求。只好自定义日期日历。如下:
1、 先布局自定义view的界面:
<?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"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_margin="@dimen/activity_vertical_margin"> <ImageButton android:id="@+id/calendarview_imgbutton_left" android:layout_marginLeft="@dimen/activity_vertical_margin" android:src="@mipmap/calendar_month_left" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:id="@+id/calendarviewtext_month" android:text="2016年4月" android:layout_width="wrap_content" android:layout_weight="1" android:textSize="22sp" android:gravity="center" android:layout_height="match_parent" /> <ImageButton android:id="@+id/calendarview_imgbutton_right" android:layout_marginRight="@dimen/activity_vertical_margin" android:src="@mipmap/calendar_month_right" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:text="日" android:layout_width="wrap_content" android:layout_weight="1" android:gravity="center" android:textSize="22sp" android:layout_height="wrap_content" /> <TextView android:text="一" android:layout_width="wrap_content" android:layout_weight="1" android:gravity="center" android:textSize="22sp" android:layout_height="wrap_content" /> <TextView android:text="二" android:layout_width="wrap_content" android:layout_weight="1" android:gravity="center" android:textSize="22sp" android:layout_height="wrap_content" /> <TextView android:text="三" android:layout_width="wrap_content" android:layout_weight="1" android:gravity="center" android:textSize="22sp" android:layout_height="wrap_content" /> <TextView android:text="四" android:layout_width="wrap_content" android:layout_weight="1" android:gravity="center" android:textSize="22sp" android:layout_height="wrap_content" /> <TextView android:text="五" android:layout_width="wrap_content" android:layout_weight="1" android:gravity="center" android:textSize="22sp" android:layout_height="wrap_content" /> <TextView android:text="六" android:layout_width="wrap_content" android:layout_weight="1" android:gravity="center" android:textSize="22sp" android:layout_height="wrap_content" /> </LinearLayout> <GridView android:id="@+id/calendarview_grid_gridview" android:layout_width="match_parent" android:layout_height="wrap_content" android:numColumns="7" android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:stretchMode="columnWidth" android:layout_margin="10dp" android:gravity="center"></GridView> </LinearLayout> 2、创建日期项类
public class DateItem { private int dateOfMonth=0; private boolean isselect=false; private int year; private int month; public int getYear() { return year; } public void setYear(int year) { this.year = year; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public int getDateOfMonth() { return dateOfMonth; } public void setDateOfMonth(int dateOfMonth) { this.dateOfMonth = dateOfMonth; } public boolean isselect() { return isselect; } public void setIsselect(boolean isselect) { this.isselect = isselect; } } 每一个日期都有年、月、日和是否被选择的标记。
3、创建gridvew的适配器
package com.xiaoyunchengzhu.multiselectcalendarview.adapter; import android.content.Context; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.xiaoyunchengzhu.multiselectcalendarview.R; import com.xiaoyunchengzhu.multiselectcalendarview.bean.DateItem; import com.xiaoyunchengzhu.multiselectcalendarview.customview.CustomCalendarView; import com.xiaoyunchengzhu.multiselectcalendarview.util.ConfigUtils; import java.util.Calendar; import java.util.List; /** * */ public class CalendarGridViewAdapter extends BaseAdapter { private List<DateItem> list; private Context context; private CustomCalendarView customCalendarView; private int itembackgourd; public CalendarGridViewAdapter(CustomCalendarView customCalendarView,Context context,List<DateItem> list,int itembackgourd){ this.context=context; this.list=list; this.itembackgourd=itembackgourd; this.customCalendarView=customCalendarView; } public void setDate(List<DateItem> list){ this.list=list; notifyDataSetChanged(); } @Override public int getCount() { return list.size(); } @Override public Object getItem(int position) { return list.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(final int position, View convertView, ViewGroup parent) { TextView textView=null; if (convertView==null){ textView=new TextView(context); convertView=textView; } textView= (TextView) convertView; textView.setGravity(Gravity.CENTER); if (list.get(position).isselect()){ if (itembackgourd==-1) { textView.setBackgroundColor(context.getResources().getColor(R.color.tet_blue)); }else { textView.setBackgroundResource(itembackgourd); } }else { textView.setBackgroundColor(context.getResources().getColor(R.color.base_bg)); } textView.setTextSize(22); if (list.get(position).getDateOfMonth()>0){ final TextView finalTextView = textView; textView.setText(list.get(position).getDateOfMonth() + ""); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { list.get(position).setIsselect(!list.get(position).isselect()); if (list.get(position).isselect()){ if (itembackgourd==-1) { finalTextView.setBackgroundColor(context.getResources().getColor(R.color.tet_blue)); }else { finalTextView.setBackgroundResource(itembackgourd); } Calendar calendar=Calendar.getInstance(); calendar.set(list.get(position).getYear(),list.get(position).getMonth(),list.get(position).getDateOfMonth()); customCalendarView.addSelectDate(ConfigUtils.simpleDate(calendar.getTime())); }else { finalTextView.setBackgroundColor(context.getResources().getColor(R.color.base_bg)); Calendar calendar=Calendar.getInstance(); calendar.set(list.get(position).getYear(),list.get(position).getMonth(),list.get(position).getDateOfMonth()); customCalendarView.removeSelect(ConfigUtils.simpleDate(calendar.getTime())); } } }); }else { textView.setBackgroundColor(context.getResources().getColor(R.color.base_bg)); textView.setText(""); } return convertView; } }适配器把一个月的日期列表适配到gridview中,并把 日期选择 标记到的,进行选择确定。其中CustomCalendarView 就是下面要说自定义的calendar的view。calendarveiw有存放日期选择的选择列表。
4、
package com.xiaoyunchengzhu.multiselectcalendarview.customview; import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.widget.AdapterView; import android.widget.GridView; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.TextView; import com.xiaoyunchengzhu.multiselectcalendarview.R; import com.xiaoyunchengzhu.multiselectcalendarview.adapter.CalendarGridViewAdapter; import com.xiaoyunchengzhu.multiselectcalendarview.bean.DateItem; import com.xiaoyunchengzhu.multiselectcalendarview.util.ConfigUtils; import com.xiaoyunchengzhu.multiselectcalendarview.util.inject.Inject; import com.xiaoyunchengzhu.multiselectcalendarview.util.inject.ViewInject; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * */ public class CustomCalendarView extends LinearLayout { @Inject(R.id.calendarview_imgbutton_left) private ImageButton left; @Inject(R.id.calendarview_imgbutton_right) private ImageButton right; @Inject(R.id.calendarviewtext_month) private TextView moth; @Inject(R.id.calendarview_grid_gridview) private GridView gridView; private CalendarGridViewAdapter adapter; private int currentYear,currentMonth; private List<String> selectdateList=new ArrayList<>(); private List<Date> currentWeekList=new ArrayList<>(); private List<Date> currentUnWeekList=new ArrayList<>(); private int itembackground; private AttributeSet attrs; public CustomCalendarView(Context context) { super(context); View view= LayoutInflater.from(getContext()).inflate(R.layout.custom_calendarview,null); ViewInject.inject(this,view); addView(view); Calendar calendar=Calendar.getInstance(); calendar.setTime(new Date()); inite(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH)); } public CustomCalendarView(Context context, AttributeSet attrs) { super(context, attrs); this.attrs=attrs; View view= LayoutInflater.from(getContext()).inflate(R.layout.custom_calendarview,null); ViewInject.inject(this,view); addView(view); Calendar calendar=Calendar.getInstance(); calendar.setTime(new Date()); inite(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH)); } public CustomCalendarView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); this.attrs=attrs; View view= LayoutInflater.from(getContext()).inflate(R.layout.custom_calendarview,null); ViewInject.inject(this,view); addView(view); Calendar calendar=Calendar.getInstance(); calendar.setTime(new Date()); inite(calendar.get(Calendar.YEAR),calendar.get(Calendar.MONTH)); } private void inite(int year, int month){ getAttrs(getContext(),attrs); currentYear=year; currentMonth=month; moth.setText(currentYear+"年 "+(currentMonth+1)+"月"); List<DateItem> dateItems=new ArrayList<>(); int firstPostion=getFirstDayWeek(currentYear,currentMonth); int monthDayNum=getMonthDays(currentYear,currentMonth); firstPostion--; for (int i=1;i<=(monthDayNum+firstPostion);i++){ DateItem dateItem=new DateItem(); dateItem.setYear(year); dateItem.setMonth(month); if (i>firstPostion){ int dayofmonth=i-firstPostion; dateItem.setDateOfMonth(dayofmonth); if (selectdateList!=null&&selectdateList.size()>0) { for (String date : selectdateList) { Calendar calendar=Calendar.getInstance(); calendar.setTime(ConfigUtils.simpleDate(date)); if (calendar.get(Calendar.YEAR)==year&&calendar.get(Calendar.MONTH)==month&&calendar.get(Calendar.DAY_OF_MONTH)==dayofmonth){ dateItem.setIsselect(true); } } } } dateItems.add(dateItem); } if (adapter==null) { adapter = new CalendarGridViewAdapter(this,getContext(), dateItems,itembackground); gridView.setAdapter(adapter); }else { if (dateItems!=null) adapter.setDate(dateItems); } left.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { setLeftOnclick(); } }); right.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { setRightOnclick(); } }); } public void setOnItemClickListener(AdapterView.OnItemClickListener onitemClicklistnear){ gridView.setOnItemClickListener(onitemClicklistnear); } public void swichUnWeekTheMonth(boolean isselect){ for (int i=0;i<gridView.getChildCount();i++) { DateItem dateItem = (DateItem) adapter.getItem(i); if (dateItem.getDateOfMonth()!=0&&(i%7!=6&&i%7!=0)) { if (isselect) { if (!dateItem.isselect()) { dateItem.setIsselect(isselect); Calendar calendar = Calendar.getInstance(); calendar.set(currentYear, currentMonth, dateItem.getDateOfMonth()); TextView textView = (TextView) gridView.getChildAt(i); textView.setBackgroundColor(getResources().getColor(R.color.tet_blue)); addSelectDate(ConfigUtils.simpleDate(calendar.getTime())); } } else { if (dateItem.isselect()) { dateItem.setIsselect(!dateItem.isselect()); Calendar calendar = Calendar.getInstance(); calendar.set(currentYear, currentMonth, dateItem.getDateOfMonth()); TextView textView = (TextView) gridView.getChildAt(i); textView.setBackgroundColor(getResources().getColor(R.color.base_bg)); removeSelect(ConfigUtils.simpleDate(calendar.getTime())); } } } } } public void swichWeekendTheMonth(boolean isselect){ for (int i=0;i<gridView.getChildCount();i++) { DateItem dateItem = (DateItem) adapter.getItem(i); if (dateItem.getDateOfMonth()!=0&&(i%7==6||i%7==0)) { if (isselect) { if (!dateItem.isselect()) { dateItem.setIsselect(isselect); Calendar calendar = Calendar.getInstance(); calendar.set(currentYear, currentMonth, dateItem.getDateOfMonth()); TextView textView = (TextView) gridView.getChildAt(i); textView.setBackgroundColor(getResources().getColor(R.color.tet_blue)); addSelectDate(ConfigUtils.simpleDate(calendar.getTime())); } } else { if (dateItem.isselect()) { dateItem.setIsselect(!dateItem.isselect()); Calendar calendar = Calendar.getInstance(); calendar.set(currentYear, currentMonth, dateItem.getDateOfMonth()); TextView textView = (TextView) gridView.getChildAt(i); textView.setBackgroundColor(getResources().getColor(R.color.base_bg)); removeSelect(ConfigUtils.simpleDate(calendar.getTime())); } } } } } public void setSelect(List<String> selectdateList){ this.selectdateList=selectdateList; inite(currentYear,currentMonth); invalidate(); } public void addSelectDate(String date){ selectdateList.add(date); invalidate(); } public void removeSelect(String date){ selectdateList.remove(date); } public List<Date> getWeekOfMonthList(){ return currentWeekList; } public List<Date> getUnWeekMonthList(){ return currentUnWeekList; } public List<String> getSelectdateList(){ return selectdateList; } private void setLeftOnclick(){ int cutMonth=(currentMonth-1); if (cutMonth>=0) { inite(currentYear,cutMonth); }else { int cutYear=currentYear-1; inite(cutYear--,11); } invalidate(); } private void setRightOnclick(){ int cutMonth=(currentMonth+1); if (cutMonth<=11) { inite(currentYear,cutMonth); }else { int cutYear=currentYear+1; inite(cutYear,0); } invalidate(); } public void clearCurrentMonthSelect(){ for (int i=0;i<gridView.getChildCount();i++){ DateItem dateItem= (DateItem) adapter.getItem(i); if (dateItem.isselect()) { dateItem.setIsselect(!dateItem.isselect()); Calendar calendar=Calendar.getInstance(); calendar.set(currentYear, currentMonth, dateItem.getDateOfMonth()); TextView textView = (TextView) gridView.getChildAt(i); textView.setBackgroundColor(getResources().getColor(R.color.base_bg)); removeSelect(ConfigUtils.simpleDate(calendar.getTime())); } } } private void getAttrs(Context context, AttributeSet attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.calendarview); itembackground=ta.getResourceId(R.styleable.calendarview_item_select_backgroud,-1); ta.recycle(); } /** * 通过年份和月份 得到当月的日子 */ private int getMonthDays(int year, int month) { month++; switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: return 31; case 4: case 6: case 9: case 11: return 30; case 2: if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)){ return 29; }else{ return 28; } default: return -1; } } /** * 返回当前月份1号位于周几 * @param year * 年份 * @param month * 月份,传入系统获取的,不需要正常的 * @return * 日:1 一:2 二:3 三:4 四:5 五:6 六:7 */ private int getFirstDayWeek(int year, int month){ Calendar calendar = Calendar.getInstance(); calendar.set(year, month, 1); return calendar.get(Calendar.DAY_OF_WEEK); } }一个gridview展示的是一个月的日期日历,以及这个月是否被选中的日期的标记。每个月的1号是 从星期几开始的,这个月一共有多少天,都需要计算,还有添加到日期列表中。
5、主Activity展示:
package com.xiaoyunchengzhu.multiselectcalendarview; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; import com.google.gson.Gson; import com.xiaoyunchengzhu.multiselectcalendarview.customview.CustomCalendarView; import com.xiaoyunchengzhu.multiselectcalendarview.util.inject.Inject; import com.xiaoyunchengzhu.multiselectcalendarview.util.inject.ViewInject; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener{ @Inject(R.id.calendarview) private CustomCalendarView calendarView; @Inject(R.id.showselectbutton) private Button show; @Inject(R.id.showselect) private TextView showtext; private List<String> initeData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ViewInject.inject(this); initeData=new ArrayList<>(); for (int i=0;i<4;i++){ String data="2016-08-"+(27+i); initeData.add(data); } for (int i=0;i<2;i++){ String data="2016-09-"+(27+i); initeData.add(data); } calendarView.setSelect(initeData); show.setOnClickListener(this); } @Override public void onClick(View v) { showtext.setText(new Gson().toJson(calendarView.getSelectdateList())); } }
初始化 自定义的日历日期控件,然后模拟已经选择的日期进行初始化选择项。点击按钮展示已经选择的日期到界面。
项目github地址:https://github.com/xiaoyunchengzhu/MultiSelectCalendarView