自定义CalendarView,可以以周视图或者月视图显示

转载请注明转自,谢谢:http://blog.csdn.net/wmlove_hqy/article/details/46716951

首先分析一下功能。

1.能够左右滑动,这里选择通过ViewPager实现。

2.能够点击、选中日期,说明每一天是一个单独的View,选中的状态的变化改变,这里用StateDrawbleList实现。

3.通过Calendar提供的方法实现数据填充。

我们先来看看效果。

这里写图片描述

好,让我们开始吧!
我首先在这里定义一个DayView.

public class DayView extends TextView{

        private int backgroupColor = Color.GREEN;
        private Date date;
        private int day;
        private int month;

        public DayView(Context context) {
            super(context);
            setTextAlignment(TEXT_ALIGNMENT_CENTER);
            setBackgroupColor();
            setTextSize(20);
            setHeight(150);
            setWidth(150);
            setTextColor(Color.BLACK);
            setGravity(Gravity.CENTER);
        }

        //提供更改选中之后背景颜色
        public void setSelectColor(int color){
            this.backgroupColor = color;
            setBackgroupColor();
            postInvalidate();
        }

        private void setBackgroupColor(){
            //设置点击时改变背景色
            StateListDrawable drawable = new StateListDrawable();
            ShapeDrawable shape = new ShapeDrawable(new OvalShape());
            shape.setShaderFactory(new ShapeDrawable.ShaderFactory() {
                @Override
                public Shader resize(int i, int i1) {
                    return new LinearGradient(0,0,0,0,backgroupColor,backgroupColor, Shader.TileMode.REPEAT);
                }
            });
            drawable.addState(new int[]{android.R.attr.state_selected}, shape);
            setBackground(drawable);
        }

        //设置具体的日期
        public void setDay(boolean showotherdays,boolean inrange){
            //判断是否显示除了这个月份之外的日期。
            //默认不显示
            //当视图为周视图时,默认为真
            if(!showotherdays){
                String text = inrange ? day+"" : "";
                boolean enable = inrange ? true : false;
                setEnabled(enable);
                setText(text);
                return;
            }
            setText(String.valueOf(day));
        }

        //供外部调用,接受具体日期
        public void setTimeRange(Calendar calendar) {
            this.day = calendar.get(Calendar.DAY_OF_MONTH);
            this.month = calendar.get(Calendar.MONTH);
            this.date = calendar.getTime();
        }

        public String getTime(){
            String time;
            SimpleDateFormat format = new SimpleDateFormat("dd MMMM", Locale.ENGLISH);
            time = format.format(date);
            return time;
        }

        public Date getDate(){
            return this.date;
        }
    }

这就表示每一天的日期,只需要实例化出来并且设置他的日期。

每一天有了,现在需要一个容器把他放进去,可以是一个月,或者是一周。
所以我定义了一个TimeView来放这些Day.

public class TimeView extends RelativeLayout implements View.OnClickListener{
    //每个星期有的天数
    private static final int DEFAULT_DAY_IN_WEEK = 7;
    //一个月有几个星期,为月视图的时候默认是 6个星期,周视图为 1个星期。
    private int WEEK_IN_MONTH;
    //用来表示周视图或者月视图的flag
    private int timeflag;
    private boolean showOtherDay;

    private List<DayView> dayViewList;
    private Calendar mCalendarCurrent = null;
    //当Day被选中时候的回调
    private OnDaySelectListener mDaySelectCallBack;
    //当Day选中状态切换的时候的回调
    private OnDaySelectChangeListener mOnDaySelectChangeListener;

    public void setOnDaySelectListener(OnDaySelectListener mDaySelectCallBack) {
        this.mDaySelectCallBack = mDaySelectCallBack;
    }

    public void setOnDaySelectChangeListener(OnDaySelectChangeListener onDaySelectChangeListener){
        this.mOnDaySelectChangeListener = onDaySelectChangeListener;
    }

    public TimeView(Context context,Calendar calendarCurrent,int timeflag) {
        super(context);
        mCalendarCurrent = CalendarUtils.getCalenar();
        CalendarUtils.copyTo(calendarCurrent,mCalendarCurrent);

        showOtherDay = false;
        timeflag = Calendar.MONTH;
        dayViewList = new ArrayList<>()

        WEEK_IN_MONTH = (timeflag==Calendar.MONTH) ? 6 : 1;
        showOtherDay = (timeflag==Calendar.WEEK_OF_YEAR) ? true : false;
        setUpView();
        setDayView(timeflag);
    }
    //画出每一行,填充后用来显示一周
    private LinearLayout makeRow(){
        LinearLayout row = new LinearLayout(getContext());
        row.setOrientation(LinearLayout.HORIZONTAL);
        LinearLayout.LayoutParams params = new     LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,0,1f);
        row.setLayoutParams(params);
        return row;
    }
    //把周视图或者月视图画出来
    private void setUpView() {
        LinearLayout root = new LinearLayout(getContext());
        root.setOrientation(LinearLayout.VERTICAL);
        LinearLayout row;
        for(int i=0;i<WEEK_IN_MONTH;i++){
            row = makeRow();
            for(int x=0;x<DEFAULT_DAY_IN_WEEK;x++){
                DayView day = new DayView(getContext());
                day.setOnClickListener(this);
                row.addView(day, new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.MATCH_PARENT, 1f));
                dayViewList.add(day);
            }
            root.addView(row);
        }
        addView(root, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f));
    }
    //把每一个DayView设置日期
    private void setDayView(int timeflag){
        Calendar calendar = getWorkingCalendar();
        for(DayView dayView : dayViewList){
            dayView.setTimeRange(calendar);
            dayView.setDay(showOtherDay, calendar.get(timeflag) == mCalendarCurrent.get(timeflag));
            calendar.add(Calendar.DATE,1);
        }
    }
    //把Calendar设置为每个月或者每个星期的第一天
    private Calendar getWorkingCalendar(){
        Calendar calendar = CalendarUtils.getCalenar();
        CalendarUtils.copyTo(mCalendarCurrent, calendar);
        if(timeflag==Calendar.MONTH){CalendarUtils.setToFirstDayInMonth(calendar);}
        CalendarUtils.setToFirstDayInWeek(calendar);
        return calendar;
    }

    public Calendar getTimeCalendar(){
        Log.i("TAG",mCalendarCurrent.getTime()+"Timecurrent");
        return this.mCalendarCurrent;
    }

    public Date getDate(){
        return this.mCalendarCurrent.getTime();
    }

    public void setSelectColor(int color){
        for(DayView dayView : dayViewList){
            dayView.setSelectColor(color);
        }
    }

    public void setTimeFlag(int timeflag){
        this.timeflag = timeflag;
    }

    //处理点击事件
    @Override
    public void onClick(View view) {
        String time = null;
        Date date = null;
        if(view instanceof DayView){
            clearSelected();
            DayView dayView = (DayView) view;
            dayView.setSelected(true);
            Toast.makeText(getContext(),dayView.getText(),Toast.LENGTH_SHORT).show();
            time = dayView.getTime();
            date = dayView.getDate();
            postInvalidate();
        }
        mDaySelectCallBack.OnDaySelect(time,date);
        mOnDaySelectChangeListener.SelectChangeCallBack();
    }
    //用于清除其他TimeView的选中状态
    public void clearSelected() {
        for(DayView other : dayViewList){
            other.setSelected(false);
        }
    }
}

这就表示一个月或者一个星期的View,其实也就是ViewPager中的一个Item。
OnDaySelectListener 和OnDaySelectChangeListener 是定义用来回调的接口。
CalendarUtils是一个工具类。

那么有了Item,接下来就是添加到ViewPager中了。
而ViewPager也是放在一个容器之中,构成了这整个CalendarView。

public class CalendarView extends RelativeLayout {
    private ViewPager mViewPager;
    private CalendarViewAdapter mCalendarViewAdapter;
    private DaySelectChanegListener mDaySelectChanegListener = new DaySelectChanegListener();
    //默认是显示月视图的
    private boolean inweek = false;
    private int TimeFlag ;

    private List<TimeView> timeViewList = new ArrayList<>();
    private List<DaySelectChanegListener> OnTimeChangeListenerList = new ArrayList<>();
    private Calendar mCalendarMax = null;
    private Calendar mCalendarMin = null;
    private Calendar mCalendarCurrent = null;
    private OnTimeChangeListener mOnTimeChangeListener = null;


    public int getTimeFlag(boolean inweek) {
        return inweek ? Calendar.WEEK_OF_YEAR : Calendar.MONTH;
    }
    //把除了选中的Day所在的TimeView之外的day全部设置为非选中状态
    private class DaySelectChanegListener implements OnDaySelectChangeListener {

        @Override
        public void SelectChangeCallBack() {
            TimeView current = timeViewList.get(mViewPager.getCurrentItem());
            for (TimeView other : timeViewList) {
                if (other!=current){other.clearSelected();}
            }
        }
    }

    public CalendarView(Context context, AttributeSet attrs) {
        super(context, attrs);

        TypedArray t = context.obtainStyledAttributes(attrs,R.styleable.CalendarView);
        inweek = t.getBoolean(R.styleable.CalendarView_viewinview,false);
        t.recycle();

        TimeFlag = getTimeFlag(inweek);

        LinearLayout root = new LinearLayout(context);
        root.setOrientation(LinearLayout.VERTICAL);

        addTimeView();

        LinearLayout title = new LinearLayout(context);
        title.setOrientation(LinearLayout.HORIZONTAL);
        Calendar calendar = CalendarUtils.getCalenar();
        CalendarUtils.setToFirstDayInWeek(calendar);
        SimpleDateFormat format = new SimpleDateFormat("EEE", Locale.ENGLISH);
        for (int i = 0; i < 7; i++) {
            TextView textView = new TextView(context);
            textView.setWidth(150);
            textView.setHeight(150);
            textView.setGravity(Gravity.CENTER);
            textView.setTextAlignment(TEXT_ALIGNMENT_CENTER);
            textView.setTextColor(Color.BLACK);
            textView.setText(format.format(calendar.getTime()));
            Log.i("TAG", format.format(calendar.getTime()));
            calendar.add(Calendar.DATE, 1);
            title.addView(textView);
        }
        Log.i("TAG", title.getChildCount() + "childcount");
        root.addView(title);

        mViewPager = new ViewPager(context);
        mCalendarViewAdapter = new CalendarViewAdapter();
        mViewPager.setAdapter(mCalendarViewAdapter);
        mViewPager.setCurrentItem(getIndex());
        mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

            @Override
            public void onPageSelected(int position) {
                TimeView timeView = timeViewList.get(position);
                Date date = timeView.getDate();
                mOnTimeChangeListener.OnTimeChange(date);
            }

            @Override
            public void onPageScrollStateChanged(int state) {}
        });

        root.addView(mViewPager, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        addView(root);
    }
    //当前的ViewPager中的TimeView因为滑动而改变时的回调。
    public void setOnTimeChangeListener(OnTimeChangeListener listener){
        if(listener!=null){
            this.mOnTimeChangeListener = listener;
        }
        else throw new NullPointerException("OnTimeChangeListener can not be null!");
    }

    public void setOnDaySelectListener(OnDaySelectListener listener){
        if(listener!=null){
            for(TimeView timeView : timeViewList){
                timeView.setOnDaySelectListener(listener);
            }
        }
        else throw new NullPointerException("OnDaySelectListener can not be null!");
    }
    //设置可以显示的最大日期
    public void setMaxDate(Calendar calendarMax){
        this.mCalendarMax = calendarMax;
        postInvalidate();
    }
    //设置可以显示的最小日期
    public void setMinDate(Calendar calendarMin){
        this.mCalendarMin = calendarMin;
        postInvalidate();
    }

    public void setSelectColor(int color){
        for(TimeView timeView : timeViewList){
            timeView.setSelectColor(color);
        }
    }
    //设置当前的日期
    public void setCurrentCalendar(Calendar currentCalendar){
        this.mCalendarCurrent = currentCalendar;
        postInvalidate();
    }
    //得到可以显示的最小Calendar
    private Calendar getMinCalendarDay(){
        if(mCalendarMin==null){
            int mindate = -2;
            Calendar min = CalendarUtils.getCalenar();
            min.add(Calendar.YEAR, mindate);
            return min;
        }
        return mCalendarMin;
    }
    //得到可以显示的最大Calendar
    private Calendar getMaxCalendarDay(){
        if(mCalendarMax==null){
            int maxdate = 2;
            Calendar max = CalendarUtils.getCalenar();
            max.add(Calendar.YEAR,maxdate);
            return max;
        }
        return mCalendarMax;
    }

    //把符合条件的TimeView添加到集合当中
    private void addTimeView(){
        Calendar minCalendar = getMinCalendarDay();
        Calendar maxCalendar = getMaxCalendarDay();
        if(mCalendarCurrent==null){
            mCalendarCurrent = CalendarUtils.getCalenar();
        }
        CalendarUtils.copyTo(minCalendar,mCalendarCurrent);
        Log.i("TAG",minCalendar.getTime()+"minCalendar"+maxCalendar.getTime()+"maxCalendar"+mCalendarCurrent.getTime()+"mCalendarCurrent");
        while (CalendarUtils.isBefore(mCalendarCurrent, maxCalendar)){
            TimeView timeView = new TimeView(getContext(),mCalendarCurrent,TimeFlag);
            timeView.setOnDaySelectChangeListener(mDaySelectChanegListener);
            timeViewList.add(timeView);
            mCalendarCurrent.add(TimeFlag, 1);
        }
    }
    //得到当前日期的Index
    private int getIndex(){
        Calendar c = CalendarUtils.getCalenar();
        for(int i=0;i<timeViewList.size();i++){
            TimeView timeView = timeViewList.get(i);
            Calendar other = timeView.getTimeCalendar();
            if(c.get(Calendar.YEAR)==other.get(Calendar.YEAR)
                    &&c.get(Calendar.MONTH)==other.get(Calendar.MONTH)){
                        if(TimeFlag==Calendar.WEEK_OF_YEAR){
                       if(c.get(Calendar.WEEK_OF_YEAR)==other.get(Calendar.WEEK_OF_YEAR)){return i;}
                        }
                return i;
            }
        }
        return 0;
    }
    //ViewPager的适配器
    private class CalendarViewAdapter extends PagerAdapter{

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

        @Override
        public boolean isViewFromObject(View view, Object o) {
            return view == o;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            TimeView timeView = timeViewList.get(position);
            Log.i("TAG",timeViewList.size()+"size");
            container.addView(timeView);
            return timeViewList.get(position);
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView(timeViewList.get(position));
        }
    }
}

到此就完成了这一个自定义的CalendarView,很简单吧。
总结一下。
主要是ViewPager中Item数据的填充,通过Calendar提供的一些方法就可以轻松的把你需要的日期筛选出来。然后就是把这些日期通过简单的逻辑判断填充到每一个所需要的View中,再就当做Item显示出来。还有一些基本的功能,如选中某一天能够回调这一天的日期,当前显示的月或者周是第几周或者哪一个月,再就是能够设置显示的最大日期和最小日期,选中某一天时的背景。最后是我主要想实现的,能够通过在布局文件中设置CalendarView是显示月视图还是周视图。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:wmlove="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" tools:context=".MainActivity">

    <wmlove.library.CalendarView
        wmlove:viewinview="false"
        android:id="@+id/calendarview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </wmlove.library.CalendarView>

</RelativeLayout>

如果有考虑不周到的地方还提出,一同探讨,谢谢。
也可以去我的GitHubh上给我Pull Requests,或者提issues
https://github.com/t154191277/CalendarView-Android

源代码下载地址:http://download.csdn.net/detail/wmlove_hqy/8859825

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Vue中定制FullCalendar自定义视图,可以按照以下步骤进行: 1. 首先,需要在Vue项目中安装FullCalendar插件,可以使用npm命令进行安装: ```shell npm install --save @fullcalendar/vue @fullcalendar/daygrid ``` 2. 在Vue组件中引入FullCalendar插件,并注册FullCalendar组件: ```javascript <template> <FullCalendar :plugins="calendarPlugins" :initialView="calendarView" /> </template> <script> import FullCalendar from '@fullcalendar/vue' import dayGridPlugin from '@fullcalendar/daygrid' export default { components: { FullCalendar }, data() { return { calendarPlugins: [dayGridPlugin], calendarView: 'dayGridMonth' } } } </script> ``` 3. 接下来,可以使用FullCalendar提供的API来自定义视图。例如,可以使用`headerToolbar`属性来自定义日历的头部工具栏: ```javascript <template> <FullCalendar :plugins="calendarPlugins" :initialView="calendarView" :headerToolbar="calendarHeader" /> </template> <script> import FullCalendar from '@fullcalendar/vue' import dayGridPlugin from '@fullcalendar/daygrid' export default { components: { FullCalendar }, data() { return { calendarPlugins: [dayGridPlugin], calendarView: 'dayGridMonth', calendarHeader: { left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay' } } } } </script> ``` 4. 可以使用`slot`来自定义日历的内容。例如,可以使用`dayContent`插槽来自定义每个日期格子的内容: ```javascript <template> <FullCalendar :plugins="calendarPlugins" :initialView="calendarView"> <template #dayContent="{ date }"> <div class="custom-day-content">{{ date.getDate() }}</div> </template> </FullCalendar> </template> <script> import FullCalendar from '@fullcalendar/vue' import dayGridPlugin from '@fullcalendar/daygrid' export default { components: { FullCalendar }, data() { return { calendarPlugins: [dayGridPlugin], calendarView: 'dayGridMonth' } } } </script> <style> .custom-day-content { background-color: #f0f0f0; border-radius: 50%; width: 30px; height: 30px; line-height: 30px; text-align: center; } </style> ``` 以上是在Vue中定制FullCalendar自定义视图的基本步骤和示例代码,可以根据具体需求进行自定义

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值