Android简易自定义日历控件实践

来源:互联网 发布:单片机数码管显示数字 编辑:程序博客网 时间:2024/06/07 15:04

      最近写了一个简易的自定义日历控件,使用简单,方便自定义,特此抛砖引玉。在网上看了一些日历控件,复杂的日历控件虽然特效好看,但是集成度高,不易修改与扩展。本日历控件使用gridview编写,可扩展性好,适合需要简单用到日历的项目。效果如下图:


      代码如下:

import android.content.Context;import android.support.v4.content.ContextCompat;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.widget.AdapterView;import android.widget.GridView;import android.widget.LinearLayout;import android.widget.TextView;import java.util.Calendar;import java.util.Date;public class CustomCalendar extends LinearLayout implements View.OnClickListener {    TextView recordLeft;    TextView recordTitle;    TextView recordRight;    GridView recordGridView;    private Context context;    private int year;    private int month;    private int[][] days = new int[6][7];    private CalendarAdapter dateAdapter;    private Calendar calendar;    private Calendar minCalendar;    private OnTitleClickListener onTitleClickListener;    private OnDateSelectedListener onDateSelectedListener;    private OnMonthSelectedListener onMonthSelectedListener;    public CustomCalendar(Context context) {        super(context);        this.context = context;        init();    }    public CustomCalendar(Context context, AttributeSet attrs) {        super(context, attrs);        this.context = context;        init();    }    public CustomCalendar(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        this.context = context;        init();    }    private void init() {        View view = LayoutInflater.from(context).inflate(R.layout.layout_calendar, this, true);        recordLeft = (TextView) view.findViewById(R.id.record_left);        recordRight = (TextView) view.findViewById(R.id.record_right);        recordTitle = (TextView) view.findViewById(R.id.record_title);        recordGridView = (GridView) view.findViewById(R.id.record_gridView);        recordLeft.setOnClickListener(this);        recordRight.setOnClickListener(this);        recordTitle.setOnClickListener(this);        view.setBackgroundColor(ContextCompat.getColor(context, android.R.color.white));        calendar = Calendar.getInstance();        year = calendar.get(Calendar.YEAR);        month = calendar.get(Calendar.MONTH) + 1;        days = CalendarUtils.getDayOfMonthFormat(year, month);        dateAdapter = new CalendarAdapter(context, days, year, month);//传入当前月的年        String title = year + "年" + month + "月";        recordTitle.setText(title);        recordGridView.setAdapter(dateAdapter);        dateAdapter.changeListHeight(recordGridView, 7);        recordGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {            @Override            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {                if (i < 7 && dateAdapter.getItem(i) > 20) {                } else if (i > 20 && dateAdapter.getItem(i) < 15) {                } else {                    calendar.set(year, month - 1, dateAdapter.getItem(i));                    dateAdapter.setSelectDate(calendar.getTime());                    if (onDateSelectedListener != null) onDateSelectedListener.onDateSelected(calendar.getTime());                }            }        });    }    public void setOnTitleClickListener(OnTitleClickListener l) {        this.onTitleClickListener = l;    }    public void setOnDateSelectedListener(OnDateSelectedListener l) {        this.onDateSelectedListener = l;    }    public void setOnMonthSelectedListener(OnMonthSelectedListener l) {        this.onMonthSelectedListener = l;    }    public void preMonth() {        if (month == 1) {            month = 12;            year--;        } else {            month--;        }        updateMonth();    }    private void updateMonth() {        days = CalendarUtils.getDayOfMonthFormat(year, month);        dateAdapter = new CalendarAdapter(context, days, year, month);        dateAdapter.setSelectDate(calendar.getTime());        recordGridView.setAdapter(dateAdapter);        dateAdapter.changeListHeight(recordGridView, 7);        String title = year + "年" + month + "月";        recordTitle.setText(title);        if (minCalendar != null) {            if (minCalendar.get(Calendar.YEAR) >= year && minCalendar.get(Calendar.MONTH) + 1 >= month) {                setPreMonthEnable(false);            } else setPreMonthEnable(true);        }        Calendar calendar1 = Calendar.getInstance();        calendar1.set(Calendar.YEAR, year);        calendar1.set(Calendar.MONTH, month - 1);        if (onMonthSelectedListener != null) {            onMonthSelectedListener.onMonthSelected(calendar1.getTime());        }    }    public void nextMonth() {        if (month == 12) {            month = 1;            year++;        } else {            month++;        }        updateMonth();    }    public void onClick(View view) {        int i = view.getId();        if (i == R.id.record_left) {            preMonth();        } else if (i == R.id.record_title) {            if (onTitleClickListener != null) onTitleClickListener.onClick();        } else if (i == R.id.record_right) {            nextMonth();        }    }    public void showMonth(int year, int month) {        this.year = year;        this.month = month;        updateMonth();    }    public int getYear() {        return year;    }    public int getMonth() {        return month;    }    public void setPreMonthEnable(boolean enable) {        recordLeft.setEnabled(enable);        recordLeft.setTextColor(ContextCompat.getColor(context, enable ? android.R.color.holo_blue_light : android.R.color.darker_gray));    }    public void setMinCalendar(Calendar calendar) {        this.minCalendar = calendar;        if (minCalendar.get(Calendar.YEAR) >= year && minCalendar.get(Calendar.MONTH) + 1 >= month) {            setPreMonthEnable(false);        } else setPreMonthEnable(true);    }    public void setMarkingDays(int[] markingDays) {        dateAdapter.setMarkingDays(markingDays);    }    public void setSelectedDay(Date date) {        dateAdapter.setSelectDate(date);    }    public interface OnTitleClickListener {        void onClick();    }    public interface OnDateSelectedListener {        void onDateSelected(Date date);    }    public interface OnMonthSelectedListener {        void onMonthSelected(Date date);    }}
      这是一个将android原生控件组合起来的自定义控件,继承自LinearLayout,上方是日历标题和按钮,下方是一个Gridview。没有自定义属性,可以直接在代码里更改样式或者根据需要扩展。点击上一个月或者下一个月可切换,点击日历中某一天可以选中,同时onDateSelectedListener会执行回调方法,可以设置它以完成一些特定的业务需求。setMinCalendar()方法可以设置一个最小的日期,显示到最小日期时上一个月将不可点击。setMarkingDays()可以设置复数个被标识的日期,但要注意的是切换月份时标识会被清空,需重新设置。setSelectedDay()可以设置日历的初始选中日期。还有点击日历标题的回调和切换月份的回调,可以完成相应的业务需求。

      关于日历的显示规则可到CalendarAdapter里进行修改,日历日期的计算则包含在CalendarUtils里,整个日历控件只包含三个类和几个资源文件,层次简单,便于拓展。我已将完整代码打包成可以引用成lib的模块,集成到项目中即可使用。引用示例:

<com.example.simplecalendar.CustomCalendar        android:layout_width="match_parent"        android:layout_height="wrap_content"/>
      下载完整代码请移步至:点击打开链接


0 0
原创粉丝点击