日历控件--MaterialCalendarView 详解

给大家推广下我业余做的新产品“班费记账”,支持微信小程序和QQ小程序

https://jizhang.lanzou.cloud/

主要为了解决传统记账方式的的一下问题

班费怎么记账?

班费记账格式是什么?

欢迎大家捧捧场,多多帮忙宣传下!
--------------以下为正文:

项目中遇到了日历选择的模块,经过搜索,发现了一个比较好用的日历控件MaterialCalendarView
下面讲讲它的基本用法.
首先对他添加依赖

compile 'com.prolificinteractive:material-calendarview:1.4.0'

由于日历控件的弹出一班是需要以弹窗dialog的形式弹出的 ,所以我这里用了DialogFragment ,不太了解的朋友可以去搜一下怎么使用。

1,新建一个fragment 让它继承自DialogFragment
在布局文件中添加代码,布局问价比较简单,这里贴上全部的代码

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.xunku.dianjia.home.fragment.CalendarViewFragment">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <com.prolificinteractive.materialcalendarview.MaterialCalendarView
            android:id="@+id/mcv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            >
        </com.prolificinteractive.materialcalendarview.MaterialCalendarView>
    </LinearLayout>

</FrameLayout>

2,先贴上fragment全部的代码,后面慢慢讲解(里面注释也很详细)

/**
 * 作为dialog弹出日历选择控件
 * 郑
 */
public class CalendarViewFragment extends DialogFragment implements OnDateSelectedListener {
    DialogFragment mContext=this;

    private View view;
    MaterialCalendarView mcv;
    //接收从Activity传来的数据
    Bundle timeBundle;

    OnFrgDataListener IListener;


    public CalendarViewFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        view=inflater.inflate(R.layout.fragment_calendar_view, container, false);
        mcv= (MaterialCalendarView) view.findViewById(R.id.mcv);
        timeBundle=getArguments();
        initData();
        return view;
    }
    @Override
    public void onStart() {
        super.onStart();

        //下面这些都是为了让dialog宽度全充满
        Window win = getDialog().getWindow();
        // 一定要设置Background,如果不设置,window属性设置无效
        win.setBackgroundDrawable( new ColorDrawable(getResources().getColor(R.color.white)));

        DisplayMetrics dm = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics( dm );
        WindowManager.LayoutParams params = win.getAttributes();
       // params.gravity = Gravity.BOTTOM;
        // 使用ViewGroup.LayoutParams,以便Dialog 宽度充满整个屏幕

        params.width =  ViewGroup.LayoutParams.MATCH_PARENT;
        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        win.setAttributes(params);

        /*if (dialog != null) {
            DisplayMetrics dm = new DisplayMetrics();
            getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
            dialog.getWindow().setLayout((int) (dm.widthPixels * 1), ViewGroup.LayoutParams.WRAP_CONTENT);
        }*/
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //这个主题 背景全透明 没有半透明
       // setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo_Light);
    }

    public void initData(){
        // 显示兴起补全的整个礼拜的上个月或者下个月的日期 一般会多出一行整个礼拜
        // 点击补全出来的另外一个月的信息 可以直接跳到那个月
        mcv.setShowOtherDates(MaterialCalendarView.SHOW_ALL);

        // 设置日历默认的时间为当前的时间
        mcv.setSelectedDate(new Date());

        // 日历的主要设置
        mcv.state().edit()
                // 设置你的日历 第一天是周一还是周一
                .setFirstDayOfWeek(Calendar.MONDAY)
                // 设置你的日历的最小的月份  月份为你设置的最小月份的下个月 比如 你设置最小为1月 其实你只能滑到2月
                .setMinimumDate(CalendarDay.from(2015, 1, 1))
                // 同最小 设置最大
                .setMaximumDate(CalendarDay.from(2018, 1, 1))
                // 设置你的日历的模式  是按月 还是按周
                .setCalendarDisplayMode(CalendarMode.MONTHS)
                .commit();

// 设置你选中日期的背景底色
        mcv.setSelectionColor(getResources().getColor(R.color.date_choose));
//        mcv.setSelectionColor(0xff4285f4);

//
        mcv.setOnDateChangedListener(this);

    }

    /**
     * 日期选择 回调函数
     * @param widget
     * @param date
     * @param selected
     */
    @Override
    public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) {
        Toast.makeText(getActivity(),getSelectedDatesString(),Toast.LENGTH_SHORT).show();
 //       Toast.makeText(getActivity(),"从Activity传递的数据:"+(String)timeBundle.get("date"),Toast.LENGTH_SHORT).show();
        IListener.progress(mcv.getSelectedDate().getDate());

        //选择后,延迟消失
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mContext.dismiss();
            }
        }, 1000);


    }

    /**
     * 将日期转换为字符串
     * @return
     */
    private String getSelectedDatesString() {
        CalendarDay date = mcv.getSelectedDate();
        if (date == null) {
            return "No Selection";
        }
        Log.i("sinstar", "getSelectedDatesString: "+date.toString());
        return FORMATTER.format(date.getDate());
    }

    private static final DateFormat FORMATTER = SimpleDateFormat.getDateInstance();


    /**
     * 定义接口,向Activity传递数据
     */
    public interface OnFrgDataListener{
        public void progress(Date date);
    }

    /**
     * 注入实例方法
     * @param
     */
   /* public void setOnFrgDataListener(OnFrgDataListener listener){
        IListener=listener;
    }*/
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if(activity instanceof OnFrgDataListener)
        {
            IListener = (OnFrgDataListener)activity;
        }
        else{
            throw new IllegalArgumentException("activity must implements OnFrgDataListener");
        }

    }
    @Override
    public void onDetach() {
        super.onDetach();

        IListener = null;
    }

这里讲解下一些重要的方法的含义:
主要的设置放在 initData() 函数里面,包括对控件的一些设置

public void initData(){
        // 显示兴起补全的整个礼拜的上个月或者下个月的日期 一般会多出一行整个礼拜
        // 点击补全出来的另外一个月的信息 可以直接跳到那个月
        mcv.setShowOtherDates(MaterialCalendarView.SHOW_ALL);

        // 设置日历默认的时间为当前的时间
        mcv.setSelectedDate(new Date());

        // 日历的主要设置
        mcv.state().edit()
                // 设置你的日历 第一天是周一还是周一
                .setFirstDayOfWeek(Calendar.MONDAY)
                // 设置你的日历的最小的月份  月份为你设置的最小月份的下个月 比如 你设置最小为1月 其实你只能滑到2月
                .setMinimumDate(CalendarDay.from(2015, 1, 1))
                // 同最小 设置最大
                .setMaximumDate(CalendarDay.from(2018, 1, 1))
                // 设置你的日历的模式  是按月 还是按周
                .setCalendarDisplayMode(CalendarMode.MONTHS)
                .commit();

// 设置你选中日期的背景底色
 //       mcv.setSelectionColor(getResources().getColor(R.color.date_choose));
        mcv.setSelectionColor(0xff4285f4);

//
        mcv.setOnDateChangedListener(this);

    }

fragment实现OnDateSelectedListener接口,实现里面的方法,每次选择日期后都会调用方法onDateSelected方法

 /**
     * 日期选择 回调函数
     * @param widget
     * @param date
     * @param selected
     */
    @Override
    public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) {
        Toast.makeText(getActivity(),getSelectedDatesString(),Toast.LENGTH_SHORT).show();
 //       Toast.makeText(getActivity(),"从Activity传递的数据:"+(String)timeBundle.get("date"),Toast.LENGTH_SHORT).show();
        IListener.progress(mcv.getSelectedDate().getDate());

        //选择后,延迟消失
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mContext.dismiss();
            }
        }, 1000);
    }

这里面选择以后我让它延时一秒后调用dismiss()方法,自动关闭,
在fragment里面我定义了一个内部接口,用来向调用它的activity回传选择的日期

/**
     * 定义接口,向Activity传递数据
     */
    public interface OnFrgDataListener{
        public void progress(Date date);
    }

然后把注入实例的方法放到它的生命周期的函数里面,以及释放实例

 /**
     * 注入实例方法
     * @param
     */
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        if(activity instanceof OnFrgDataListener)
        {
            IListener = (OnFrgDataListener)activity;
        }
        else{
            throw new IllegalArgumentException("activity must implements OnFrgDataListener");
        }

    }
    /**
     * 释放实例
    */
    @Override
    public void onDetach() {
        super.onDetach();
        IListener = null;
    }

这样在activity中调用它的时候会自动注入实例,

由于在很多地方需要让它左右两边全充满屏幕,这里我在onStart()方法里面定义一些它的属性

 @Override
    public void onStart() {
        super.onStart();

        //下面这些都是为了让dialog宽度全充满
        Window win = getDialog().getWindow();
        // 一定要设置Background,如果不设置,window属性设置无效
        win.setBackgroundDrawable( new ColorDrawable(getResources().getColor(R.color.white)));

        DisplayMetrics dm = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics( dm );
        WindowManager.LayoutParams params = win.getAttributes();
       // params.gravity = Gravity.BOTTOM;
        // 使用ViewGroup.LayoutParams,以便Dialog 宽度充满整个屏幕

        params.width =  ViewGroup.LayoutParams.MATCH_PARENT;
        params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
        win.setAttributes(params);

        /*if (dialog != null) {
            DisplayMetrics dm = new DisplayMetrics();
            getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm);
            dialog.getWindow().setLayout((int) (dm.widthPixels * 1), ViewGroup.LayoutParams.WRAP_CONTENT);
        }*/
    }

有的地方需要弹出的dialog背景全透明,有的地方需要他的背景半透明,这里可以通过设置它的style来实现

@Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //这个主题 背景全透明 没有半透明
       // setStyle(DialogFragment.STYLE_NO_FRAME, android.R.style.Theme_Holo_Light);
    }

基本的设置就是这些了,注意接口回传的数据是一个Date类型的值,你需要自己设置格式转换来转换他们

//"yyyy-MM-dd"  "yyyy年MM月dd日"根据你的需要设置
private SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");

然后调用这个sdf就可以转换了

String str=sdf.format(date);

得到的string就是你要的内容了

MaterialCalendarView的配置都写好了,下面就是如何来调用他了

1,首先 定义这个fragment的实例

//弹出的时间弹窗
    CalendarViewFragment calendarViewFragment;
    //向dialog传递数据
    Bundle timeBundle=new Bundle();

2,在OnCreate()方法中实例化

calendarViewFragment=new CalendarViewFragment();

3,让这个activity实现你之前在fragment里面定义的接口

public class AddActivityActivity extends AppCompatActivity implements CalendarViewFragment.OnFrgDataListener

4,然后实现它的方法

private SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");

 @Override
    public void progress(Date date) {
        //每次选择日期后,都会调用这个方法
        if(date!=null){
            String str=sdf.format(date);
        }
    }

这样你选择的日期就会通过这个接口传递到你的activity中

5,在你的点击事件里面加入

calendarViewFragment.show(getSupportFragmentManager(),"timeChoose");

这行代码的意思就是显示这个dialog的fragment,第二个参数是啥意思我也没搞懂.

使用起来还是很简单的.

其他参考博客:http://blog.csdn.net/u014733374/article/details/46969507

控件的一些其他的属性,有需要可以看下

在源码里面有一个dynamic setters test模块,对它进行一下说明(献给英语不好的各位):
1.other dates其它的日期
other months 月(显示前一个后一个月的日期)
out of range超出范围
decorated disabled 装饰禁用
select days outside month选择天超出月范围的(多出的日期可选择)
2.month mode 月模式显示
3.week mode 周模式显示
4.selection mode 选择模式
no selsction 不可以选择
single date 选择一个
multiple dates 多个日期
5.toggle topbar 切换topbar(不显示年月)
6.previous以前的一个月
7.next 下一个月
8.set min date 设置最小日期之前不可选
9.set max date 设置最大日期之后不可选
10.set selected date设置默认选的一个日期
11.random colors随机颜色(选中的颜色)
12.set width and height 设置每个数据的宽高
13.clear selection 清空选择
14.paging enabled分页功能(否则只能选中一个月的日期)
顺便说一下布局属性:
app:mcv_allowClickDaysOutsideCurrentMonth=“true"允许按当前月份的天数
app:mcv_showOtherDates=“all” 本月外其它的日期可以被选中
app:mcv_arrowColor=”" 箭头颜色
app:mcv_calendarMode="" 日历模式
app:mcv_dateTextAppearance="" 日期文本外观
app:mcv_firstDayOfWeek="" 星期一
app:mcv_headerTextAppearance="" 标题文本外观
app:mcv_leftArrowMask="" 左箭头面具
app:mcv_monthLabels="" 月标签
app:mcv_rightArrowMask="" 右箭头面具
app:mcv_selectionColor="" 选择颜色
app:mcv_weekDayLabels="" 周标签
app:mcv_weekDayTextAppearance="" 周日期的文本外观
对日历控件的说明就这些了。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值