Android 自定义日期段选择控件,开始日期-结束日期。

这篇博客分享了在Android开发中创建一个自定义日期段选择控件的实现过程,包括选择开始和结束日期的功能。控件允许的最大选择范围为1年,且允许开始和结束日期为同一天。博客内容涵盖了自定义控件属性、代码、布局文件、资源文件的详细步骤,并提供了在Activity中的使用示例。
摘要由CSDN通过智能技术生成

开发中碰到个需求,需要在一个控件中选择完成开始和结束日期。实现的过程走的是程序员开发的老路子,找到轮子后自己改吧改吧就成了。去年做的找不到参考的文章连接了,请原博主见谅。

当时做的时候有几个需求: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
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值