Android 自定义日期段选择控件功能(开始时间-结束时间)

开发中碰到个需求,需要在一个空间中选择完成开始和结束时间。实现的过程走的是程序员开发的老路子,找到轮子后自己改吧改吧就成了。

当时做的时候有几个需求:1.当天为最大的结束日期,2.最大选择范围1年,3.开始时间和结束时间可以为同一天。如有其他需求实现,可以参考代码改进一下。先上效果图:

视频点击后的虚影是屏幕录制的原因。实现步骤:(如有缺失什么资源,请告知。开始时间和结束时间显示自己布局内添加就可以)

1.自定义控件属性

<declare-styleable name="MyCalendar">
 <attr name="dateformat" format="string"></attr>
 <attr name="titleSize" format="dimension"></attr>
 <attr name="titleColor" format="color"></attr>
 <attr name="goIcon" format="reference"></attr>
 <attr name="preIcon" format="reference"></attr>
 <attr name="dayInMonthColor" format="color"></attr>
 <attr name="dayOutMonthcolor" format="color"></attr>
 <attr name="todayColor" format="color"></attr>
 <attr name="todayEmptycircleColor" format="color"></attr>
 <attr name="todayFillcircleColor" format="color"></attr>
 <attr name="calendarbackground" format="color|reference"></attr>
</declare-styleable>

2.自定义控件代码

/**
 * @Description: 可以选择时间范围的日历控件
 * @Author MengXY
 * @Emil mxy_2012_1@163.com
 * @Date 2019/1/8
*/
public class CalendarView extends LinearLayout implements View.OnClickListener{
 private TextView title;
 private RecyclerView recyclerView;
 private RelativeLayout layout_calendar_gonext;
 private RelativeLayout layout_calendar_goup;
 private LinearLayoutManager linearLayoutManager;
 private Calendar curDate = Calendar.getInstance();
 //从服务器获取的日期
 private Date dateFromServer;
 //外层主recyclerview的adapter
 private MainRvAdapter mainAdapter;
 private List<CalendarCell> months = new ArrayList<>();
 private Context context;
 //相关属性
 private int titleColor;
 private int titleSize;
 private int enableSelectColor;
 private int disableSeletColor;
 private int todayColor;
 private int todayEmptyColor;
 private int todayFillColor;
 /** 初始日期为当前日期前一年*/
 private String time;
 private long timeBefor;
 private long timeNow;
 private List<String> titles = new ArrayList<>();
 //点击的开始时间与结束时间
 private Date sDateTime;
 private Date eDateTime;
 private boolean isSelectingSTime = true;
 private HashMap<Integer, SubRvAdapter> allAdapters = new HashMap<>();
 public CalendarView(Context context) {
 this(context, null);
 }
 public CalendarView(Context context, AttributeSet attrs) {
 this(context, attrs, 0);
 }
 private int maxSelect = 13;
 public CalendarView(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyCalendar);
 titleColor = ta.getColor(R.styleable.MyCalendar_titleColor, Color.WHITE);
 titleSize = (int) ta.getDimension(R.styleable.MyCalendar_titleSize, 15);
 enableSelectColor = ta.getColor(R.styleable.MyCalendar_dayInMonthColor, context.getResources().getColor(R.color.text_lable));
 disableSeletColor = ta.getColor(R.styleable.MyCalendar_dayOutMonthcolor, context.getResources().getColor(R.color.text_unenable));
 todayColor = ta.getColor(R.styleable.MyCalendar_todayColor, Color.BLUE);
 todayEmptyColor = ta.getColor(R.styleable.MyCalendar_todayEmptycircleColor, Color.CYAN);
 todayFillColor = ta.getColor(R.styleable.MyCalendar_todayFillcircleColor, Color.CYAN);
 ta.recycle();
 this.context = context;
 init(context);
 }
 //该方法用于设置从服务器获取的时间,如果没有从服务器获取的时间将使用手机本地时间
 private void initTime() {
 Calendar calendar = Calendar.getInstance(); //得到日历
 calendar.setTime(new Date());
 calendar.add(Calendar.MONTH,-(maxSelect-1));
 time = DateUtils.formatData(calendar.getTime(),Constant.TFORMATE_YMD);
 timeBefor = DateUtils.getDataTime(time);
 String now = DateUtils.formatData(new Date(),Constant.TFORMATE_YMD);
 timeNow = DateUtils.getDataTime(now);
// LogUtils.e("之前日期:"+time+"=="+timeBefor);
// LogUtils.e("当前日期:"+now+"=="+timeNow);
 curDate = DateUtil.strToCalendar(time, Constant.TFORMATE_YMD);
 dateFromServer = DateUtil.strToDate(time, Constant.TFORMATE_YMD);
 }
 private void init(Context context) {
 bindView(context);
 renderCalendar();
 }
 private void bindView(Context context) {
 View view = LayoutInflater.from(context).inflate(R.layout.appoint_calendarview, this, false);
 title = (TextView) view.findViewById(R.id.calendar_title);
 title.setTextColor(titleColor);
 title.setTextSize(titleSize);
 layout_calendar_gonext = view.findViewById(R.id.layout_calendar_gonext);
 layout_calendar_goup = view.findViewById(R.id.layout_calendar_goup);
 layout_calendar_gonext.setOnClickListener(this);
 layout_calendar_goup.setOnClickListener(this);
 recyclerView = (RecyclerView) view.findViewById(R.id.calendar_rv);
 linearLayoutManager = new LinearLayoutManager(this.context, LinearLayoutManager.HORIZONTAL, false);
 recyclerView.setLayoutManager(linearLayoutManager);
 PagerSnapHelper snapHelper = new PagerSnapHelper();
 snapHelper.attachToRecyclerView(recyclerView);
 addView(view);
 }
 public void renderCalendar() {
 months.clear();
 initTime();
 for (int i = 0; i < maxSelect; i++) {
 ArrayList<Date> cells = new ArrayList<>();
 if (i != 0) {
 curDate.add(Calendar.MONTH, 1);//后推一个月
 } else {
 curDate.add(Calendar.MONTH, 0);//当前月
 }
 Calendar calendar = (Calendar) curDate.clone();
 //将日历设置到当月第一天
 calendar.set(Calendar.DAY_OF_MONTH, 1);
 //获得当月第一天是星期几,如果是星期一则返回1此时1-1=0证明上个月没有多余天数
 int prevDays = calendar.get(Calendar.DAY_OF_WEEK) - 1;
 //将calendar在1号的基础上向前推prevdays天。
 calendar.add(Calendar.DAY_OF_MONTH, -prevDays);
 //最大行数是6*7也就是,1号正好是星期六时的情况
 int maxCellcount = 6 * 7;
 while (cells.size() < maxCellcount) {
 cells.add(calendar.getTime());
 //日期后移一天
 calendar.add(calendar.DAY_OF_MONTH, 1);
 }
 months.add(new CalendarCell(i, cells));
 }
 for (int i = 0; i < months.size(); i++) {
 //title格式 2018年6月3日
 String title = (months.get(i).getCells().get(20).getYear() + 1900) +
 "\t-\t" +
 (months.get(i).getCells().get(20).getMonth() + 1);
 titles.add(title);
 }
 title.setText(titles.get(maxSelect-1));
 //只限定3个月,因此模拟给3个数值即可
 mainAdapter = new MainRvAdapter(R.layout.appoint_calendarview_item, months);
 recyclerView.setAdapter(mainAdapter);
 //recyclerview 的滚动监听
 recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
 @Override
 public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
 title.setText(titles.get(linearLayoutManager.findLastVisibleItemPosition()));
 super.onScrollStateChanged(recyclerView, newState);
 }
 });
 recyclerView.scrollToPosition(maxSelect-1);
 }
 @Override
 public void onClick(View v) {
 int index = linearLayoutManager.findLastVisibleItemPosition();
 LogUtils.e("当前项"+index);
 switch (v.getId()){
 case R.id.layout_calendar_gonext:
 if(index < maxSelect-1){
 recyclerView.scrollToPosition(index+1);
 title.setText(titles.get(index+1));
 }
 break;
 case R.id.layout_calendar_goup:
 if(index > 0){
 recyclerView.scrollToPosition(index-1);
 title.setText(titles.get(index-1));
 }
 break;
 }
 }
 /**
 * 最外层水平recyclerview的adapter
 */
 private class MainRvAdapter extends BaseQuickAdapter<CalendarCell, BaseViewHolder> {
 public MainRvAdapter(int layoutResId, @Nullable List<CalendarCell> data) {
 super(layoutResId, data);
 }
 @Override
 protected void convert(BaseViewHolder helper, final CalendarCell item) {
 if (((RecyclerView) helper.getView(R.id.appoint_calendarview_item_rv)).getLayoutManager() == null) {
 //RecyclerView不能都使用同一个LayoutManager
 GridLayoutManager manager = new GridLayoutManager(mContext, 7);
 //recyclerview嵌套高度不固定(wrap_content)时必须setAutoMeasureEnabled(true),否则测量时控件高度为0
 manager.setAutoMeasureEnabled(true);
 ((RecyclerView) helper.getView(R.id.appoint_calendarview_item_rv)).setLayoutManager(manager);
 }
 SubRvAdapter subRvAdapter = null;
 if (allAdapters.get(helper.getPosition()) == null) {
 subRvAdapter = new SubRvAdapter(R.layout.calendar_text_day, item.getCells());
 allAdapters.put(helper.getPosition(), subRvAdapter);
 ((RecyclerView) helper.getView(R.id.appoint_calendarview_item_rv)).setAdapter(subRvAdapter);
 } else {
 subRvAdapter = allAdapters.get(helper.getPosition());
 ((RecyclerView) helper.getView(R.id.appoint_calendarview_item_rv)).setAdapter(subRvAdapter);
 }
 //item 点击事件响应
 subRvAdapter.setOnItemClickListener(new OnItemClickListener() {
 @Override
 public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
 Date date = item.getCells().get(position);
 if(date.getTime() >= timeBefor && date.getTime()<= timeNow ){
 if (isSelectingSTime) {
 //正在选择开始时间
 selectSDate(item.getCells().get(position));
 } else {
 //正在选择结束时间
 selectEDate(item.getCells().get(position));
 }
 }
 //更新所有的adapter,比如今天6月,需要更新6、7、8三个月份不同adapter
 Iterator iterator = allAdapters.entrySet().iterator();
 while (iterator.hasNext()) {
 Map.Entry entry = (Map.Entry) iterator.next();
 ((SubRvAdapter) entry.getValue()).notifyDataSetChanged();
 }
 }
 });
 }
 }
 public void selectSDate(Date date) {
 if (sDateTime != null && eDateTime != null) {
 sDateTime = date;
 notifyDateSelectChanged();
 } else {
 sDateTime = date;
 notifyDateSelectChanged();
 }
 eDateTime = null;
 isSelectingSTime = false;
 /** 当前没有选择结束时间*/
 if(this.calendaSelListener != null){
 calendaSelListener.selectStatus(false);
 }
 }
 public void selectEDate(Date date) {
 if (sDateTime != null) {
 if (date.getTime() >= sDateTime.getTime()) {
 eDateTime = date;
 isSelectingSTime = true;
 notifyDateSelectChanged();
 }else {
 eDateTime = sDateTime;
 sDateTime = date;
 isSelectingSTime = true;
 notifyDateSelectChanged();
 }
 /** 选择完成*/
 if(this.calendaSelListener != null){
 calendaSelListener.selectStatus(true);
 }
 }
 }
 /**
 * 通知开始时间跟结束时间均改变
 */
 public void notifyDateSelectChanged() {
 if (mETimeSelectListener != null && eDateTime != null) {
 mETimeSelectListener.onETimeSelect(eDateTime);
 }
 if (mSTimeSelectListener != null && sDateTime != null) {
 mSTimeSelectListener.onSTimeSelect(sDateTime);
 }
 }
 private class SubRvAdapter extends BaseQuickAdapter<Date, BaseViewHolder> {
 public SubRvAdapter(int layoutResId, @Nullable List<Date> data) {
 super(layoutResId, data);
 }
 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
 @Override
 protected void convert(BaseViewHolder helper, Date date) {
 helper.setIsRecyclable(false);//不让recyclerview进行复用,复用会出问题
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).setEmptyColor(todayEmptyColor);
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).setFillColor(todayFillColor);
 int day = date.getDate();
 //设置文本
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).setText(String.valueOf(day));
 //设置颜色
 if(date.getTime() >= timeBefor && date.getTime()<= timeNow ){
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).setTextColor(enableSelectColor);
 }else {
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).setTextColor(disableSeletColor);
 }
 //更改选中文字颜色
 if(sDateTime != null && eDateTime != null){
 if(date.getTime()>sDateTime.getTime() && date.getTime()<eDateTime.getTime()){
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).isSelected(true);
 helper.getView(R.id.calendar_day_rl).setBackgroundColor(getResources().getColor(R.color.date_duration_bg));
 }
 }
 /****************************/
 if (eDateTime != null && date.getTime() == eDateTime.getTime()) {
 //结束时间
 if(eDateTime.equals(sDateTime)){
 ((CalendarDayRelativeLayout) helper.getView(R.id.calendar_day_rl)).isSameDay();
 }else {
 ((CalendarDayRelativeLayout) helper.getView(R.id.calendar_day_rl)).isETime(true);
 }
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).isETime(true);
 }
 if (sDateTime != null && date.getTime() == sDateTime.getTime()) {
 //开始时间
 if (eDateTime != null) {
 if(eDateTime.equals(sDateTime)) {
 ((CalendarDayRelativeLayout) helper.getView(R.id.calendar_day_rl)).isSameDay();
 }else {
 ((CalendarDayRelativeLayout) helper.getView(R.id.calendar_day_rl)).isSTime(true);
 }
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).isSTime(true);
 } else {
 ((CalendarDayRelativeLayout) helper.getView(R.id.calendar_day_rl)).isDurationSun(true);
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).isSTime(true);
 }
 }
 /*****************************************/
 if(date.getTime() == timeNow){
 ((CalendarDayTextView) helper.getView(R.id.calendar_day_tv)).setToday(true);
 }
 }
 }
 private class CalendarCell {
 private int position;
 ArrayList<Date> cells;
 public CalendarCell(int position, ArrayList<Date> cells) {
 this.position = position;
 this.cells = cells;
 }
 public int getPosition() {
 return position;
 }
 public void setPosition(int position) {
 this.position = position;
 }
 public ArrayList<Date> getCells() {
 return cells;
 }
 public void setCells(ArrayList<Date> cells) {
 this.cells = cells;
 }
 }
 //开始时间的选择监听
 public interface CalendarSTimeSelListener {
 void onSTimeSelect(Date date);
 }
 private CalendarSTimeSelListener mSTimeSelectListener;
 public void setSTimeSelListener(CalendarSTimeSelListener li) {
 mSTimeSelectListener = li;
 }
 //结束时间的监听事件
 public interface CalendatEtimSelListener {
 void onETimeSelect(Date date);
 }
 private CalendaSelListener calendaSelListener;
 /**选择日期完整性*/
 public interface CalendaSelListener{
 void selectStatus(boolean isOk);
 }
 public void setCalendaSelListener(CalendaSelListener calendaSelListener) {
 this.calendaSelListener = calendaSelListener;
 }
 private CalendatEtimSelListener mETimeSelectListener;
 public void setETimeSelListener(CalendatEtimSelListener li) {
 mETimeSelectListener = li;
 }
}

3.自定义view用到的布局 appoint_calendarview.xml,对应日历控件如下面图片的部分。

<?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:layout_marginTop="15dp"
 android:orientation="vertical">

 <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="20dp"
 android:gravity="center_vertical"
 android:orientation="horizontal">
 <TextView
 android:id="@+id/calendar_title"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_centerInParent="true"
 android:text="2018年"
 android:textColor="@color/text_lable"
 android:textSize="15dp"/>
 <RelativeLayout
 android:id="@+id/layout_calendar_gonext"
 android:layout_width="wrap_content"
 android:layout_height="match_parent"
 android:layout_alignParentRight="true"
 android:paddingLeft="15dp"
 android:paddingRight="15dp"
 >
 <ImageView
 android:layout_width="10dp"
 android:layout_height="10dp"
 android:layout_centerVertical="true"
 android:src="@mipmap/icon_arrow_right" />
 </RelativeLayout>
 <RelativeLayout
 android:id="@+id/layout_calendar_goup"
 android:layout_width="wrap_content"
 android:layout_height="match_parent"
 android:paddingLeft="15dp"
 android:paddingRight="15dp"
 >
 <ImageView
 android:layout_width="10dp"
 android:layout_height="10dp"
 android:layout_centerVertical="true"
 android:src="@mipmap/icon_back_black" />
 </RelativeLayout>

 </RelativeLayout>

 <LinearLayout
 android:id="@+id/calendar_week_header"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginTop="15dp"
 android:gravity="center_vertical"
 android:orientation="horizontal"
 >
 <TextView
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical"
 android:layout_weight="1"
 android:text="@string/sun"
 android:textAlignment="center"
 android:textColor="#555"
 android:textSize="13dp" />

 <TextView
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical"
 android:layout_weight="1"
 android:text="@string/mon"
 android:textAlignment="center"
 android:textColor="#555"
 android:textSize="13dp" />

 <TextView
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical"
 android:layout_weight="1"
 android:text="@string/tue"
 android:textAlignment="center"
 android:textColor="#555"
 android:textSize="13dp" />

 <TextView
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical"
 android:layout_weight="1"
 android:text="@string/wed"
 android:textAlignment="center"
 android:textColor="#555"
 android:textSize="13dp" />

 <TextView
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical"
 android:layout_weight="1"
 android:text="@string/thu"
 android:textAlignment="center"
 android:textColor="#555"
 android:textSize="13dp" />

 <TextView
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical"
 android:layout_weight="1"
 android:text="@string/fri"
 android:textAlignment="center"
 android:textColor="#555"
 android:textSize="13dp" />

 <TextView
 android:layout_width="0dp"
 android:layout_height="wrap_content"
 android:layout_gravity="center_vertical"
 android:layout_weight="1"
 android:text="@string/sat"
 android:textAlignment="center"
 android:textColor="#555"
 android:textSize="13dp" />
 </LinearLayout>

 <android.support.v7.widget.RecyclerView
 android:id="@+id/calendar_rv"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginTop="10dp"
 android:overScrollMode="never"
 />
</LinearLayout>

定义控件选择后的背景部分:CalendarDayRelativeLayout.java

import android.content.Context;
import android.graphics.Color;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.widget.RelativeLayout;

public class CalendarDayRelativeLayout extends RelativeLayout {
 public CalendarDayRelativeLayout(Context context) {
 this(context, null);
 }

 public CalendarDayRelativeLayout(Context context, AttributeSet attrs) {
 super(context, attrs);
 }

 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
 public void isDurationSat(boolean isSaturday) {
 this.setBackground(getResources().getDrawable(R.drawable.appoint_calendar_sat_bg));
 }

 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
 public void isDurationSun(boolean isSunday) {
 this.setBackground(getResources().getDrawable(R.drawable.appoint_calendar_sun_bg));
 }
 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
 public void isETime(boolean etime) {
// this.setBackgroundResource(getResources().getDrawable(R.drawable.));

 this.setBackground(getResources().getDrawable(R.drawable.appoint_calendar_sat_bg));
 }
 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
 public void isSTime(boolean stime) {
// this.setBackground(getResources().getDrawable(R.mipmap.appoint_calendar_start_bg));
 this.setBackground(getResources().getDrawable(R.drawable.appoint_calendar_sun_bg));
 }

 /**
 * 同一天
 * */
 @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
 public void isSameDay(){
 this.setBackground(getResources().getDrawable(R.drawable.appoint_calendar_same_bg));
 }
}

自定义控件内日期的CalendarDayTextView.java

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.util.AttributeSet;

/**
 * @Description: 日历内日期
 * @Author MengXY
 * @Date 2019/1/8
*/
public class CalendarDayTextView extends android.support.v7.widget.AppCompatTextView {
 public boolean isToday;
 private boolean isSTime;
 private boolean isETime;
 private Context context;
 public void setEmptyColor(int emptyColor) {
 this.emptyColor = emptyColor;
 }
 public void setFillColor(int fillColor) {
 this.fillColor = fillColor;
 }
 private int emptyColor = Color.parseColor("#00ff00");
 private int fillColor = Color.parseColor("#00ff00");
 private Paint mPaintSTime;
 private Paint mPaintETime;

 public CalendarDayTextView(Context context) {
 super(context);
 initview(context);
 }
 public CalendarDayTextView(Context context, AttributeSet attrs) {
 super(context, attrs);
 initview(context);
 }
 private void initview(Context context) {
 this.context=context;
// mPaintSTime = new Paint(Paint.ANTI_ALIAS_FLAG);
// mPaintSTime.setStyle(Paint.Style.FILL);
// mPaintSTime.setColor(context.getResources().getColor(R.color.date_time_bg));
// mPaintSTime.setStrokeWidth(2);
//
// mPaintETime = new Paint(Paint.ANTI_ALIAS_FLAG);
// mPaintETime.setStyle(Paint.Style.FILL);
// mPaintETime.setColor(context.getResources().getColor(R.color.date_time_bg));
// mPaintETime.setStrokeWidth(2);
 }
 @Override
 protected void onDraw(Canvas canvas) {
 //根据当前逻辑开始时间必须先绘制结束时间
// if (isETime) {
// canvas.save();
// //移动到当前控件的中心,以中心为圆点绘制实心圆
// canvas.translate(getWidth() / 2, getHeight() / 2);
// canvas.drawCircle(0, 0, getWidth() / 2 , mPaintETime);
// canvas.restore();
// //此处必须将圆移动回开始位置,否则文本显示会受到影响
// canvas.translate(0, 0);
// }
//
// if (isSTime) {
// canvas.save();
// //移动到当前控件的中心,以中心为圆点绘制实心圆
// canvas.translate(getWidth() / 2, getHeight() / 2);
// canvas.drawCircle(0, 0, getWidth() / 2 , mPaintSTime);
// canvas.restore();
// //此处必须将圆移动回开始位置,否则文本显示会受到影响
// canvas.translate(0, 0);
// }
 super.onDraw(canvas);
 }
 public void setToday(boolean today) {
 isToday = today;
 this.setTextColor(context.getResources().getColor(R.color.text_main_tab_select));
 }
 public void isETime(boolean etime) {
 isETime = etime;
// this.setTextColor(context.getResources().getColor(R.color.date_time_tv));
// this.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
 isSelected(true);
 }
 public void isSTime(boolean stime) {
 isSTime = stime;
 isSelected(true);
// this.setTextColor(context.getResources().getColor(R.color.date_time_tv));
// this.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
 }

 public void isSelected(boolean isSelcted){
 if(isSelcted){
 this.setTextColor(context.getResources().getColor(R.color.date_time_tv));
 this.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
 }else {
 this.setTextColor(context.getResources().getColor(R.color.text_lable));
 }
 }
}

appoint_calendarview.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/appoint_calendarview_item_rv"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">

</android.support.v7.widget.RecyclerView>

calendar_text_day.xml

<?xml version="1.0" encoding="utf-8"?>
<com.包名.CalendarDayRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="44dp"
 android:gravity="center"
 android:id="@+id/calendar_day_rl"
 android:layout_marginTop="5dp"
 android:layout_marginBottom="5dp"
 >
 <com..包名.CalendarDayTextView
 android:id="@+id/calendar_day_tv"
 android:layout_width="44dp"
 android:layout_height="44dp"
 android:layout_centerInParent="true"
 android:gravity="center"
 android:textColor="@color/white"
 android:text="31"
 android:includeFontPadding="false"
 android:textSize="13dp"/>
</com..包名.CalendarDayRelativeLayout>

DateUtil.java

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtil {
 //Calendar 转化 String
 public static String calendarToStr(Calendar calendar,String format) {
// Calendar calendat = Calendar.getInstance();
 SimpleDateFormat sdf = new SimpleDateFormat(format);
 return sdf.format(calendar.getTime());
 }

 //String 转化Calendar
 public static Calendar strToCalendar(String str,String format) {
// String str = "2012-5-27";
 SimpleDateFormat sdf = new SimpleDateFormat(format);
 Date date = null;
 Calendar calendar = null;
 try {
 date = sdf.parse(str);
 calendar = Calendar.getInstance();
 calendar.setTime(date);
 } catch (ParseException e) {
 e.printStackTrace();
 }
 return calendar;
 }

 // Date 转化String
 public static String dateTostr(Date date,String format) {
 SimpleDateFormat sdf = new SimpleDateFormat(format);
// String dateStr = sdf.format(new Date());
 String dateStr = sdf.format(date);
 return dateStr;
 }

 // String 转化Date
 public static Date strToDate(String str,String format) {
 SimpleDateFormat sdf = new SimpleDateFormat(format);
 Date date = null;
 try {
 date = sdf.parse(str);
 } catch (ParseException e) {
 e.printStackTrace();
 }
 return date;
 }

 //Date 转化Calendar
 public static Calendar dateToCalendar(Date date) {
 Calendar calendar = Calendar.getInstance();
 calendar.setTime(date);
 return calendar;
 }

 //Calendar转化Date
 public static Date calendarToDate(Calendar calendar) {
 return calendar.getTime();
 }

 // String 转成 Timestamp
 public static Timestamp strToTimeStamp(String str) {
// Timestamp ts = Timestamp.valueOf("2012-1-14 08:11:00");
 return Timestamp.valueOf(str);
 }

 //Date 转 TimeStamp
 public static Timestamp dateToTimeStamp(Date date,String format) {
 SimpleDateFormat df = new SimpleDateFormat(format);
 String time = df.format(new Date());
 Timestamp ts = Timestamp.valueOf(time);
 return ts;
 }
}

4.资源文件 /drawableappoint_calendar_sat_bg.xml //开始时间

<shape xmlns:android="http://schemas.android.com/apk/res/android">
 <corners android:topRightRadius="44dp" android:bottomRightRadius="44dp"/>
 <size android:height="44dp"/>
 <solid android:color="#41D2C4"/>
</shape>

appoint_calendar_sun_bg.xml //结束时间

<shape xmlns:android="http://schemas.android.com/apk/res/android">
 <corners
 android:bottomLeftRadius="44dp"
 android:topLeftRadius="44dp" />
 <size android:height="44dp" />
 <solid android:color="#41D2C4" />
</shape>

appoint_calendar_same_bg.xml //开始时间和结束时间是同一天

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
 <solid android:color="@color/date_duration_bg" />
 <corners android:radius="60dp" />
</shape>

/value

<string name="sun">日</string>
<string name="mon">一</string>
<string name="tue">二</string>
<string name="wed">三</string>
<string name="thu">四</string>
<string name="fri">五</string>
<string name="sat">六</string>

<color name="date_duration_bg">#41D2C4</color>

5.在activity中使用 activity_selectdate.xml

<?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"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:background="@color/white"
 android:orientation="vertical">

 <RelativeLayout
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_marginTop="40dp">

 <FrameLayout
 android:id="@+id/layout_line"
 android:layout_width="10dp"
 android:layout_height="1dp"
 android:layout_centerInParent="true"
 android:background="#35C1B5" />
 <TextView
 android:id="@+id/tv_startime"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_toLeftOf="@+id/layout_line"
 android:layout_marginRight="22.5dp"
 android:textColor="#35C1B5"
 android:textSize="14dp"
 android:text="@string/starTime"
 />
 <TextView
 android:id="@+id/tv_endtime"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_toRightOf="@+id/layout_line"
 android:layout_marginLeft="22.5dp"
 android:textColor="#35C1B5"
 android:textSize="14dp"
 android:text="@string/endTime"
 />
 </RelativeLayout>
 <FrameLayout
 android:layout_width="match_parent"
 android:layout_height="0.5dp"
 android:layout_marginTop="10dp"
 android:background="@color/bg_line"
 />
 <com.包名.CalendarView
 android:id="@+id/calendarview"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 app:titleColor = "@color/text_lable"
 />
</LinearLayout>

SelectTimeActivity.java

public class SelectTimeActivity extends BaseActivity {

 @BindView(R.id.tv_title)
 TextView tvTitle;
 @BindView(R.id.iv_title_back)
 ImageView ivTitleBack;
 @BindView(R.id.tv_title_left)
 TextView tvTitleLeft;
 @BindView(R.id.layout_title_left)
 RelativeLayout layoutTitleLeft;
 @BindView(R.id.tv_title_right)
 TextView tvTitleRight;
 @BindView(R.id.layout_title_right)
 RelativeLayout layoutTitleRight;
 @BindView(R.id.layout_line)
 FrameLayout layoutLine;
 @BindView(R.id.tv_startime)
 TextView tvStartime;
 @BindView(R.id.tv_endtime)
 TextView tvEndtime;
 @BindView(R.id.calendarview)
 CalendarView calendarview;
 private String starTime;
 private String endTime;
 private boolean isSelecgOk = false;
 @Override
 protected void onCreate(@Nullable Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_selectdate);
 ButterKnife.bind(this);
 setStatusBar(true);
 initView();
 }

 private void initView() {
 tvTitle.setText(getString(R.string.selectTime));
 ivTitleBack.setVisibility(View.GONE);
 tvTitleLeft.setText(getString(R.string.cancel));
 tvTitleRight.setText(getString(R.string.confirm));
 calendarview.setETimeSelListener(new CalendarView.CalendatEtimSelListener() {
 @Override
 public void onETimeSelect(Date date) {
 if (date != null) {
 endTime = DateUtils.formatData(date, Constant.TFORMATE_YMD);
 tvEndtime.setText(endTime);
 }else {
 endTime = null;
 }
 }
 });
 calendarview.setSTimeSelListener(new CalendarView.CalendarSTimeSelListener() {
 @Override
 public void onSTimeSelect(Date date) {
 if (date != null) {
 starTime = DateUtils.formatData(date, Constant.TFORMATE_YMD);
 tvStartime.setText(starTime);
 }else {
 starTime = null;
 }
 }
 });
 calendarview.setCalendaSelListener(new CalendarView.CalendaSelListener() {
 @Override
 public void selectStatus(boolean isOk) {
 isSelecgOk = isOk;
 }
 });
 }

 @OnClick({R.id.tv_title_left, R.id.tv_title_right})
 public void onClick(View view) {
 switch (view.getId()) {
 case R.id.tv_title_left:
 finish();
 break;
 case R.id.tv_title_right:
 if(TextUtils.isEmpty(starTime)){
 ToastUtils.showToast(getString(R.string.history_alert1));
 return;
 }
 if(TextUtils.isEmpty(endTime) || !isSelecgOk){
 ToastUtils.showToast(getResources().getString(R.string.history_alert));
 return;
 }
 Intent intent = new Intent();
 intent.putExtra("starTime",starTime);
 intent.putExtra("endTime",endTime);
 setResult(RESULT_OK,intent);
 finish();
 break;
 }
 }
}

RecyclerAdapter引用

implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'

到此这篇关于Android 自定义日期段选择控件,开始时间-结束时间。的文章就介绍到这了,更多相关Android 自定义日期段选择控件,开始时间-结束时间。内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Android中日期与时间设置控件用法实例

    本文实例讲述了Android中日期与时间设置控件用法.分享给大家供大家参考.具体如下: 1.日期设置控件:DatePickerDialog 2.时间设置控件:TimePickerDialog 实例代码: 页面添加两个Button,单击分别显示日期设置控件和时间设置控件,还是有TextView控件,用于显示设置后的系统时间 main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout x

  • android实现双日期选择控件(可隐藏日,只显示年月)

    在安卓开发中,会碰到选开始日期和结束日期的问题.特别是在使用Pad时,如果弹出一个Dialog,能够同时选择开始日期和结束日期,那将是极好的.我在开发中在DatePickerDialog的基础上做了修改,实现了这种Dialog.效果如下: 具体实现方法为: 先新建一个安卓项目DoubleDatePicker,在res/layout文件夹下新建date_picker_dialog.xml,内容如下: <?xml version="1.0" encoding="utf-8&

  • Android自定义控件之日期选择控件使用详解

    Android日期选择控件效果如下: 调用的代码: @OnClick(R.id.btn0) public void btn0() { final AlertDialog dialog = new AlertDialog.Builder(context).create(); dialog.show(); Window window = dialog.getWindow(); window.setContentView(R.layout.dialog_change_date); window.set

  • Android之日期时间选择控件DatePicker和TimePicker实例

    这个月根据需求在项目中做了一个时间选择器,虽然没有用到Android原生的时间选择控件,但我羞愧地发现自己竟然从来没有用过这方面控件!趁现在有时间,赶紧查缺补漏,写一篇博客吧. (注:为了便于区分,本文将选择年月日的控件称为日期选择控件,将选择时分的控件称为时间选择控件.) 1.创建项目 新建一个项目,MainActivity的布局如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  • Android开发中DatePicker日期与时间控件实例代码

    一.简介 二.方法 最日常的使用方法了 日期控件DatePicker 时间控件TimePicker 月份从0开始 三.代码实例 效果图: 代码: fry.Activity01 package fry; import com.example.DatePicherDemo1.R; import android.app.Activity; import android.os.Bundle; import android.widget.DatePicker; import android.widget.

  • Android 自定义日期段选择控件功能(开始时间-结束时间)

    开发中碰到个需求,需要在一个空间中选择完成开始和结束时间.实现的过程走的是程序员开发的老路子,找到轮子后自己改吧改吧就成了. 当时做的时候有几个需求:1.当天为最大的结束日期,2.最大选择范围1年,3.开始时间和结束时间可以为同一天.如有其他需求实现,可以参考代码改进一下.先上效果图: 视频点击后的虚影是屏幕录制的原因.实现步骤:(如有缺失什么资源,请告知.开始时间和结束时间显示自己布局内添加就可以) 1.自定义控件属性 <declare-styleable name="MyCalenda

  • Android自定义顶部导航栏控件实例代码

    下面一段代码给大家介绍了android 自定义顶部导航栏控件功能,具体代码如下所示: class HeaderBar @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : FrameLayout(context, attrs, defStyleAttr) { //重写构造方法 在java里面 我们一般是重写三个构造方法//在kotlin中 我们可以使用

  • Android 实现IOS 滚轮选择控件的实例(源码下载)

     Android 实现IOS 滚轮选择控件的实例 最近根据项目需要,整理了一个相对比较全面的 WheelView 使用控件,借用之前看到的一句话来说,就是站在巨人肩膀上,进行了一些小调整. 这里先贴上效果图 一般常用的时间选择格式,,单项选择,以及城市联动,这里基本都可以满足了. 这里把 单项选择,和 日期时间选择 给提出到 Util 类中,代码如下: public class Util { /** * 时间选择回调 */ public interface TimerPickerCallBack

  • android自定义WaveView水波纹控件

    本文实例为大家分享了android自定义WaveView水波纹控件的使用方法,供大家参考,具体内容如下 Github Repository and libaray WaveView水波纹控件 首先看下演示demo demo中可以看到不同高度,不同速度,不同幅度的水波纹:你可以通过view的参数直接控制view的表现形式. 引入你的工程 在项目的根目录下的build.gradle文件中添加如下代码: allprojects { repositories { ... maven { url 'htt

  • Android自定义View之组合控件实现类似电商app顶部栏

    本文实例为大家分享了Android自定义View之组合控件,仿电商app顶部栏的相关代码,供大家参考,具体内容如下 效果图: 分析:左右两边可以是TextView和Button,设置drawableTop即可,中间的看着像是EditText,但是用过淘宝天猫等类似app的话会发现点击搜索不是在当前Activit进行搜索的,是跳转到另外的页面进行的,所以用TextView然后设置背景即可. 实现流程 参数列表: 设置属性文件:values下建立attrs.xml文件,添加需要自定义的属性. <?x

  • Android 自定义底部上拉控件的实现方法

    前言 又到了新的一月,今天提供一个Android自定义底部上拉布局的实现,起因是自己在项目中需要实现这样一个控件,干脆自己写一个练练手. 写完了觉得能想到的需求都基本有了(可能会有其它需求,不过基本上改吧改吧就行了),又花了一点时间直接放到了Github上托管,希望能给您一些参考价值: SlideBottomLayout-Android 简单易上手的Android底部上拉控件 先看一下实现效果: 分析一下这种控件的基本需求有以下几种: 1.有一个部分是能够作为把手(就是图中的handle,)进行

  • android自定义圆形倒计时显示控件

    本文实例为大家分享了android自定义圆形倒计时显示控件的具体代码,供大家参考,具体内容如下 先上效果图 - 倒计时结束 代码块 attr.xml 控件需要用到的属性: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CountDownView"> <!--颜色--> <attr name

  • Android自定义view实现输入控件

    本文实例为大家分享了Android自定义view实现输入控件的具体代码,供大家参考,具体内容如下 网络上大部分的输入控件都是多个EditText组合而成,本例中采用的是: 单个EditText作为输入的捕捉控件 多个ImageView的子类作为显示的控件,绘制EditText中的数据 如上图: 输入前和输入后输入框需要发生响应的改变 点击自定义控件要弹出软键盘 EditText数据捕捉,以及EditView不能操作(如果可以操作,数据处理会混乱) 输完后会得到相应的提示 ImageView的子类

  • Android自定义view实现倒计时控件

    本文实例为大家分享了Android自定义view实现倒计时控件的具体代码,供大家参考,具体内容如下 直接上代码 自定义TextView 文字展示 public class StrokeTextView extends TextView { private TextView borderText = null;///用于描边的TextView private Context mContext; public StrokeTextView(Context context) { super(conte

  • Android自定义下拉刷新控件RefreshableView

    这是在了解下拉刷新功能原理下的产物,下拉刷新可以说是国产APP里面必有的功能,连Google都为此出了SwipeRefreshLayout,一种MD风格的下拉刷新. 不过,MD风格在国内似乎很是艰难,不单单是国内系统主流仍是4.4的原因,也有用户习惯的问题,扯的有点多了,在看了许多博客之后,我突然想写一个能仿照 SwipeRefreshLayout 的兼容所有控件的下拉刷新,不单单只是 ListView,希望它也可以包容普通的View和ScrollView,经过两天的奋斗,终于搞定了,因为我的目

随机推荐