MonthPicker类 public class CalendarView extends LinearLayout implements View.OnClickListener { private Context context; private LinearLayout headView; public GridView bodyView; private List<Year> years;//所有要显示的年份 private Year thisYear;//今年 private MonthAdapter monthAdapter; private TextView textBack, textNext, textYear; private int yearPosition, monthPosition, currentYear, currentMonth; private boolean flagFirst; private Dialog dialog; private int startYear, startMonthPosition, endYear, endMonthPosition; private TextView showText; public CalendarView(Context context, String startDate, String endDate) { super(context); String[] startD = startDate.split("/"); String[] endD = endDate.split("/"); this.startYear = Integer.parseInt(startD[2]); this.endYear = Integer.parseInt(endD[2]); for (int i = 0; i < Year.monthNames.length; i++) { if (Year.monthNames[i].equals(startD[1])) { this.startMonthPosition = i; } if (Year.monthNames[i].equals(endD[1])) { this.endMonthPosition = i; } } init(context); } public CalendarView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public void setStartYear(int startYear) { this.startYear = startYear; } public void setStartMonthPosition(int startMonthPosition) { this.startMonthPosition = startMonthPosition; } public void setEndYear(int endYear) { this.endYear = endYear; } public void setEndMonthPosition(int endMonthPosition) { this.endMonthPosition = endMonthPosition; } public void setShowText(TextView tv) { this.showText = tv; } public void init(Context context) { this.context = context; this.setOrientation(VERTICAL); this.setGravity(Gravity.CENTER); flagFirst = true; LayoutInflater inflater = LayoutInflater.from(context); LinearLayout view = new LinearLayout(context); view = (LinearLayout) inflater.inflate(R.layout.layout_calendar, view, false); this.addView(view); this.setLayoutParams(view.getLayoutParams()); headView = (LinearLayout) view.findViewById(R.id.head_year); bodyView = (GridView) view.findViewById(R.id.grid_month); textBack = (TextView) headView.findViewById(R.id.text_back); textBack.setText("< "); textBack.setOnClickListener(this); textNext = (TextView) headView.findViewById(R.id.text_next); textNext.setText(" >"); textNext.setOnClickListener(this); textYear = (TextView) headView.findViewById(R.id.text_year); years = new ArrayList<Year>(); for (int year = startYear; year <= endYear; year++) { Year y = new Year(String.valueOf(year)); if (year == startYear) { y = new Year(startMonthPosition, String.valueOf(year)); } if (year == endYear) { y = new Year(String.valueOf(year), endMonthPosition); } years.add(y); } Calendar calendar = Calendar.getInstance(); currentMonth = calendar.get(Calendar.MONTH); monthPosition = currentMonth; Year cYear = new Year(String.valueOf(calendar.get(Calendar.YEAR))); for (Year y : years) { if (y.getName().equals(cYear.getName())) { yearPosition = years.indexOf(y); } } currentYear = yearPosition; if (yearPosition == 0) { textBack.setVisibility(INVISIBLE); } if (yearPosition == years.size() - 1) { textNext.setVisibility(INVISIBLE); } thisYear = years.get(yearPosition); textYear.setText(thisYear.getName()); monthAdapter = new MonthAdapter(thisYear.getMonths(), context); monthAdapter.setmGridView(bodyView); bodyView.setAdapter(monthAdapter); } public void show() { dialog = new Dialog(context, R.style.MonthPickerDialog); dialog.setContentView(this); dialog.show(); } //测试数据,需要外部提供实际数据 public void test() { Year year = new Year("2010", 5, 12); years.add(year); years.add(new Year("2011")); years.add(new Year("2012")); years.add(new Year("2013")); years.add(new Year("2014")); years.add(new Year("2015")); Calendar calendar = Calendar.getInstance(); currentMonth = calendar.get(Calendar.MONTH); monthPosition = currentMonth; Year cYear = new Year(String.valueOf(calendar.get(Calendar.YEAR))); years.add(cYear); yearPosition = years.indexOf(cYear); currentYear = yearPosition; thisYear = years.get(yearPosition); textYear.setText(thisYear.getName()); monthAdapter = new MonthAdapter(thisYear.getMonths(), context); monthAdapter.setmGridView(bodyView); bodyView.setAdapter(monthAdapter); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.text_back: textNext.setVisibility(View.VISIBLE); if (yearPosition > 0) { yearPosition--; thisYear = years.get(yearPosition); textYear.setText(thisYear.getName()); monthAdapter.setMonths(thisYear.getMonths()); monthAdapter.notifyDataSetChanged(); if (yearPosition == 0) { textBack.setVisibility(View.INVISIBLE); } } break; case R.id.text_next: textBack.setVisibility(View.VISIBLE); if (yearPosition < years.size() - 1) { yearPosition++; textNext.setVisibility(View.VISIBLE); thisYear = years.get(yearPosition); textYear.setText(thisYear.getName()); monthAdapter.setMonths(thisYear.getMonths()); monthAdapter.notifyDataSetChanged(); if (yearPosition == years.size() - 1) { textNext.setVisibility(View.INVISIBLE); } } break; default: break; } } /* /月份适配器 */ public class MonthAdapter extends BaseAdapter implements View.OnClickListener { private List<Month> months; private Context context; private LayoutInflater inflater; private GridView mGridView; public MonthAdapter(List<Month> months, Context context) { this.months = months; this.context = context; inflater = LayoutInflater.from(context); } public void setMonths(List<Month> months) { this.months = months; } public void setmGridView(GridView mGridView) { this.mGridView = mGridView; } @Override public int getCount() { return months == null ? 0 : months.size(); } @Override public Object getItem(int position) { return months == null ? null : months.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView == null ? inflater.inflate(R.layout.item_month, parent, false) : convertView; ViewHolder holder = (ViewHolder) view.getTag(); if (holder == null) { holder = new ViewHolder(); holder.textMonth = (TextView) view.findViewById(R.id.text_month); } Month month = months.get(position); holder.textMonth.setText(month.getName()); if (month.isEffect()) { holder.textMonth.setClickable(true); holder.textMonth.setOnClickListener(this); holder.textMonth.setTextColor(context.getResources().getColor(R.color.carlendar_text_black)); if (flagFirst && currentYear == yearPosition && currentMonth == position) { holder.textMonth.setBackground(context.getResources().getDrawable(R.drawable.color_car_selected)); holder.textMonth.setTag(true); holder.textMonth.setTextColor(context.getResources().getColor(R.color.carlendar_text_press)); flagFirst = false; } if (holder.textMonth.getTag() != null) { holder.textMonth.setTextColor(context.getResources().getColor(R.color.carlendar_text_press)); holder.textMonth.setBackground(context.getResources().getDrawable(R.drawable.color_car_selected)); } } else { holder.textMonth.setTextColor(context.getResources().getColor(R.color.carlendar_text_gray)); holder.textMonth.setBackground(context.getResources().getDrawable(R.drawable.color_car_back)); holder.textMonth.setClickable(false); } return view; } @Override public void onClick(View v) { int count = mGridView.getChildCount() - 1; while (count >= 0) { TextView textView = (TextView) mGridView.getChildAt(count).findViewById(R.id.text_month); textView.setBackground(context.getResources().getDrawable(R.drawable.color_car_back)); textView.setTag(null); if (months.get(count).isEffect()) { if (textView == v) { monthPosition = count; } textView.setTextColor(context.getResources().getColor(R.color.carlendar_text_black)); } else { textView.setTextColor(context.getResources().getColor(R.color.carlendar_text_gray)); } count--; } v.setBackground(context.getResources().getDrawable(R.drawable.color_car_selected)); v.setTag(true); ((TextView) v).setTextColor(context.getResources().getColor(R.color.carlendar_text_press)); Month month = thisYear.getMonths().get(monthPosition); if (month.isEffect()) { showText.setText(month.getName() + " " + thisYear.getName()); dialog.dismiss(); } } public class ViewHolder { TextView textMonth; } } /* /实体类:年 */ public static class Year { private List<Month> months; private int past, feature; private String name; public static String[] monthNames = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; public Year(String name) { this(name, -1, Integer.MAX_VALUE); } public Year(int past, String name) { this(name, past, Integer.MAX_VALUE); } public Year(String name, int feature) { this(name, -1, feature); } public Year(String name, int past, int feature) { this.name = name; months = new ArrayList<Month>(); for (int i = 0; i < 12; i++) { Month month = new Month(monthNames[i]); if (i < past || i > feature) { month.setIsEffect(false); } months.add(month); } } public List<Month> getMonths() { return months; } public void setMonths(List<Month> months) { this.months = months; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPast() { return past; } public void setPast(int past) { this.past = past; } public int getFeature() { return feature; } public void setFeature(int feature) { this.feature = feature; } } /* /实体类:月 */ public static class Month { private String name; private boolean isEffect; public Month(String name) { this.name = name; isEffect = true; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isEffect() { return isEffect; } public void setIsEffect(boolean isEffect) { this.isEffect = isEffect; } } }
MonthPicker布局:layout_calendar
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="300dp" android:layout_height="245dp" android:background="#ffffff" android:gravity="center" android:orientation="vertical" android:paddingBottom="50dp" android:paddingLeft="15dp" android:paddingRight="15dp" android:paddingTop="13dp" tools:context=".MainActivity" > <LinearLayout android:id="@+id/head_year" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:background="#ffffff" android:gravity="center" android:orientation="horizontal" > <TextView android:id="@+id/text_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="25dp" android:gravity="left" android:text="back" android:textSize="32dp" /> <TextView android:id="@+id/text_year" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginRight="15dp" android:gravity="center" android:text="2015" android:textSize="32dp" /> <TextView android:id="@+id/text_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="right" android:text="next" android:textSize="32dp" /> </LinearLayout> <GridView android:id="@+id/grid_month" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="17dp" android:background="#ffffff" android:gravity="center" android:horizontalSpacing="13dp" android:numColumns="4" android:verticalSpacing="10dp" ></GridView> </LinearLayout>
MonthPicker中Month的布局:item_month<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" tools:context=".MainActivity" > <TextView android:id="@+id/text_month" android:layout_width="75dp" android:layout_height="wrap_content" android:layout_gravity="center" android:background="#ffffff" android:foregroundGravity="center" android:gravity="center" android:textColor="#333333" android:textSize="25sp" /> </LinearLayout> Dialog的style<style name="MonthPickerDialog" parent="android:style/Theme.Dialog"> <item name="android:windowBackground">@color/carlendar_text_press</item> <item name="android:windowNoTitle">true</item> </style>Color<resources> <color name="carlendar_text_black">#333333</color> <color name="carlendar_text_gray">#999999</color> <color name="carlendar_text_press">#ffffff</color> <color name="carlendar_back_press">#ffef8350</color> </resources> Drawable 1 color_car_back<color xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/carlendar_text_press"> </color> 2 color_car_selected<color xmlns:android="http://schemas.android.com/apk/res/android" android:color="@color/carlendar_back_press"> </color>