Android项目实战(二十九):酒店预定日期选择

时间:2024-04-07 16:04:43

先看需求效果图:

Android项目实战(二十九):酒店预定日期选择     Android项目实战(二十九):酒店预定日期选择       Android项目实战(二十九):酒店预定日期选择

几个需求点:

1、显示当月以及下个月的日历 (可自行拓展更多月份)

2、首次点击选择“开始日期”,再次点击选择"结束日期"

  (1)、如果“开始日期” “结束日期” 相同 Android项目实战(二十九):酒店预定日期选择

  (2)、如果“开始日期” “结束日期” 不同,且“结束日期” 晚于 “开始日期” Android项目实战(二十九):酒店预定日期选择

  (3)、如果“结束日期” 早于 “开始日期” ,重置当前 日期 为 “开始日期”

3、选择的“开始日期” “结束日期” 显示在 Android项目实战(二十九):酒店预定日期选择

难点:

1、 获取当月以及下个月的日历,一个月多少天,每天星期几

2、 判断每个日子的点 与  “开始日期” “结束日期” 的关系,用于显示背景色

技术储备:

1、浅谈RecyclerView(完美替代ListView,GridView)

2、Android项目实战(十三):浅谈EventBus

-----------------------------------------------------------------------------------------------------------------------

实现思路:

1、一个外部RecyclerView 用于显示 日历,每一个item 都用于显示一个月的日历             ,下面都称为 外部RecyclerView

2、外部RecyclerView的每一个Item 内再用一个RecyclerView显示该月的所有日期,每一天都是一个item   ,下面都称为 内部RecyclerView

3、点击内部RecyclerView的item 日期,添加监听事件,根据是否开始、结束、中间日期来显示 相应的选中背景

Android项目实战(二十九):酒店预定日期选择

代码实现:

1、代码框架总览

Android项目实战(二十九):酒店预定日期选择

2、实体类

(1)、月份类,外部RecyclerView的数据源实体类

/**
* Created by xqx on 2017/1/17.
* 代表日历上的每一个月份
*/
public class MonthTimeEntity { private int year; //该月份 属于哪一年
private int month; // 该月 是哪一个月份 public MonthTimeEntity(int year, int month) {
this.year = year;
this.month = 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;
}
}

MonthTimeEntity.java

(2)、日期类,内部RecyclerView的数据源实体类

/**
* Created by xqx on 2017/1/17.
* 日历中每一个月中的 每一个天数
*/
public class DayTimeEntity {
private int day ; //日期,几号
private int month; //属于的月份
private int year; //属于的年份 private int monthPosition; //属于的月份位置,注意是该日期属于的月份在外层列表中的position,不是月份
private int dayPosition; //属于的日期位置,注意是该日期在每个月(内层列表)中的位置 public DayTimeEntity(int day, int month, int year, int monthPosition) {
this.day = day;
this.month = month;
this.year = year;
this.monthPosition = monthPosition;
} public int getDay() {
return day;
} public void setDay(int day) {
this.day = day;
} 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 int getMonthPosition() {
return monthPosition;
} public void setMonthPosition(int monthPosition) {
this.monthPosition = monthPosition;
} public int getDayPosition() {
return dayPosition;
} public void setDayPosition(int dayPosition) {
this.dayPosition = dayPosition;
} }

DayTimeEntity.java

(3)、更新类,用于选择 “开始日期”、“结束日期”之后的刷新适配器操作

/**
* Created by xqx on 2017/1/17.
* 用于EventBus发送消息
*/
public class UpdataCalendar {
}

UpdataCalendar.java

3、主要实现

(1)、主界面布局

上面就是普通的布局形式,日历用一个RecyclerView显示,这个列表的每一个item都用于显示一个月份的所有天数

<?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:orientation="vertical"
> <!--标题栏-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="6dp"
android:background="@color/white"
> <!--标题-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="预定日期"
android:layout_centerInParent="true"
android:textSize="20sp"
/>
</RelativeLayout> <ImageView
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#d9d9d9"
/> <RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f2f4f7"
android:paddingTop="20dp"
>
<TextView
android:id="@+id/plan_time_txt_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始\n时间"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="87dp"
android:layout_marginStart="87dp"
android:background="@mipmap/bg_white_circle"
android:gravity="center"
/>
<TextView
android:id="@+id/plan_time_txt_stop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="结束\n时间"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:layout_marginRight="74dp"
android:layout_marginEnd="74dp"
android:background="@mipmap/bg_white_circle"
android:gravity="center"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#f2f4f7"
android:paddingTop="20dp"
android:paddingBottom="20dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=""
android:text="S"
android:gravity="center"
/> <TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=""
android:text="M"
android:gravity="center"
/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=""
android:text="T"
android:gravity="center"
/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=""
android:text="W"
android:gravity="center"
/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=""
android:text="T"
android:gravity="center"
/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=""
android:text="F"
android:gravity="center" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=""
android:text="S"
android:gravity="center"
/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/plan_time_calender"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:paddingLeft="20dp"
android:paddingRight="20dp"
> </android.support.v7.widget.RecyclerView>
</LinearLayout>

acticity_main.xml

Android项目实战(二十九):酒店预定日期选择

(2)、日历外部RecyclerView的ViewHolder类,可以看出外层RecyclerView 的 item 只需要一个TextView显示几年几月 和 一个RecyclerView显示该月的天数即可

Android项目实战(二十九):酒店预定日期选择

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView; /**
* Created by xqxon 2017/1/17.
*/
public class MonthTimeViewHolder extends RecyclerView.ViewHolder{ public TextView plan_time_txt_month; //文本 2018-1
public RecyclerView plan_time_recycler_content ; //月份里面详细日期的列表
public Context context; //上下文 public MonthTimeViewHolder(View itemView, Context context) {
super(itemView);
this.context = context;
plan_time_recycler_content = (RecyclerView) itemView.findViewById(R.id.plan_time_recycler_content);
plan_time_txt_month = (TextView) itemView.findViewById(R.id.plan_time_txt_month); RecyclerView.LayoutManager layoutManager =
new GridLayoutManager(context,
, // 每行显示item项数目
GridLayoutManager.VERTICAL, //水平排列
false
); plan_time_recycler_content.setLayoutManager(layoutManager);
}
}

MonthTimeViewHolder

(3)、日历外部RecyclerView的item 布局文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"> <TextView
android:id="@+id/plan_time_txt_month"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/blue"
android:textSize="16sp"
android:text="Aug 2017"
android:layout_marginTop="10dp"
android:layout_marginLeft="20dp"
android:layout_marginBottom="10dp"
/> <android.support.v7.widget.RecyclerView
android:id="@+id/plan_time_recycler_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
</android.support.v7.widget.RecyclerView>
</LinearLayout>

item_recycler_timeplan

Android项目实战(二十九):酒店预定日期选择

(4)、Activity

public class MonthTimeActivity extends Activity {

    private ImageButton back;
private TextView startTime; //开始时间
private TextView stopTime; //结束时间 private RecyclerView reycycler;
private MonthTimeAdapter adapter;
private ArrayList<MonthTimeEntity> datas; public static DayTimeEntity startDay;
public static DayTimeEntity stopDay;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); initView();
initData(); EventBus.getDefault().register(this); } private void initData() {
startDay = new DayTimeEntity(,,,);
stopDay = new DayTimeEntity(-,-,-,-);
datas = new ArrayList<>(); Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH)+; c.add(Calendar.MONTH,);
int nextYear = c.get(Calendar.YEAR);
int nextMonth = c.get(Calendar.MONTH)+; datas.add(new MonthTimeEntity(year,month)); //当前月份
datas.add(new MonthTimeEntity(nextYear,nextMonth)); //下个月
adapter = new MonthTimeAdapter(datas, MonthTimeActivity.this);
reycycler.setAdapter(adapter); } private void initView() {
startTime = (TextView) findViewById(R.id.plan_time_txt_start);
stopTime = (TextView) findViewById(R.id.plan_time_txt_stop); reycycler = (RecyclerView) findViewById(R.id.plan_time_calender);
LinearLayoutManager layoutManager =
new LinearLayoutManager(this, // 上下文
LinearLayout.VERTICAL, //垂直布局,
false); reycycler.setLayoutManager(layoutManager);
} public void onEventMainThread(UpdataCalendar event) {
adapter.notifyDataSetChanged();
startTime.setText(startDay.getMonth()+"月"+startDay.getDay()+"日"+"\n");
if (stopDay.getDay() == -) {
stopTime.setText("结束"+"\n"+"时间");
}else{
stopTime.setText(stopDay.getMonth() + "月" + stopDay.getDay() + "日" + "\n");
}
} @Override
protected void onDestroy() {
super.onDestroy();
EventBus.getDefault().unregister(this);
}
}

MonthTimeActivity.java

几个核心点:

 1、 两个静态变量的类 用于标记  开始日期和结束日期,和每个日子进行对比,显示不同的背景色

 public static DayTimeEntity startDay;     //开始日期
public static DayTimeEntity stopDay; //结束日期

2、数据源的初始化

   private void initData() {
startDay = new DayTimeEntity(,,,);
stopDay = new DayTimeEntity(-,-,-,-); //注意这里参数都为 -1 不是随便设的 ,后面会用到
datas = new ArrayList<>();
    
Calendar c = Calendar.getInstance();
int year = c.get(Calendar.YEAR);
int month = c.get(Calendar.MONTH)+; // 获得当前月份的信息, 属于哪一年,哪一月 c.add(Calendar.MONTH,);
int nextYear = c.get(Calendar.YEAR);
int nextMonth = c.get(Calendar.MONTH)+; // 获得当前月份的下一个月份的信息, 属于哪一年,哪一月。 可以以此类推 不限制于 2个月份 datas.add(new MonthTimeEntity(year,month)); //当前月份的对象 ,对象里信息 包括:哪一年,哪一月
datas.add(new MonthTimeEntity(nextYear,nextMonth)); //下个月份的对象
adapter = new MonthTimeAdapter(datas, MonthTimeActivity.this);
reycycler.setAdapter(adapter); }

  

(5)、日历外部RecyclerView的适配器Adapter

/**
* Created by xqx on 2017/1/17.
*/
public class MonthTimeAdapter extends RecyclerView.Adapter<MonthTimeViewHolder>{ private ArrayList<MonthTimeEntity> datas;
private Context context; public MonthTimeAdapter(ArrayList<MonthTimeEntity> datas, Context context) {
this.datas = datas;
this.context = context;
} @Override
public MonthTimeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
MonthTimeViewHolder ret = null;
// 不需要检查是否复用,因为只要进入此方法,必然没有复用
// 因为RecyclerView 通过Holder检查复用
View v = LayoutInflater.from(context).inflate(R.layout.item_recycler_timeplan, parent, false);
ret = new MonthTimeViewHolder(v,context);
return ret;
} @Override
public void onBindViewHolder(MonthTimeViewHolder holder, int position) {
MonthTimeEntity monthTimeEntity = datas.get(position);
holder.plan_time_txt_month.setText(monthTimeEntity.getYear()+"--"+ monthTimeEntity.getMonth()); //显示 几年--几月
//得到该月份的第一天
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, monthTimeEntity.getYear()); //指定年份
calendar.set(Calendar.MONTH, monthTimeEntity.getMonth() - ); //指定月份 Java月份从0开始算
calendar.set(Calendar.DAY_OF_MONTH,); // 指定天数 ,这三行是为了得到 这一年这一月的第一天 int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); //得到该月份第一天 是星期几
ArrayList<DayTimeEntity> days = new ArrayList<DayTimeEntity>();
for (int i = ; i < dayOfWeek-; i++) { //
days.add(new DayTimeEntity(, monthTimeEntity.getMonth(), monthTimeEntity.getYear(),position));
}
calendar.add(Calendar.MONTH, );// 加一个月,变为下月的1号
calendar.add(Calendar.DATE, -);// 减去一天,变为当月最后一天
for (int i = ; i <= calendar.get(Calendar.DAY_OF_MONTH); i++) { //添加 该月份的天数 一号 到 该月的最后一天
days.add(new DayTimeEntity(i, monthTimeEntity.getMonth(), monthTimeEntity.getYear(),position));
} DayTimeAdapter adapter = new DayTimeAdapter(days,context);
holder.plan_time_recycler_content.setAdapter(adapter); } @Override
public int getItemCount() {
int ret = ;
if (datas!=null){
ret = datas.size();
}
return ret;
}
}

MonthTimeAdapter.java

核心代码:

      //得到该月份的第一天
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, monthTimeEntity.getYear()); //指定年份
calendar.set(Calendar.MONTH, monthTimeEntity.getMonth() - 1); //指定月份 Java月份从0开始算
calendar.set(Calendar.DAY_OF_MONTH,1); // 指定天数 ,这三行是为了得到 这一年这一月的第一天 int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK); //得到该月份第一天 是星期几
     for (int i = 0; i < dayOfWeek-1; i++) {                          //
days.add(new DayTimeEntity(0, monthTimeEntity.getMonth(), monthTimeEntity.getYear(),position)); //填充空白天数
}

目的是实现 :比如第一天是星期3 ,那么日历上 星期日,星期一,星期二的位置 要为空白

       意味着一个天数的item getDay() == 0 ,说明这天是空白天数

   
calendar.add(Calendar.MONTH, 1);// 加一个月,变为下月的1号
calendar.add(Calendar.DATE, -1);// 减去一天,变为当月最后一天
for (int i = 1; i <= calendar.get(Calendar.DAY_OF_MONTH); i++) { // 添加 该月份的天数 一号 到 该月的最后一天
days.add(new DayTimeEntity(i, monthTimeEntity.getMonth(), monthTimeEntity.getYear(),position));
}

目的是实现:得到该月份的最后一天是几号,然后从1号到最后一天都作为数据源添加到内部的recyclerview中。

以上是外层Recyclerview(每一个Item是一个月份)的相关代码

-------------------------------------------------------------------------------------------------

(6)  外部RecyclerView的 Item中的内部RecyclerView ,每一个item都是该月份的一天

item布局:  就只有一个textview ,用于显示 几号

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="2dp"
android:paddingTop="6dp"
android:paddingBottom="6dp"
android:id="@+id/select_ly_day"
> <TextView
android:id="@+id/select_txt_day"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:layout_gravity="center"
android:gravity="center"
/> </LinearLayout>

item_recycler_selectday.xml

(7)内部RecyclerView的ViewHolder

**
* Created by xqx on //.
*
*/
public class DayTimeViewHolder extends RecyclerView.ViewHolder{ public TextView select_txt_day; //日期文本
public LinearLayout select_ly_day; //父容器 , 用于点击日期 public DayTimeViewHolder(View itemView) {
super(itemView);
select_ly_day = (LinearLayout) itemView.findViewById(R.id.select_ly_day);
select_txt_day = (TextView) itemView.findViewById(R.id.select_txt_day);
}
}

DayTimeViewHolder.java

(8)内部RecyclerView的适配器Adapter

package com.maiji.calendardemo.selectTime;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup; import com.maiji.calendardemo.MonthTimeActivity;
import com.maiji.calendardemo.R;
import com.maiji.calendardemo.entity.DayTimeEntity;
import com.maiji.calendardemo.entity.UpdataCalendar; import java.util.ArrayList; import de.greenrobot.event.EventBus; /**
* Created by xqx on 2017/1/17.
*/
public class DayTimeAdapter extends RecyclerView.Adapter<DayTimeViewHolder>{ private ArrayList<DayTimeEntity> days;
private Context context; public DayTimeAdapter(ArrayList<DayTimeEntity> days, Context context) {
this.days = days;
this.context = context; } @Override
public DayTimeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
DayTimeViewHolder ret = null;
// 不需要检查是否复用,因为只要进入此方法,必然没有复用
// 因为RecyclerView 通过Holder检查复用
View v = LayoutInflater.from(context).inflate(R.layout.item_recycler_selectday, parent, false);
ret = new DayTimeViewHolder(v); return ret;
} @Override
public void onBindViewHolder(final DayTimeViewHolder holder, final int position) {
final DayTimeEntity dayTimeEntity = days.get(position);
//显示日期
if (dayTimeEntity.getDay()!=) {
holder.select_txt_day.setText(dayTimeEntity.getDay() + "");
holder.select_ly_day.setEnabled(true);
}else{
holder.select_ly_day.setEnabled(false);
}
holder.select_ly_day.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (MonthTimeActivity.startDay.getYear() == ){ // 第一次点击开始的位置,因为开始默认参数是 0,0,0,0
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay()); // 该item 天数的 年月日等信息 赋给 开始日期
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
}else if(MonthTimeActivity.startDay.getYear()> && MonthTimeActivity.stopDay.getYear() ==-){ //已经点击了开始 ,点击结束位置,(默认结束位置-1,-1,-1,-1 说明还没有点击结束位置)
if (dayTimeEntity.getYear()> MonthTimeActivity.startDay.getYear()) {
//如果选中的年份大于开始的年份,说明结束日期肯定大于开始日期 ,合法的 ,将该item的天数的 信息 赋给 结束日期
MonthTimeActivity.stopDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.stopDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.stopDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.stopDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.stopDay.setDayPosition(position);
}else if (dayTimeEntity.getYear() == MonthTimeActivity.startDay.getYear()){
//如果选中的年份 等于 选中的年份
if (dayTimeEntity.getMonth()> MonthTimeActivity.startDay.getMonth()){
//如果改item的天数的月份大于开始日期的月份,说明结束日期肯定大于开始日期 ,合法的 ,将该item的天数的 信息 赋给 结束日期
MonthTimeActivity.stopDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.stopDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.stopDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.stopDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.stopDay.setDayPosition(position);
}else if(dayTimeEntity.getMonth() == MonthTimeActivity.startDay.getMonth()){
//年份月份 都相等
if (dayTimeEntity.getDay() >= MonthTimeActivity.startDay.getDay()){
//判断天数 ,如果 该item的天数的 日子大于等于 开始日期的 日子 ,说明结束日期合法的 ,将该item的天数的 信息 赋给 结束日期
MonthTimeActivity.stopDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.stopDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.stopDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.stopDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.stopDay.setDayPosition(position);
}else{
//天数小与初始 从新选择开始 ,结束日期重置,开始日期为当前的位置的天数的信息
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
MonthTimeActivity.stopDay.setDay(-);
MonthTimeActivity.stopDay.setMonth(-);
MonthTimeActivity.stopDay.setYear(-);
MonthTimeActivity.stopDay.setMonthPosition(-);
MonthTimeActivity.stopDay.setDayPosition(-);
}
}else {
//选中的月份 比开始日期的月份还小,说明 结束位置不合法,结束日期重置,开始日期为当前的位置的天数的信息
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
MonthTimeActivity.stopDay.setDay(-);
MonthTimeActivity.stopDay.setMonth(-);
MonthTimeActivity.stopDay.setYear(-);
MonthTimeActivity.stopDay.setMonthPosition(-);
MonthTimeActivity.stopDay.setDayPosition(-);
} }else{
//选中的年份 比开始日期的年份还小,说明 结束位置不合法,结束日期重置,开始日期为当前的位置的天数的信息
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
MonthTimeActivity.stopDay.setDay(-);
MonthTimeActivity.stopDay.setMonth(-);
MonthTimeActivity.stopDay.setYear(-);
MonthTimeActivity.stopDay.setMonthPosition(-);
MonthTimeActivity.stopDay.setDayPosition(-);
}
}else if(MonthTimeActivity.startDay.getYear()> && MonthTimeActivity.startDay.getYear()>){ //已经点击开始和结束 第三次点击 ,重新点击开始
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
MonthTimeActivity.stopDay.setDay(-);
MonthTimeActivity.stopDay.setMonth(-);
MonthTimeActivity.stopDay.setYear(-);
MonthTimeActivity.stopDay.setMonthPosition(-);
MonthTimeActivity.stopDay.setDayPosition(-);
}
EventBus.getDefault().post(new UpdataCalendar()); // 发消息刷新适配器,目的为了显示日历上各个日期的背景颜色
}
}); if (MonthTimeActivity.startDay.getYear()== dayTimeEntity.getYear() && MonthTimeActivity.startDay.getMonth() == dayTimeEntity.getMonth() && MonthTimeActivity.startDay.getDay() == dayTimeEntity.getDay()
&& MonthTimeActivity.stopDay.getYear()== dayTimeEntity.getYear() && MonthTimeActivity.stopDay.getMonth() == dayTimeEntity.getMonth() && MonthTimeActivity.stopDay.getDay() == dayTimeEntity.getDay() ){
//开始和结束同一天
holder.select_ly_day.setBackgroundResource(R.drawable.bg_time_startstop); }
else if (MonthTimeActivity.startDay.getYear()== dayTimeEntity.getYear() && MonthTimeActivity.startDay.getMonth() == dayTimeEntity.getMonth() && MonthTimeActivity.startDay.getDay() == dayTimeEntity.getDay()){
//该item是 开始日期
holder.select_ly_day.setBackgroundResource(R.drawable.bg_time_start);
}else if(MonthTimeActivity.stopDay.getYear()== dayTimeEntity.getYear() && MonthTimeActivity.stopDay.getMonth() == dayTimeEntity.getMonth() && MonthTimeActivity.stopDay.getDay() == dayTimeEntity.getDay()){
//该item是 结束日期
holder.select_ly_day.setBackgroundResource(R.drawable.bg_time_stop);
}else if(dayTimeEntity.getMonthPosition()>= MonthTimeActivity.startDay.getMonthPosition() && dayTimeEntity.getMonthPosition()<= MonthTimeActivity.stopDay.getMonthPosition()){
//处于开始和结束之间的点
if (dayTimeEntity.getMonthPosition()== MonthTimeActivity.startDay.getMonthPosition()&& dayTimeEntity.getMonthPosition()== MonthTimeActivity.stopDay.getMonthPosition()){
//开始和结束是一个月份
if (dayTimeEntity.getDay()> MonthTimeActivity.startDay.getDay() && dayTimeEntity.getDay() < MonthTimeActivity.stopDay.getDay()) {
holder.select_ly_day.setBackgroundResource(R.color.blue);
}else{
holder.select_ly_day.setBackgroundResource(R.color.white);
}
}else if(MonthTimeActivity.startDay.getMonthPosition() != MonthTimeActivity.stopDay.getMonthPosition()){
// 日期和 开始 不是一个月份
if (dayTimeEntity.getMonthPosition()== MonthTimeActivity.startDay.getMonthPosition() && dayTimeEntity.getDay()> MonthTimeActivity.startDay.getDay()){
//和初始相同月 天数往后
holder.select_ly_day.setBackgroundResource(R.color.blue);
}else if(dayTimeEntity.getMonthPosition()== MonthTimeActivity.stopDay.getMonthPosition() && dayTimeEntity.getDay()< MonthTimeActivity.stopDay.getDay()){
//和结束相同月 天数往前
holder.select_ly_day.setBackgroundResource(R.color.blue);
}else if(dayTimeEntity.getMonthPosition()!= MonthTimeActivity.startDay.getMonthPosition() && dayTimeEntity.getMonthPosition()!= MonthTimeActivity.stopDay.getMonthPosition()){
//和 开始结束都不是同一个月
holder.select_ly_day.setBackgroundResource(R.color.blue);
}else{
holder.select_ly_day.setBackgroundResource(R.color.white);
}
} }else{
holder.select_ly_day.setBackgroundResource(R.color.white);
} } @Override
public int getItemCount() {
int ret = ;
if (days!=null){
ret = days.size();
}
return ret;
}
}

DayTimeAdapter.java

  核心代码:

  1、 不是日期的item不可点击,即 getDay()的到参数 为0的不可点击,详情看(5)

     //显示日期
if (dayTimeEntity.getDay()!=) {
holder.select_txt_day.setText(dayTimeEntity.getDay() + "");
holder.select_ly_day.setEnabled(true);
}else{
holder.select_ly_day.setEnabled(false);
}

  2、 item设置点击监听事件,标记并赋值“开始位置”和“结束位置”

holder.select_ly_day.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (MonthTimeActivity.startDay.getYear() == ){ // 第一次点击开始的位置,因为开始默认参数是 0,0,0,0
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay()); // 该item 天数的 年月日等信息 赋给 开始日期
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
}else if(MonthTimeActivity.startDay.getYear()> && MonthTimeActivity.stopDay.getYear() ==-){ //已经点击了开始 ,点击结束位置,(默认结束位置-1,-1,-1,-1 说明还没有点击结束位置)
if (dayTimeEntity.getYear()> MonthTimeActivity.startDay.getYear()) {
//如果选中的年份大于开始的年份,说明结束日期肯定大于开始日期 ,合法的 ,将该item的天数的 信息 赋给 结束日期
MonthTimeActivity.stopDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.stopDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.stopDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.stopDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.stopDay.setDayPosition(position);
}else if (dayTimeEntity.getYear() == MonthTimeActivity.startDay.getYear()){
//如果选中的年份 等于 选中的年份
if (dayTimeEntity.getMonth()> MonthTimeActivity.startDay.getMonth()){
//如果改item的天数的月份大于开始日期的月份,说明结束日期肯定大于开始日期 ,合法的 ,将该item的天数的 信息 赋给 结束日期
MonthTimeActivity.stopDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.stopDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.stopDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.stopDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.stopDay.setDayPosition(position);
}else if(dayTimeEntity.getMonth() == MonthTimeActivity.startDay.getMonth()){
//年份月份 都相等
if (dayTimeEntity.getDay() >= MonthTimeActivity.startDay.getDay()){
//判断天数 ,如果 该item的天数的 日子大于等于 开始日期的 日子 ,说明结束日期合法的 ,将该item的天数的 信息 赋给 结束日期
MonthTimeActivity.stopDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.stopDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.stopDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.stopDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.stopDay.setDayPosition(position);
}else{
//天数小与初始 从新选择开始 ,结束日期重置,开始日期为当前的位置的天数的信息
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
MonthTimeActivity.stopDay.setDay(-);
MonthTimeActivity.stopDay.setMonth(-);
MonthTimeActivity.stopDay.setYear(-);
MonthTimeActivity.stopDay.setMonthPosition(-);
MonthTimeActivity.stopDay.setDayPosition(-);
}
}else {
//选中的月份 比开始日期的月份还小,说明 结束位置不合法,结束日期重置,开始日期为当前的位置的天数的信息
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
MonthTimeActivity.stopDay.setDay(-);
MonthTimeActivity.stopDay.setMonth(-);
MonthTimeActivity.stopDay.setYear(-);
MonthTimeActivity.stopDay.setMonthPosition(-);
MonthTimeActivity.stopDay.setDayPosition(-);
} }else{
//选中的年份 比开始日期的年份还小,说明 结束位置不合法,结束日期重置,开始日期为当前的位置的天数的信息
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
MonthTimeActivity.stopDay.setDay(-);
MonthTimeActivity.stopDay.setMonth(-);
MonthTimeActivity.stopDay.setYear(-);
MonthTimeActivity.stopDay.setMonthPosition(-);
MonthTimeActivity.stopDay.setDayPosition(-);
}
}else if(MonthTimeActivity.startDay.getYear()> && MonthTimeActivity.startDay.getYear()>){ //已经点击开始和结束 第三次点击 ,重新点击开始
MonthTimeActivity.startDay.setDay(dayTimeEntity.getDay());
MonthTimeActivity.startDay.setMonth(dayTimeEntity.getMonth());
MonthTimeActivity.startDay.setYear(dayTimeEntity.getYear());
MonthTimeActivity.startDay.setMonthPosition(dayTimeEntity.getMonthPosition());
MonthTimeActivity.startDay.setDayPosition(position);
MonthTimeActivity.stopDay.setDay(-);
MonthTimeActivity.stopDay.setMonth(-);
MonthTimeActivity.stopDay.setYear(-);
MonthTimeActivity.stopDay.setMonthPosition(-);
MonthTimeActivity.stopDay.setDayPosition(-);
}
EventBus.getDefault().post(new UpdataCalendar()); // 发消息刷新适配器,目的为了显示日历上各个日期的背景颜色
}
});

  3、根据每个item的年月日,在外部列表中的位置,在内部列表中的位置 信息 和“开始日期”、“结束日期”的信息对比,设置相应的背景色

if (MonthTimeActivity.startDay.getYear()== dayTimeEntity.getYear() && MonthTimeActivity.startDay.getMonth() == dayTimeEntity.getMonth() && MonthTimeActivity.startDay.getDay() == dayTimeEntity.getDay()
&& MonthTimeActivity.stopDay.getYear()== dayTimeEntity.getYear() && MonthTimeActivity.stopDay.getMonth() == dayTimeEntity.getMonth() && MonthTimeActivity.stopDay.getDay() == dayTimeEntity.getDay() ){
//开始和结束同一天
holder.select_ly_day.setBackgroundResource(R.drawable.bg_time_startstop);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.white));
}
else if (MonthTimeActivity.startDay.getYear()== dayTimeEntity.getYear() && MonthTimeActivity.startDay.getMonth() == dayTimeEntity.getMonth() && MonthTimeActivity.startDay.getDay() == dayTimeEntity.getDay()){
//该item是 开始日期
holder.select_ly_day.setBackgroundResource(R.drawable.bg_time_start);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.white));
}else if(MonthTimeActivity.stopDay.getYear()== dayTimeEntity.getYear() && MonthTimeActivity.stopDay.getMonth() == dayTimeEntity.getMonth() && MonthTimeActivity.stopDay.getDay() == dayTimeEntity.getDay()){
//该item是 结束日期
holder.select_ly_day.setBackgroundResource(R.drawable.bg_time_stop);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.white));
}else if(dayTimeEntity.getMonthPosition()>= MonthTimeActivity.startDay.getMonthPosition() && dayTimeEntity.getMonthPosition()<= MonthTimeActivity.stopDay.getMonthPosition()){
//处于开始和结束之间的点
if (dayTimeEntity.getMonthPosition()== MonthTimeActivity.startDay.getMonthPosition()&& dayTimeEntity.getMonthPosition()== MonthTimeActivity.stopDay.getMonthPosition()){
//开始和结束是一个月份
if (dayTimeEntity.getDay()> MonthTimeActivity.startDay.getDay() && dayTimeEntity.getDay() < MonthTimeActivity.stopDay.getDay()) {
holder.select_ly_day.setBackgroundResource(R.color.blue);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.white));
}else{
holder.select_ly_day.setBackgroundResource(R.color.white);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.txtColor));
}
}else if(MonthTimeActivity.startDay.getMonthPosition() != MonthTimeActivity.stopDay.getMonthPosition()){
// 日期和 开始 不是一个月份
if (dayTimeEntity.getMonthPosition()== MonthTimeActivity.startDay.getMonthPosition() && dayTimeEntity.getDay()> MonthTimeActivity.startDay.getDay()){
//和初始相同月 天数往后
holder.select_ly_day.setBackgroundResource(R.color.blue);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.white));
}else if(dayTimeEntity.getMonthPosition()== MonthTimeActivity.stopDay.getMonthPosition() && dayTimeEntity.getDay()< MonthTimeActivity.stopDay.getDay()){
//和结束相同月 天数往前
if (dayTimeEntity.getDay()<=0){
holder.select_ly_day.setBackgroundResource(R.color.white);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.txtColor));
}else {
holder.select_ly_day.setBackgroundResource(R.color.blue);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.white));
}
}else if(dayTimeEntity.getMonthPosition()!= MonthTimeActivity.startDay.getMonthPosition() && dayTimeEntity.getMonthPosition()!= MonthTimeActivity.stopDay.getMonthPosition()){
//和 开始结束都不是同一个月
holder.select_ly_day.setBackgroundResource(R.color.blue);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.white));
}else{
holder.select_ly_day.setBackgroundResource(R.color.white);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.txtColor));
}
} }else{
holder.select_ly_day.setBackgroundResource(R.color.white);
holder.select_txt_day.setTextColor(context.getResources().getColor(R.color.txtColor));
}

  判断逻辑都在代码中有注释

(9) 资源文件的代码

  1、drawable文件

  bg_time_start.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--开始日期的背景-->
<corners android:bottomLeftRadius="20dp"
android:topLeftRadius="20dp"
></corners>
<solid android:color="#4ab7e8"></solid>
</shape>

  bg_time_stop.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--结束日期的背景-->
<corners android:bottomRightRadius="20dp"
android:topRightRadius="20dp"
></corners>
<solid android:color="#4ab7e8"></solid>
</shape>

  bg_time_startstop.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<!--开始日期和结束日期同一天的背景-->
<corners android:radius="20dp"
></corners>
<solid android:color="#4ab7e8"></solid>
</shape>

  (2)、colors.xml

<color name="white">#fff</color>

<color name="blue">#4ab7e8</color>

--------------------------------------------------------------------------------------------------------------------------

GitHub:仿美团酒店预订日期选择

另:强制当天作为开始日期,只选择结束日期,可以调整结束日期和开始日期的间隔时间限制

GitHub:仿美团酒店预订日期选择(强制当天作为开始日期)