之前做的APP,没有明确的需求,就是说让我做一个像那种酒店订房的日期选择,用来订位置???说是出差的人回来可能工位被占了,需要用到这个软件去预定位置····(内部人使用的,当然没用起来··)
所以我在网上找了一个模板,但是已经过了很久了,我已经记不清是哪位大神做的,我只是进行一些小小的更改,还有发现一些小BUG,改了下,
这图好像太大了,,,,不知道怎么调,将就着看吧,主要代码呢,全是自定义View,我是真不会,我之前改的一部分时间太长了,已经完全看不懂了,各位大佬就将就着看吧,
首先是定义的DatePickerItemView
public class DatePickerItemView extends View {
private static final int COLUME = 7;
// private static final String[] weeks = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
// private static final int WEEK_HEIGHT = 50;
private static final int WEEK_HEIGHT = 0;
// private static final int ITEM_PADDING = 5;
public static final int SAME_MONTH = 0; //0代表开始和结束在同一个月,1,2,3代表开始和结束不在同一个月
public static final int START_MONTH = 1; //开头的那个月
public static final int END_MONTH = 2; //中间的月份
public static final int MID_MONTH = 3; //结束的月份
private Controler mControler;
private ItemBean item;
// private int dayCount = 30;
private float mWidth;
private float mHeight;
private float radius;
private float mTopsub;
private float mBottomsub;
private float mTextTopsub;
private float mTextBottomsub;
// private int selectedStart = -1;
// private int selectedEnd = -1;
private Paint mDayNumberPaint;
private Paint mDaySlectedBackGrountPaint;
private Paint mDayTextPaint;
public DatePickerItemView(Context context) {
super(context);
init();
}
public DatePickerItemView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSpecsize = MeasureSpec.getSize(widthMeasureSpec);
int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
if (heightSpecMode == MeasureSpec.AT_MOST) {
int height = widthSpecsize / 7 * 6;
setMeasuredDimension(widthSpecsize, height);
} else if (heightSpecMode == MeasureSpec.UNSPECIFIED) {
int height = widthSpecsize / 7 * 6;
setMeasuredDimension(widthSpecsize, height);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
}
private void init() {
mDayNumberPaint = new Paint();
mDayNumberPaint.setAntiAlias(true);
mDayNumberPaint.setTextSize(30);
mDayNumberPaint.setTextAlign(Paint.Align.CENTER); //text绘制时,x方向居中
mDayNumberPaint.setFakeBoldText(true);
Paint.FontMetrics fontMetrics = mDayNumberPaint.getFontMetrics();
mTopsub = fontMetrics.top / 2;
mBottomsub = fontMetrics.bottom / 2;
// mDayNumberPaint.setTextSize(MONTH_DAY_LABEL_TEXT_SIZE);
// mDayNumberPaint.setColor(mDayTextColor);
// mDayNumberPaint.setTypeface(Typeface.create(mDayOfWeekTypeface, Typeface.NORMAL));
// mDayNumberPaint.setStyle(Style.FILL);
// mDaySlectedBackGrountPaint
// mMonthPaint
// mYearPaint
mDaySlectedBackGrountPaint = new Paint();
// mDaySlectedBackGrountPaint.setColor(getResources().getColor(R.color.colorpPink));
mDayTextPaint = new Paint();
mDayTextPaint.setTextSize(18);
mDayTextPaint.setAntiAlias(true);
mDayTextPaint.setTextAlign(Paint.Align.CENTER); //text绘制时,x方向居中
mDayTextPaint.setFakeBoldText(true);
mDayTextPaint.setColor(Color.WHITE);
Paint.FontMetrics textFm = mDayNumberPaint.getFontMetrics();
mTextTopsub = textFm.top / 2;
mTextBottomsub = textFm.bottom / 2;
// mDaySlectedBackGrountPaint.setFakeBoldText(true);
// mDaySlectedBackGrountPaint.setAntiAlias(true);
// mDaySlectedBackGrountPaint.setTextAlign(Align.CENTER);
// mDaySlectedBackGrountPaint.setStyle(Style.FILL);
// mDaySlectedBackGrountPaint.setAlpha(SELECTED_CIRCLE_ALPHA);
}
@Override
protected void onDraw(Canvas canvas) {
// drawWeekDay(canvas);
drawDayNumberBackgroung(canvas);
drawDayNumber(canvas);
// drawDayText(canvas);
}
private void drawDayText(Canvas canvas) {
int pos1st = item.getPos1st();
int row;
int col;
float wid = mWidth / COLUME;
float widsub = wid / 2;
ArrayList<HolidayItemBean> holidayItems = item.getHolidayItems();
mDayTextPaint.setColor(getResources().getColor(R.color.color_FF6257));
for (int i = 0; i < holidayItems.size(); i++) {
row = day2Pos(holidayItems.get(i).getDay()) / COLUME;
col = day2Pos(holidayItems.get(i).getDay()) % COLUME;
canvas.drawText(holidayItems.get(i).getName(), wid * col + widsub, wid * row - mTextBottomsub - mTextTopsub + 5, mDayTextPaint);
}
mDayTextPaint.setColor(Color.WHITE);
if (item.getType() == START_MONTH && item.getStart() != -1) {
row = day2Pos(item.getStart()) / COLUME;
col = day2Pos(item.getStart()) % COLUME;
canvas.drawText("开始", wid * col + widsub, wid * (row - 2), mDayTextPaint);
} else if (item.getType() == END_MONTH && item.getEnd() != -1) {
row = day2Pos(item.getEnd()) / COLUME;
col = day2Pos(item.getEnd()) % COLUME;
canvas.drawText("结束", wid * col + widsub, wid * (row - 2), mDayTextPaint);
} else if (item.getType() == SAME_MONTH && item.getEnd() != -1) {
if (item.getStart() != -1) {
row = day2Pos(item.getStart()) / COLUME;
col = day2Pos(item.getStart()) % COLUME;
canvas.drawText("开始", wid * col + widsub, wid * (row - 2), mDayTextPaint);
}
if (item.getEnd() != -1) {
row = day2Pos(item.getEnd()) / COLUME;
col = day2Pos(item.getEnd()) % COLUME;
canvas.drawText("结束", wid * col + widsub, wid * (row - 2), mDayTextPaint);
}
}
}
// private void drawWeekDay(Canvas canvas){
// float wid = mWidth / weeks.length;
// for (int i = 0; i < weeks.length; i++){
// canvas.drawText(weeks[i],wid*i+wid/2,WEEK_HEIGHT / 2 - mBottomsub - mTopsub,mDayNumberPaint);
// }
// }
/**
* 求本月的x号对应的位置,如果4月1日是四月第一个星期三,那么返回值为1日在该项对应的位置:3(从0开始)
*
* @param day
* @return
*/
private int day2Pos(int day) {
return day - 1 + item.getPos1st();
}
private void drawDayNumberBackgroung(Canvas canvas) {
float wid = mWidth / COLUME;
float widsub = wid / 2;
// float r = widsub - ITEM_PADDING;
int row;
int col;
switch (item.getType()) {
case START_MONTH:
for (int i = item.getStart(); i <= item.getEnd() && i > 0; i++) {
if (i == item.getStart()) {
mDaySlectedBackGrountPaint.setColor(getResources().getColor(R.color.color_6191FB));
} else {
mDaySlectedBackGrountPaint.setColor(getResources().getColor(R.color.color_61CAFB));
}
row = day2Pos(i) / COLUME;
col = day2Pos(i) % COLUME;
// canvas.drawCircle(col * wid + widsub,row * wid +WEEK_HEIGHT+widsub,r,mDaySlectedBackGrountPaint);
canvas.drawRect(col * wid, row * wid, (col + 1) * wid, (row + 1) * wid, mDaySlectedBackGrountPaint);
}
break;
case MID_MONTH:
mDaySlectedBackGrountPaint.setColor(getResources().getColor(R.color.color_61CAFB));
for (int i = 1; i <= Utils.getDaysInMonth(item.getMonth(), item.getYear()); i++) {
row = day2Pos(i) / COLUME;
col = day2Pos(i) % COLUME;
// canvas.drawCircle(col * wid + widsub,row * wid +WEEK_HEIGHT+widsub,r,mDaySlectedBackGrountPaint);
canvas.drawRect(col * wid, row * wid, (col + 1) * wid, (row + 1) * wid, mDaySlectedBackGrountPaint);
}
break;
case SAME_MONTH:
for (int i = item.getStart(); i <= item.getEnd() && i > 0; i++) {
if (i == item.getStart() || i == item.getEnd()) {
mDaySlectedBackGrountPaint.setColor(getResources().getColor(R.color.color_6191FB));
} else {
mDaySlectedBackGrountPaint.setColor(getResources().getColor(R.color.color_61CAFB));
}
row = day2Pos(i) / COLUME;
col = day2Pos(i) % COLUME;
// canvas.drawCircle(col * wid + widsub,row * wid +WEEK_HEIGHT+widsub,r,mDaySlectedBackGrountPaint);
canvas.drawRect(col * wid, row * wid, (col + 1) * wid, (row + 1) * wid, mDaySlectedBackGrountPaint);
}
break;
case END_MONTH:
for (int i = item.getStart(); i <= item.getEnd(); i++) {
if (i == item.getEnd()) {
mDaySlectedBackGrountPaint.setColor(getResources().getColor(R.color.color_6191FB));
} else {
mDaySlectedBackGrountPaint.setColor(getResources().getColor(R.color.color_61CAFB));
}
row = day2Pos(i) / COLUME;
col = day2Pos(i) % COLUME;
// canvas.drawCircle(col * wid + widsub,row * wid +WEEK_HEIGHT+widsub,r,mDaySlectedBackGrountPaint);
canvas.drawRect(col * wid, row * wid, (col + 1) * wid, (row + 1) * wid, mDaySlectedBackGrountPaint);
}
break;
default:
break;
}
}
/**
* 将今天以前的日期置灰
* @param canvas
*/
private void drawDayNumber(Canvas canvas) {
float wid = mWidth / COLUME;
float widsub = wid / 2;
float offset = widsub + WEEK_HEIGHT - mBottomsub - mTopsub;
int row;
int col;
int pos1st = item.getPos1st();
//获取每个月总天数
int dayCount = Utils.getDaysInMonth(item.getMonth(), item.getYear());
int nowMonth = TimeUtil.getNowMonth();
int nowDay = TimeUtil.getNowDay();
for (int i = 0; i < dayCount; i++) {
row = (pos1st + i) / COLUME;
col = (pos1st + i) % COLUME;
if (item.getMonth() == nowMonth && i < (nowDay - 1)) {
mDayNumberPaint.setColor(getResources().getColor(R.color.color_C4C4C4));
} else if (((item.getType() == START_MONTH || item.getType() == SAME_MONTH) && i + 1 == item.getStart())
|| ((item.getType() == END_MONTH || item.getType() == SAME_MONTH) && i + 1 == item.getEnd())
&& i >= nowDay - 1) {
mDayNumberPaint.setColor(Color.BLACK);
} else if (i >= nowDay - 1) {
mDayNumberPaint.setColor(Color.BLACK);
}
canvas.drawText((i + 1) + "", wid * col + widsub, wid * row + offset, mDayNumberPaint);
}
// for (int i = item.getPos1st(); i < Utils.getDaysInMonth(item.getMonth(),item.getYear())+item.getPos1st()-1; i++){
// row = i / COLUME;
// col = i % COLUME;
// canvas.drawText(i+"",wid * col+widsub,wid * row+offset,mDayNumberPaint);
// }
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float wid = mWidth / COLUME;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
// float x = event.getX();
// float y = event.getY();
// if (y < WEEK_HEIGHT || y > WEEK_HEIGHT + wid * 6){
// break;
// }
// int row = (int) ((y - WEEK_HEIGHT) / wid);
// int col = (int)( x / wid);
// int pos = row * COLUME + col;
// Log.d("ldx","pos:"+pos);
// int endPos = Utils.getDaysInMonth(item.getMonth(),item.getYear()) +item.getPos1st() - 1;
// if (pos <= endPos && pos >= item.getPos1st()) {
if (selectedStart == -1){ //选择开始时间
selectedStart = row * COLUME + col;
selectedEnd = selectedStart;
}else if (selectedStart == selectedEnd){ //选择结束时间
selectedEnd = row * COLUME + col;
if (selectedEnd < selectedStart){ //如果选择的结束时间早于开始时间
selectedEnd = -1;
selectedStart = -1;
}
}else { //重新选择时间
selectedStart = row * COLUME + col;
selectedEnd = selectedStart;
}
invalidate();
//
// mControler.viewClicked(item,pos-item.getPos1st()+1);
// Log.d("ldx","real pos"+(pos-item.getPos1st()+1));
Toast.makeText(getContext(),"row,col:"+row+","+col,Toast.LENGTH_SHORT).show();
// }
break;
case MotionEvent.ACTION_UP:
float x = event.getX();
float y = event.getY();
if (y < WEEK_HEIGHT || y > WEEK_HEIGHT + wid * 6) {
break;
}
int row = (int) ((y - WEEK_HEIGHT) / wid);
int col = (int) (x / wid);
int pos = row * COLUME + col;
Log.d("ldx", "pos:" + (pos - item.getPos1st() + 1));
int nowMonth = TimeUtil.getNowMonth();
int nowDay = TimeUtil.getNowDay();
if (item.getMonth() == nowMonth && (pos - item.getPos1st() + 1) <= nowDay - 1){
return true;
}
int endPos = Utils.getDaysInMonth(item.getMonth(), item.getYear()) + item.getPos1st() - 1;
if (pos <= endPos && pos >= item.getPos1st()) {
// if (selectedStart == -1){ //选择开始时间
// selectedStart = row * COLUME + col;
// selectedEnd = selectedStart;
// }else if (selectedStart == selectedEnd){ //选择结束时间
// selectedEnd = row * COLUME + col;
// if (selectedEnd < selectedStart){ //如果选择的结束时间早于开始时间
// selectedEnd = -1;
// selectedStart = -1;
// }
// }else { //重新选择时间
// selectedStart = row * COLUME + col;
// selectedEnd = selectedStart;
// }
// invalidate();
mControler.viewClicked(item, pos - item.getPos1st() + 1);
Log.d("ldx", "real pos" + (pos - item.getPos1st() + 1)+ "-----"+item.getMonth());
}
break;
}
return true;
}
public void setItem(ItemBean item) {
this.item = item;
}
// public int getDayCount() {
// return dayCount;
// }
//
// public void setDayCount(int dayCount) {
// this.dayCount = dayCount;
// }
public void setmControler(Controler mControler) {
this.mControler = mControler;
}
}
这个里面主要做的就是将页面的内容绘制出来,以及选择开始日期到结束日期时颜色,我改的超过当前日期设置为灰色并不可选择
DatePickerView这个好像是设置基础显示页面时顶上的星期条目
public class DatePickerView extends RelativeLayout {
private String[] weekDayTitle = {"日","一","二","三","四","五","六"};
private Context mContext;
private LinearLayout llWeekDayTitle;
private RelativeLayout rlListViewContainer;
private TextView yearMonthTitle;
private ListView datePickListView;
private Controler mControler;
private int lastFirstVisibleItem = -1;
private ArrayList<ItemBean> items;
public DatePickerView(Context context) {
super(context);
}
public DatePickerView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = getContext();
init();
addWeekTitle();
addMonthTitleAndListView();
}
private void init(){
}
/**
* 将星期几的标题加入到view中
*/
private void addWeekTitle(){
llWeekDayTitle = new LinearLayout(mContext);
llWeekDayTitle.setId(R.id.ll_week_title);
llWeekDayTitle.setOrientation(LinearLayout.HORIZONTAL);
llWeekDayTitle.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
for(int i = 0; i < weekDayTitle.length; i++){
TextView tv = new TextView(mContext);
if (i == 0 || i == weekDayTitle.length - 1){
tv.setTextColor(Color.RED);
}
tv.setText(weekDayTitle[i]);
tv.setGravity(Gravity.CENTER);
tv.setLayoutParams(new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT,1.0f));
tv.setPadding(0, Utils.dp2Px(mContext,10),0,Utils.dp2Px(mContext,10));
llWeekDayTitle.addView(tv);
}
addView(llWeekDayTitle);
}
/**
* 将显示月份的标题和listview加入到view中
*/
private void addMonthTitleAndListView(){
rlListViewContainer = new RelativeLayout(mContext);
LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.BELOW,llWeekDayTitle.getId());
rlListViewContainer.setLayoutParams(lp);
datePickListView = new ListView(mContext);
datePickListView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
datePickListView.setSelector(new ColorDrawable());
rlListViewContainer.addView(datePickListView);
yearMonthTitle = new TextView(mContext);
yearMonthTitle.setPadding(0,Utils.dp2Px(mContext,5),0,Utils.dp2Px(mContext,5));
yearMonthTitle.setGravity(Gravity.CENTER);
yearMonthTitle.setBackgroundColor(getResources().getColor(R.color.color_D8D8D8));
LayoutParams tvLp = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
tvLp.addRule(RelativeLayout.ALIGN_PARENT_TOP,TRUE);
yearMonthTitle.setLayoutParams(tvLp);
rlListViewContainer.addView(yearMonthTitle);
addView(rlListViewContainer);
}
/**
* 设置ArrayList- 之后,重新设置ListView的Adapt和Controler
*/
private void resetControlerAndListView(){
mControler = new Controler(items);
DatePickerListAdapter datePickerListAdapter = new DatePickerListAdapter(mContext,items,mControler);
mControler.setDatePickerListAdapter(datePickerListAdapter);
datePickListView.setAdapter(datePickerListAdapter);
datePickListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
Log.d("ldx","firstVisibleItem:"+firstVisibleItem);
if (firstVisibleItem != lastFirstVisibleItem) {
MarginLayoutParams params = (MarginLayoutParams) yearMonthTitle.getLayoutParams();
params.topMargin = 0;
yearMonthTitle.setLayoutParams(params);
StringBuilder sb = new StringBuilder();
sb.append(items.get(firstVisibleItem).getYear())
.append("年")
.append(items.get(firstVisibleItem).getMonth())
.append("月");
yearMonthTitle.setText(sb.toString());
}
View childView = view.getChildAt(0);
if (childView != null) {
// int titleHeight = tv_titles.getHeight();
int titleBottom = yearMonthTitle.getHeight();
int bottom = childView.getBottom();
MarginLayoutParams params = (MarginLayoutParams) yearMonthTitle.getLayoutParams();
if (bottom < titleBottom) {
float pushedDistance = bottom - titleBottom;
params.topMargin = (int) pushedDistance;
yearMonthTitle.setLayoutParams(params);
} else {
if (params.topMargin != 0) {
params.topMargin = 0;
yearMonthTitle.setLayoutParams(params);
}
}
}
lastFirstVisibleItem = firstVisibleItem;
}
});
}
public void setItems(ArrayList<ItemBean> items) {
this.items = items;
resetControlerAndListView();
}
/**
* 设置选择入住时间和离店时间后执行的回调函数
* @param startEndDaySelectListener
*/
public void setStartEndDaySelectListener(StartEndDayClickListener startEndDaySelectListener){
mControler.setListener(startEndDaySelectListener);
}
public ArrayList<ItemBean> getItems() {
return items;
}
}
主要是这个ItemBean,用来存年月日,也是选中后日期的bean类
public class ItemBean {
/**
* 该项对应的年份
*/
private int year;
/**
* 该项对应的月份
*/
private int month;
/**
* 该月份被选中的第一天
*/
private int start = -1;
/**
* 该月份被选中的最后一天
*/
private int end = -1;
/**
* 该月份的类型
* SAME_MONTH 入住和离店在同一个月,从start到end被选中
* START_MONTH 入住对应的月份,从start到该月最后一天被选中
* END_MONTH 离店对应的月份,从1号到end被选中
*/
private int type;
/**
* 该月的1号对应的位置
* 如果5月1号为五月的第一个星期四,则pos1st为4(从0开始,星期日为0)
*/
private int pos1st;
/**
* 该月份里的节假日
*/
private ArrayList<HolidayItemBean> holidayItems;
/**
* 用来计算pos1st
*/
private boolean isclick;
private Calendar calendar;
public ItemBean(){
}
public ItemBean(int year, int month) {
this.month = month;
this.year = year;
calendar = Calendar.getInstance();
calendar.set(year,month-1,1);
pos1st = calendar.get(Calendar.DAY_OF_WEEK) - 1;
holidayItems = new ArrayList<>();
// holidayItems.add(new HolidayItemBean(6,""));
// holidayItems.add(new HolidayItemBean(10,""));
}
public ArrayList<HolidayItemBean> getHolidayItems() {
return holidayItems;
}
public void setHolidayItems(ArrayList<HolidayItemBean> holidayItems) {
this.holidayItems = holidayItems;
}
public int getPos1st() {
return pos1st;
}
public void setPos1st(int pos1st) {
this.pos1st = pos1st;
}
public int getEnd() {
return end;
}
public void setEnd(int end) {
this.end = end;
}
public int getStart() {
return start;
}
public void setStart(int start) {
this.start = start;
}
public void setType(int type) {
this.type = type;
}
public int getType(){
return type;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public boolean isIsclick() {
return isclick;
}
public void setIsclick(boolean isclick) {
this.isclick = isclick;
}
}
然后就是这个HolidayItemBean我是真的菜,不敢随便描述大佬的类··
public class HolidayItemBean {
private int day;
private String name;
public HolidayItemBean(int day, String name) {
this.day = day;
this.name = name;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
DatePickerListAdapter这个适配器主要是用来显示时间列表的,也就是title与下面日期的适配器
public class DatePickerListAdapter extends BaseAdapter{
private Context mContext;
private ArrayList<ItemBean> items;
private Controler mControler;
public DatePickerListAdapter(Context context, ArrayList<ItemBean> items, Controler controler){
this.mContext = context;
this.items = items;
this.mControler = controler;
}
@Override
public int getCount() {
return items.size();
}
@Override
public Object getItem(int position) {
return items.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view;
final ViewHolder viewHolder;
if (convertView == null){
view = LayoutInflater.from(mContext).inflate(R.layout.item_day_picker,null);
viewHolder = new ViewHolder(view);
viewHolder.itemView.setmControler(mControler);
view.setTag(viewHolder);
}else{
view = convertView;
viewHolder = (ViewHolder)view.getTag();
}
viewHolder.itemView.setItem(items.get(position));
viewHolder.itemView.invalidate();
StringBuilder sb = new StringBuilder();
sb.append(items.get(position).getYear())
.append("年")
.append(items.get(position).getMonth())
.append("月");
viewHolder.tv_year_month.setText(sb.toString());
return view;
}
private static class ViewHolder{
private DatePickerItemView itemView;
private TextView tv_year_month;
public ViewHolder(View view){
itemView = (DatePickerItemView)view.findViewById(R.id.item);
tv_year_month = (TextView) view.findViewById(R.id.tv_year_month);
}
}
}
public interface StartEndDayClickListener {
void startDayClicked(ItemBean item, int day);
void endDayClicked(ItemBean startItem, int startDay, ItemBean endItem, int endDay);
}
主要用的几个工具类描述一下,Utils用来返回当前月的天数,大佬的这个有点问题,改了改,现在对应月份应该没问题
public class Utils {
//传入年和月份,获取该月的天数
public static int getDaysInMonth(int month, int year) {
month = month - 1;
switch (month) {
case Calendar.JANUARY:
case Calendar.MARCH:
case Calendar.MAY:
case Calendar.JULY:
case Calendar.AUGUST:
case Calendar.OCTOBER:
case Calendar.DECEMBER:
case Calendar.APRIL:
case Calendar.JUNE:
case Calendar.SEPTEMBER:
case Calendar.NOVEMBER:
case Calendar.FEBRUARY:
return TimeUtil.getMonthLastDay(year,month + 1);
default:
throw new IllegalArgumentException("Invalid Month");
}
}
public static int dp2Px(Context context, float dp) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dp * scale + 0.5f);
}
}
TimeUtil这个工具类呢,主要是用来返回当前的年份,月份,几号
public class TimeUtil {
//获取当天的开始时间
public static Date getDayBegin() {
Calendar cal = new GregorianCalendar();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
return cal.getTime();
}
//获取当天的结束时间
public static Date getDayEnd() {
Calendar cal = new GregorianCalendar();
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
return cal.getTime();
}
//获取昨天的开始时间
public static Date getBeginDayOfYesterday() {
Calendar cal = new GregorianCalendar();
cal.setTime(getDayBegin());
cal.add(Calendar.DAY_OF_MONTH, -1);
return cal.getTime();
}
//获取昨天的结束时间
public static Date getEndDayOfYesterDay() {
Calendar cal = new GregorianCalendar();
cal.setTime(getDayEnd());
cal.add(Calendar.DAY_OF_MONTH, -1);
return cal.getTime();
}
//获取明天的开始时间
public static Date getBeginDayOfTomorrow() {
Calendar cal = new GregorianCalendar();
cal.setTime(getDayBegin());
cal.add(Calendar.DAY_OF_MONTH, 1);
return cal.getTime();
}
//获取明天的结束时间
public static Date getEndDayOfTomorrow() {
Calendar cal = new GregorianCalendar();
cal.setTime(getDayEnd());
cal.add(Calendar.DAY_OF_MONTH, 1);
return cal.getTime();
}
/**
* 获取今年是哪一年
*
* @return
*/
@SuppressLint("WrongConstant")
public static Integer getNowYear() {
Date date = new Date();
GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
gc.setTime(date);
return Integer.valueOf(gc.get(1));
}
/**
* 获取本月是哪一月
*
* @return
*/
@SuppressLint("WrongConstant")
public static int getNowMonth() {
Date date = new Date();
GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
gc.setTime(date);
return gc.get(2) + 1;
}
/**
* 获取今天是几号
*
* @return
*/
public static int getNowDay() {
Date date = new Date();
GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
gc.setTime(date);
return gc.get(Calendar.DAY_OF_MONTH);
}
/**
* 两个日期相减得到的天数
*
* @return
*/
public static int getDiffDays(Date beginDate, Date endDate) {
if (beginDate == null || endDate == null) {
throw new IllegalArgumentException("getDiffDays param is null!");
}
long diff = (endDate.getTime() - beginDate.getTime())
/ (1000 * 60 * 60 * 24);
int days = new Long(diff).intValue();
return days;
}
/**
* 两个日期相减得到的毫秒数
*
* @param beginDate
* @param endDate
* @return
*/
public static long dateDiff(Date beginDate, Date endDate) {
long date1ms = beginDate.getTime();
long date2ms = endDate.getTime();
return date2ms - date1ms;
}
/**
* 获取两个日期中的最大日期
*
* @param beginDate
* @param endDate
* @return
*/
public static Date max(Date beginDate, Date endDate) {
if (beginDate == null) {
return endDate;
}
if (endDate == null) {
return beginDate;
}
if (beginDate.after(endDate)) {
return beginDate;
}
return endDate;
}
//获取两个日期中的最小日期
public static Date min(Date beginDate, Date endDate) {
if (beginDate == null) {
return endDate;
}
if (endDate == null) {
return beginDate;
}
if (beginDate.after(endDate)) {
return endDate;
}
return beginDate;
}
//返回某月该季度的第一个月
public static Date getFirstSeasonDate(Date date) {
final int[] SEASON = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4};
Calendar cal = Calendar.getInstance();
cal.setTime(date);
int sean = SEASON[cal.get(Calendar.MONTH)];
cal.set(Calendar.MONTH, sean * 3 - 3);
return cal.getTime();
}
//返回某个日期下几天的日期
public static Date getNextDay(Date date, int i) {
Calendar cal = new GregorianCalendar();
cal.setTime(date);
cal.set(Calendar.DATE, cal.get(Calendar.DATE) + i);
return cal.getTime();
}
//返回某个日期前几天的日期
public static Date getFrontDay(Date date, int i) {
Calendar cal = new GregorianCalendar();
cal.setTime(date);
cal.set(Calendar.DATE, cal.get(Calendar.DATE) - i);
return cal.getTime();
}
/**
* 将Date类型转换为日期字符串
*
* @param date Date对象
* @param type 需要的日期格式(yyyy-MM-dd HH:mm:ss)
* @return 按照需求格式的日期字符串
*/
public static String formatDate(Date date, String type) {
try {
SimpleDateFormat df = new SimpleDateFormat(type);
return df.format(date);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* 某月最后一天
*
* @param year
* @param month
* @return
*/
public static int getLastDayOfMonth(int year, int month) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1);
int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH);
cal.set(Calendar.DAY_OF_MONTH, lastDay);
return lastDay;
}
/**
* 获得指定日期前几个月相差多少天(包含当天的)
*
* @param startDate
* @param month
* @return
*/
public static int getDiffDays(Date startDate, int month) {
Date date = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(calendar.MONTH, -month);
Date afterTime = calendar.getTime();
calendar.setTime(afterTime);
calendar.add(calendar.DAY_OF_MONTH, +1);
Date realTime = calendar.getTime();
int diffDays = getDiffDays(realTime, startDate);
return diffDays;
}
/**
* 获得指定日期前几年相差多少天(包含当天的)
*
* @param startDate
* @param year
* @return
*/
public static int getDiffDaysWithYear(Date startDate, int year) {
Date date = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(calendar.YEAR, -year);
Date afterTime = calendar.getTime();
calendar.setTime(afterTime);
calendar.add(calendar.DAY_OF_YEAR, +1);
Date realTime = calendar.getTime();
int diffDays = getDiffDays(realTime, startDate);
return diffDays;
}
/**
* 得到年
*
* @param date Date对象
* @return 年
*/
public static int getYear(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
return c.get(Calendar.YEAR);
}
/**
* 得到月
*
* @param date Date对象
* @return 月
*/
public static int getMonth(Date date) {
Calendar c = Calendar.getInstance();
c.setTime(date);
return c.get(Calendar.MONTH) + 1;
}
/**
* 得到指定月的天数
* */
public static int getMonthLastDay(int year, int month)
{
Calendar a = Calendar.getInstance();
a.set(Calendar.YEAR, year);
a.set(Calendar.MONTH, month - 1);
a.set(Calendar.DATE, 1);//把日期设置为当月第一天
a.roll(Calendar.DATE, -1);//日期回滚一天,也就是最后一天
int maxDate = a.get(Calendar.DATE);
return maxDate;
}
}
Controler很牛逼的类!
虽然上面的Created by是我,但是一看就知道自己几斤几两,这必不是我···
public class Controler {
/**
* 日历要显示的所有月份
*/
private ArrayList<ItemBean> items;
/**
* 入住对应的月份
*/
private ItemBean startItem;
/**
* 离店对应的月份
*/
private ItemBean endItem;
/**
* 入住的日期(几号)
*/
private int startDay;
/**
*离店的日期(几号)
*/
private int endDay;
/**
* 是否为首次点击,即是否在选择入住时间
*/
private boolean first; //是否为首次点击
/**
* ListView的Adapter
*/
private DatePickerListAdapter datePickerListAdapter;
/**
* 当选择完入住、离店日期的时候执行的回调函数
*/
private StartEndDayClickListener mListener;
public Controler(ArrayList<ItemBean> items){
// endItem = new Item();
first = true;
startDay = -1;
endDay = -1;
this.items = items;
}
/**
* 当点击一个日期时,调用该方法
* @param item
* @param day
*/
public void viewClicked(ItemBean item, int day){
if (first){ //选择入住时间
resetAll(); //将所有月份都设置为未被选中
startItem = item;
startItem.setYear(item.getYear());
startItem.setMonth(item.getMonth());
startItem.setType(DatePickerItemView.START_MONTH); //设置此月份为入住对应的月份
startItem.setStart(day);
startItem.setEnd(day);
endItem = item;
endItem.setYear(item.getYear());
endItem.setMonth(item.getMonth());
startDay = day;
endDay = day;
if (mListener != null){
mListener.startDayClicked(item,day); //选择开始时间的回调函数
}
first = false;
Log.d("ldx","11111");
Log.d("ldx",startItem.getYear()+","+startItem.getMonth());
}else { //已经选择过入住时间,此次为设置离店时间
Log.d("ldx","22222");
//如果第二次选择的时间晚于开始时间
if (item.getYear() > startItem.getYear()
|| (item.getYear() == startItem.getYear() && item.getMonth() > startItem.getMonth())
||(item.getYear() == startItem.getYear() && item.getMonth() == startItem.getMonth() && startDay <= day)){
endItem = item;
endItem.setYear(item.getYear());
endItem.setMonth(item.getMonth());
// endItem = item;
endDay = day;
if (endItem.getMonth() == startItem.getMonth() && endItem.getYear() == startItem.getYear()){
item.setType(DatePickerItemView.SAME_MONTH); //入住和离店在同一个月
Log.d("ldx","2.11111");
Log.d("ldx",startItem.getYear()+","+startItem.getMonth()+"|"+endItem.getYear()+","+endItem.getMonth());
}else {
//入住和离店不在一个月
startItem.setEnd(Utils.getDaysInMonth(startItem.getMonth(),startItem.getYear()));
item.setType(DatePickerItemView.END_MONTH);
item.setStart(1);
Log.d("ldx","2.222222");
}
setMidMonth(); //把入住时间和离店时间中间的月份的类型设置为MID_MONTH
item.setEnd(day);
if (mListener != null){
mListener.endDayClicked(startItem,startDay,item,day); //结束时间的回调函数
}
first = true;
}else { //如果第二次点击的时间早于开始的时间,相当于选择入住时间,所以逻辑和第一种情况相同
resetAll();
startItem = item;
startItem.setYear(item.getYear());
startItem.setMonth(item.getMonth());
startDay = day;
startItem.setType(DatePickerItemView.START_MONTH); //设置此月份为入住对应的月份
startItem.setStart(day);
startItem.setEnd(day);
endItem = item;
endItem.setYear(item.getYear());
endItem.setMonth(item.getMonth());
endDay = day;
if (mListener != null){
mListener.startDayClicked(item,day); //选择开始时间的回调函数
}
first = false;
Log.d("ldx","33333333");
}
}
datePickerListAdapter.notifyDataSetChanged(); //刷新ListView
}
/**
* 将入住和离店时间之间的月份的类型设为MID_MONTH
*/
private void setMidMonth(){
int startIndex = items.indexOf(startItem);
int endIndex = items.indexOf(endItem);
for (int i = startIndex + 1; i < endIndex; i++){
items.get(i).setType(DatePickerItemView.MID_MONTH);
items.get(i).setStart(1);
items.get(i).setEnd(Utils.getDaysInMonth(items.get(i).getMonth(),items.get(i).getYear()));
}
}
/**
* 将所有月份都设置为未被选中
*/
private void resetAll(){
for (int i = 0; i < items.size(); i++){
items.get(i).setStart(-1);
items.get(i).setEnd(-1);
items.get(i).setType(-1);
}
}
public void setListener(StartEndDayClickListener mListener) {
this.mListener = mListener;
}
public void setItems(ArrayList<ItemBean> items) {
this.items = items;
}
public void setDatePickerListAdapter(DatePickerListAdapter datePickerListAdapter) {
this.datePickerListAdapter = datePickerListAdapter;
}
public int getEndDay() {
return endDay;
}
public ItemBean getEndItem() {
return endItem;
}
public int getStartDay() {
return startDay;
}
public ItemBean getStartItem() {
return startItem;
}
}
下面是我写的了!!因为怕有问题,又新开了个项目跑了一遍,哈哈哈哈!MainActivity!!
public class MainActivity extends AppCompatActivity {
private ArrayList<ItemBean> items;
private int flag = 0;
private static final int STARTMONTH = 1;
private static final int ENDMONTH = 12;
private String endTime = "";
private String startTime = "";
private String startEquals = "";
private DatePickerView datePicker;
private Button btnSure;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
datePicker = (DatePickerView) findViewById(R.id.datePicker);
btnSure = (Button) findViewById(R.id.btn_sure);
getEndTime();
btnSure.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if ("".equals(startEquals)) {
Toast.makeText(MainActivity.this, "请选择开始日期", Toast.LENGTH_SHORT).show();
} else if (!"".equals(startEquals) && "".equals(endTime)) {
Toast.makeText(MainActivity.this, "请选择结束日期", Toast.LENGTH_SHORT).show();
} else if (!"".equals(startEquals) && !"".equals(endTime)) {
Toast.makeText(MainActivity.this, startTime + "-------" + endTime, Toast.LENGTH_SHORT).show();
}
}
});
}
/**
* 获取用户选择的时间段
*/
private void getEndTime() {
Integer nowYear = TimeUtil.getNowYear();
int nowMonth = TimeUtil.getNowMonth();
items = new ArrayList<>();
while (true) {
flag = flag + 1;
items.add(new ItemBean(nowYear, nowMonth));
if (nowMonth == ENDMONTH) {
items.add(new ItemBean(nowYear + 1, STARTMONTH));
flag = flag + 1;
}
nowMonth++;
//这里用来设置当前时间选择展示几个月的日期
if (flag >= 5) {
break;
}
}
datePicker.setItems(items);
datePicker.setStartEndDaySelectListener(new StartEndDayClickListener() {
@Override
public void startDayClicked(ItemBean item, int day) {
if (endTime != "") {
endTime = "";
}
StringBuilder sb = new StringBuilder();
sb.append(item.getYear())
.append("-")
.append(item.getMonth())
.append("-")
.append(day);
startEquals = sb.toString();
}
@Override
public void endDayClicked(ItemBean startItem, int startDay, ItemBean endItem, int endDay) {
if ("".equals(startTime)) {
startTime = "";
}
StringBuilder sb = new StringBuilder();
sb.append(endItem.getYear())
.append("-")
.append(endItem.getMonth())
.append("-")
.append(endDay);
StringBuilder sbstart = new StringBuilder();
sbstart.append(startItem.getYear())
.append("-")
.append(startItem.getMonth())
.append("-")
.append(startDay);
startTime = sbstart.toString();
endTime = sb.toString();
}
});
}
}
接下来就是布局里面的:activity_main
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.dateselect.customview.DatePickerView
android:id="@+id/datePicker"
android:layout_above="@id/btn_sure"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.example.dateselect.customview.DatePickerView>
<Button
android:text="确定"
android:id="@+id/btn_sure"
android:layout_alignParentBottom="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
data_item
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/ll_week_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="#EAEAEA">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:paddingBottom="10dp"
android:paddingTop="10dp"
android:text="日"
android:textColor="@color/color_FF6257" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="一"
android:textColor="@color/color_1A2B3A" />
<TextView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="二"
android:textColor="@color/color_1A2B3A" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="三"
android:textColor="@color/color_1A2B3A" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="四"
android:textColor="@color/color_1A2B3A" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="五"
android:textColor="@color/color_1A2B3A" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="六"
android:textColor="@color/color_FF6257" />
</LinearLayout>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/ll_week_title">
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:listSelector="@android:color/transparent" />
<TextView
android:id="@+id/tv_position"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="@color/color_C4C4C4"
android:gravity="center"
android:paddingBottom="5dp"
android:paddingTop="5dp"
android:text="这是第0项" />
</RelativeLayout>
</RelativeLayout>
item_day_picker
<?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="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_year_month"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/color_D8D8D8"
android:gravity="center"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:text="这是第x项" />
<com.example.dateselect.customview.DatePickerItemView
android:id="@+id/item"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
color也给你们!!!!
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#6191FB</color>
<color name="white">#FFFFFF</color>
<color name="black">#000000</color>
<color name="transparent">#00000000</color>
<color name="color_99000000">#99000000</color>
<color name="color_66000000">#66000000</color>
<color name="color_80FFFFFF">#80FFFFFF</color>
<color name="color_20A1B2C3">#20A1B2C3</color>
<color name="color_701A2B3A">#701A2B3A</color>
<color name="color_8D9093">#8D9093</color>
<color name="color_6191FB">#6191FB</color>
<color name="color_61CAFB">#61CAFB</color>
<color name="color_FF6257">#FF6257</color>
<color name="color_353442">#353442</color>
<color name="color_F6F7FB">#F6F7FB</color>
<color name="color_F7F8FC">#F7F8FC</color>
<color name="color_999999">#999999</color>
<color name="color_C4C4C4">#C4C4C4</color>
<color name="color_D8D8D8">#D8D8D8</color>
<color name="color_F4F4F4">#F4F4F4</color>
<color name="color_1A2B3A">#1A2B3A</color>
<color name="color_EEF3FF">#EEF3FF</color>
<color name="color_d4d4d4">#d4d4d4</color>
<color name="color_ededed">#ededed</color>
<color name="color_FFFFFF">#FFFFFF</color>
<color name="color_FAFAFA">#FAFAFA</color>
</resources>
这是原作者,我实在找不到了,,没法转载你的地址,不好意思··