Android日历控件

做的是一个酒店的项目,可以选择入住和离开的日期。声明为了省事在网上找的资料,自己修改的逻辑,希望对需要的朋友有帮助。喜欢的给个好评。谢谢啦!祝生活愉快!
先上图
日历的样式,可以上下纵向滑动
第一步,搭建布局xml

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/days_detail"
                android:gravity="center"
                android:padding="16dp"
                android:text="选择住店离店日期"
                android:textColor="@color/white"
                android:textSize="18sp" />

            <ImageView
                android:id="@+id/back_to_up"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="10dp"
                android:src="@drawable/backto" />
        </FrameLayout>

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <View
                android:layout_width="match_parent"
                android:layout_height="30dp"
                android:background="@color/days_detail" />

            <android.support.v7.widget.CardView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_margin="10dp"
                android:layout_marginTop="20dp"
                android:padding="10dp"
                app:cardCornerRadius="10dp"
                app:cardElevation="16dp">

                <LinearLayout
                    android:id="@+id/ll"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical" />
            </android.support.v7.widget.CardView>
        </FrameLayout>
    </LinearLayout>
</ScrollView>

第二部在编写逻辑

 LinearLayout ll;
    MyCalendar c1;
    Date date;
    String nowday;
    long nd = 1000 * 24L * 60L * 60L;//一天的毫秒数
    SimpleDateFormat simpleDateFormat, sd1, sd2;
    SharedPreferences sp;
    SharedPreferences.Editor editor;
    private String inday, outday//日期
     sp_inday, sp_outday;//周几
  Activity   extends BaseActivity implements MyCalendar.OnDaySelectListener {

继承BaseActivity实现点击日历的监听回调

 private void init() {
        List<String> listDate = getDateList();
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        for (int i = 0; i < listDate.size(); i++) {
            c1 = new MyCalendar(this);
            c1.setLayoutParams(params);
            Date date = null;
            try {
                date = simpleDateFormat.parse(listDate.get(i));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            if (!"".equals(sp_inday)) {
                c1.setInDay(sp_inday);
            }
            if (!"".equals(sp_outday)) {
                c1.setOutDay(sp_outday);
            }
            c1.setTheDay(date);
            c1.setOnDaySelectListener(this);
            ll.addView(c1);
        }
    }

    @Override
    public void onDaySelectListener(View view, String date) {
        //若日历日期小于当前日期,或日历日期-当前日期超过三个月,则不能点击
        try {
            if (simpleDateFormat.parse(date).getTime() < simpleDateFormat.parse(nowday).getTime()) {
                return;
            }
            long dayxc = (simpleDateFormat.parse(date).getTime() - simpleDateFormat.parse(nowday).getTime()) / nd;
            if (dayxc > 90) {
                return;
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        //若以前已经选择了日期,则在进入日历后会显示以选择的日期,该部分作用则是重新点击日历时,清空以前选择的数据(包括背景图案)
        if (!"".equals(sp_inday)) {
            c1.viewIn.setBackgroundColor(Color.WHITE);
            ((TextView) c1.viewIn.findViewById(R.id.tv_calendar_day)).setTextColor(Color.BLACK);
            ((TextView) c1.viewIn.findViewById(R.id.tv_calendar)).setText("");
        }
        if (!"".equals(sp_outday)) {
            c1.viewOut.setBackgroundColor(Color.WHITE);
            ((TextView) c1.viewOut.findViewById(R.id.tv_calendar_day)).setTextColor(Color.BLACK);
            ((TextView) c1.viewOut.findViewById(R.id.tv_calendar)).setText("");
        }

        String dateDay = date.split("-")[2];
        if (Integer.parseInt(dateDay) < 10) {
            dateDay = date.split("-")[2].replace("0", "");
        }
        TextView textDayView = (TextView) view.findViewById(R.id.tv_calendar_day);
        TextView textView = (TextView) view.findViewById(R.id.tv_calendar);
        view.setBackgroundColor(Color.parseColor("#33B5E5"));
        textDayView.setTextColor(Color.WHITE);
        if (null == inday || inday.equals("")) {
            textDayView.setText(dateDay);
            textView.setText("入住");
            inday = date;
        } else {
            if (inday.equals(date)) {
                view.setBackgroundColor(Color.WHITE);
                textDayView.setText(dateDay);
                textDayView.setTextColor(Color.BLACK);
                textView.setText("");
                inday = "";
            } else {
                try {
                    if (simpleDateFormat.parse(date).getTime() < simpleDateFormat.parse(inday).getTime()) {
                        view.setBackgroundColor(Color.WHITE);
                        textDayView.setTextColor(Color.BLACK);
                        Toast.makeText(CalendarActivity.this, "离开日期不能小于入住日期", Toast.LENGTH_SHORT).show();
                        return;
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                textDayView.setText(dateDay);
                textView.setText("离开");
                outday = date;
                editor.putString("dateIn", inday);
                editor.putString("dateOut", outday);
                editor.commit();
                finish();
            }
        }
    }

    //根据当前日期,向后数三个月(若当前day不是1号,为满足至少90天,则需要向后数4个月)
    @SuppressLint("SimpleDateFormat")
    public List<String> getDateList() {
        List<String> list = new ArrayList<String>();
        Date date = new Date();
        int nowMon = date.getMonth() + 1;
        String yyyy = sd1.format(date);
        String dd = sd2.format(date);
        if (nowMon == 9) {
            list.add(simpleDateFormat.format(date));
            list.add(yyyy + "-10-" + dd);
            list.add(yyyy + "-11-" + dd);
            if (!dd.equals("01")) {
                list.add(yyyy + "-12-" + dd);
            }
        } else if (nowMon == 10) {
            list.add(yyyy + "-10-" + dd);
            list.add(yyyy + "-11-" + dd);
            list.add(yyyy + "-12-" + dd);
            if (!dd.equals("01")) {
                list.add((Integer.parseInt(yyyy) + 1) + "-01-" + dd);
            }
        } else if (nowMon == 11) {
            list.add(yyyy + "-11-" + dd);
            list.add(yyyy + "-12-" + dd);
            list.add((Integer.parseInt(yyyy) + 1) + "-01-" + dd);
            if (!dd.equals("01")) {
                list.add((Integer.parseInt(yyyy) + 1) + "-02-" + dd);
            }
        } else if (nowMon == 12) {
            list.add(yyyy + "-12-" + dd);
            list.add((Integer.parseInt(yyyy) + 1) + "-01-" + dd);
            list.add((Integer.parseInt(yyyy) + 1) + "-02-" + dd);
            if (!dd.equals("01")) {
                list.add((Integer.parseInt(yyyy) + 1) + "-03-" + dd);
            }
        } else {
            list.add(yyyy + "-" + getMon(nowMon) + "-" + dd);
            list.add(yyyy + "-" + getMon((nowMon + 1)) + "-" + dd);
            list.add(yyyy + "-" + getMon((nowMon + 2)) + "-" + dd);
            if (!dd.equals("01")) {
                list.add(yyyy + "-" + getMon((nowMon + 3)) + "-" + dd);
            }
        }
        return list;
    }

    public String getMon(int mon) {
        String month = "";
        if (mon < 10) {
            month = "0" + mon;
        } else {
            month = "" + mon;
        }
        return month;
    }

第三部 编写监听,自定义的控件

public class MyCalendar extends LinearLayout {

    private static Context context;

    private Date theInDay;
    private String inday = "", outday = "";
    public static View viewIn;
    public static View viewOut;
    public static String positionIn;
    public static String positionOut;

    public static final int WEEKDAYS = 7;

    public static String[] WEEK = {
            "周日",
            "周一",
            "周二",
            "周三",
            "周四",
            "周五",
            "周六"
    };

    static long nd = 1000 * 24L * 60L * 60L;//一天的毫秒数

    private List<String> gvList;//存放天

    private OnDaySelectListener callBack;//回调函数

    private static String nowday = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

    private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMM");//日期格式化

    private static SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd");//日期格式化

    /**
     * 构造函数
     *
     * @param context
     */
    public MyCalendar(Context context) {
        super(context);
        MyCalendar.context = context;
    }

    /**
     * 日期变量转成对应的星期字符串
     *
     * @param date
     * @return
     */
    public static String DateToWeek(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayIndex = calendar.get(Calendar.DAY_OF_WEEK);
        if (dayIndex < 1 || dayIndex > WEEKDAYS) {
            return null;
        }

        return WEEK[dayIndex - 1];
    }

    /**
     * 获得天数差
     *
     * @param begin
     * @param end
     * @return
     */
    public static long getDayDiff(Date begin, Date end) {
        long day = 1;
        if (end.getTime() < begin.getTime()) {
            day = -1;
        } else if (end.getTime() == begin.getTime()) {
            day = 1;
        } else {
            day += (end.getTime() - begin.getTime()) / (24 * 60 * 60 * 1000);
        }
        return day;
    }

    /**
     * 将yyyy-MM-dd类型转换成MM.dd
     *
     * @param time
     * @return
     * @throws ParseException
     */
    public static String format1(String time) throws ParseException {
        SimpleDateFormat from = new SimpleDateFormat("yyyy-MM-dd", Locale.CHINA);
        SimpleDateFormat to = new SimpleDateFormat("MM.dd", Locale.CHINA);
        return to.format(from.parse(time));
    }

    /**
     * 获得指定日期的后一天
     *
     * @param specifiedDay
     * @return
     */
    public static String getSpecifiedDayAfter(String specifiedDay) {
        Calendar c = Calendar.getInstance();
        Date date = null;
        try {
            date = new SimpleDateFormat("yy-MM-dd").parse(specifiedDay);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.setTime(date);
        int day = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day + 1);

        String dayAfter = new SimpleDateFormat("yyyy-MM-dd")
                .format(c.getTime());
        return dayAfter;
    }

    /**
     * 构造函数
     *
     * @param context
     */
    public MyCalendar(Context context, AttributeSet attrs) {
        super(context, attrs);
        MyCalendar.context = context;
    }

    public void setInDay(String inday) {
        this.inday = inday;
    }

    public void setOutDay(String outday) {
        this.outday = outday;
    }

    public void setTheDay(Date dateIn) {
        this.theInDay = dateIn;
        init();
    }

    /**
     * 初始化日期以及view等控件
     */
    private void init() {
        gvList = new ArrayList<String>();//存放天
        final Calendar cal = Calendar.getInstance();//获取日历实例
        cal.setTime(theInDay);//cal设置为当天的
        cal.set(Calendar.DATE, 1);//cal设置当前day为当前月第一天
        int tempSum = countNeedHowMuchEmpety(cal);//获取当前月第一天为星期几
        int dayNumInMonth = getDayNumInMonth(cal);//获取当前月有多少天
        setGvListData(tempSum, dayNumInMonth, cal.get(Calendar.YEAR) + "-" + getMonth((cal.get(Calendar.MONTH) + 1)));

        View view = LayoutInflater.from(context).inflate(R.layout.comm_calendar, this, true);//获取布局,开始初始化
        TextView tv_year = (TextView) view.findViewById(R.id.tv_year);
        if (cal.get(Calendar.YEAR) > new Date().getYear()) {
            tv_year.setVisibility(View.VISIBLE);
            tv_year.setText(cal.get(Calendar.YEAR) + "年");
        }
        TextView tv_month = (TextView) view.findViewById(R.id.tv_month);
        tv_month.setText(String.valueOf(theInDay.getMonth() + 1));
        MyGridView gv = (MyGridView) view.findViewById(R.id.gv_calendar);
        calendarGridViewAdapter gridViewAdapter = new calendarGridViewAdapter(gvList, inday, outday);
        gv.setAdapter(gridViewAdapter);
        gv.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View arg1, int position, long arg3) {
                String choiceDay = (String) adapterView.getAdapter().getItem(position);
                String[] date = choiceDay.split(",");
                String day = date[1];
                if (!" ".equals(day)) {
                    if (Integer.parseInt(day) < 10) {
                        day = "0" + date[1];
                    }
                    choiceDay = date[0] + "-" + day;
                    if (callBack != null) {//调用回调函数回调数据
                        callBack.onDaySelectListener(arg1, choiceDay);
                    }
                }
            }
        });
    }

    /**
     * 为gridview中添加需要展示的数据
     *
     * @param tempSum
     * @param dayNumInMonth
     */
    private void setGvListData(int tempSum, int dayNumInMonth, String YM) {
        gvList.clear();
        for (int i = 0; i < tempSum; i++) {
            gvList.add(" , ");
        }
        for (int j = 1; j <= dayNumInMonth; j++) {
            gvList.add(YM + "," + String.valueOf(j));
        }
    }

    private String getMonth(int month) {
        String mon = "";
        if (month < 10) {
            mon = "0" + month;
        } else {
            mon = "" + month;
        }
        return mon;
    }

    /**
     * 获取当前月的总共天数
     *
     * @param cal
     * @return cal.getActualMaximum(Calendar.DATE)
     */
    private int getDayNumInMonth(Calendar cal) {
        return cal.getActualMaximum(Calendar.DATE);
    }

    /**
     * 获取当前月第一天在第一个礼拜的第几天,得出第一天是星期几
     *
     * @param cal
     * @return firstDayInWeek
     */
    private int countNeedHowMuchEmpety(Calendar cal) {
        int firstDayInWeek = cal.get(Calendar.DAY_OF_WEEK) - 1;

        Log.e("MyCalendar", String.valueOf(firstDayInWeek));
        return firstDayInWeek;
    }


    /**
     * gridview中adapter的viewholder
     *
     * @author wx
     */
    static class GrideViewHolder {
        TextView tvDay, tv;
    }

    /**
     * gridview的adapter
     *
     * @author Administrator
     */
    static class calendarGridViewAdapter extends BaseAdapter {

        List<String> gvList;//存放天
        String inday, outday;

        public calendarGridViewAdapter(List<String> gvList, String inday, String outday) {
            super();
            this.gvList = gvList;
            this.inday = inday;
            this.outday = outday;
        }

        @Override
        public int getCount() {
            return gvList.size();
        }

        @Override
        public String getItem(int position) {
            return gvList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            GrideViewHolder holder;
            if (convertView == null) {
                holder = new GrideViewHolder();
                convertView = inflate(context, R.layout.common_calendar_gridview_item, null);
                holder.tv = (TextView) convertView.findViewById(R.id.tv_calendar);
                holder.tvDay = (TextView) convertView.findViewById(R.id.tv_calendar_day);
                convertView.setTag(holder);
            } else {
                holder = (GrideViewHolder) convertView.getTag();
            }
            String[] date = getItem(position).split(",");
            holder.tvDay.setText(date[1]);
            if ((position + 1) % 7 == 0 || (position) % 7 == 0) {
                holder.tvDay.setTextColor(Color.parseColor("#339900"));
            }
            if (!date[1].equals(" ")) {
                String day = date[1];
                if (Integer.parseInt(date[1]) < 10) {
                    day = "0" + date[1];
                }
                if ((date[0] + "-" + day).equals(nowday)) {
                    holder.tvDay.setTextColor(Color.parseColor("#FF6600"));
                    holder.tvDay.setTextSize(15);
                    holder.tvDay.setText("今天");
                }
                if (!"".equals(inday) && (date[0] + "-" + day).equals(inday)) {
                    convertView.setBackgroundColor(Color.parseColor("#33B5E5"));
                    holder.tvDay.setTextColor(Color.WHITE);
                    holder.tvDay.setText(date[1]);
                    holder.tv.setText("入住");
                    viewIn = convertView;
                    positionIn = date[1];
                }
                if (!"".equals(outday) && (date[0] + "-" + day).equals(outday)) {
                    convertView.setBackgroundColor(Color.parseColor("#33B5E5"));
                    holder.tvDay.setTextColor(Color.WHITE);
                    holder.tvDay.setText(date[1]);
                    holder.tv.setText("离开");
                    viewOut = convertView;
                    positionOut = date[1];
                }
                try {
                    //若日历日期<当前日期,则不能选择
                    if (dateFormat2.parse(date[0] + "-" + day).getTime() < dateFormat2.parse(nowday).getTime()) {
                        holder.tvDay.setTextColor(Color.parseColor("#999999"));
                    }
                    //若日历日期-当前日期>90天,则不能选择
                    long dayxc = (dateFormat2.parse(date[0] + "-" + day).getTime() - dateFormat2.parse(nowday).getTime()) / nd;
                    if (dayxc > 90) {
                        holder.tvDay.setTextColor(Color.parseColor("#999999"));
                    }
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            return convertView;
        }
    }

    /**
     * 自定义监听接口
     *
     * @author Administrator
     */
    public interface OnDaySelectListener {
        void onDaySelectListener(View view, String date);
    }

    /**
     * 自定义监听接口设置对象
     *
     * @param o
     */
    public void setOnDaySelectListener(OnDaySelectListener o) {
        callBack = o;
    }
}

在界面显示选择的日期
看图
接下来就是为了显示选择的日期进行逻辑判断,包括字符串的转换以及日期格式的转换,日期的计算等。

simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        if ("".equals(home_into_date.getText().toString())
                && "".equals(home_out_date.getText().toString())) {
            inday = simpleDateFormat.format(new Date());
            try {
                //转换时间格式
                String changeDate = MyCalendar.format1(inday);

                Date dateIn = simpleDateFormat.parse(inday);
                //将日期转换成周
                String weekIn = MyCalendar.DateToWeek(dateIn);
                home_into_date.setText("" + changeDate + weekIn);
                String nextDay = MyCalendar.format1(MyCalendar.getSpecifiedDayAfter(inday));
                Date dateOut = simpleDateFormat.parse(MyCalendar.getSpecifiedDayAfter(inday));
                String weekOut = MyCalendar.DateToWeek(dateOut);
                home_out_date.setText("" + nextDay + weekOut);
                long days = MyCalendar.getDayDiff(dateIn, dateOut);
                home_total_days.setText("共" + (days - 1) + "晚");
            } catch (ParseException e) {
                e.printStackTrace();
            }
        } else {
        //这里使用sp传的值
            inday = pro.getString("dateIn", "");
            outday = pro.getString("dateOut", "");
            try {
                String changeDate = MyCalendar.format1(inday);
                Date dateIn = simpleDateFormat.parse(inday);
                //将日期转换成周
                String weekIn = MyCalendar.DateToWeek(dateIn);
                home_into_date.setText("" + changeDate + weekIn);
                String outDay = MyCalendar.format1(outday);
                Date dateOut = simpleDateFormat.parse(outday);
                String weekOut = MyCalendar.DateToWeek(dateOut);
                home_out_date.setText("" + outDay + weekOut);
                long days = MyCalendar.getDayDiff(dateIn, dateOut);
                home_total_days.setText("共" + (days - 1) + "晚");
            } catch (ParseException e) {
                e.printStackTrace();
            }

其中有几个布局,给图自己写吧
comm_calendar
这里写图片描述
common_calendar_gridview_item

<LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:id="@+id/tv_calendar_day"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:gravity="center"
                android:textSize="15sp" />

            <TextView
                android:id="@+id/tv_calendar"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:gravity="center"
                android:textColor="#FFFFFF"
                android:textSize="15sp" />
        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="0.5dp"
            android:background="#E4E4E4" />
    </LinearLayout>

看到这里了,给个好评吧!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值