Android-日历

本篇源自于GitHub开源框架的修改:
github : MagicMashRoom/SuperCalendar

修改后我的版本:GitHub : MyCalenderTest

效果图:

Android-日历_第1张图片

一、左右滑动的问题

功能需求:

只需要展示本月后十二个月的日历,比如2017年9月-2018年9月。
首先进入页面就显示本月的日历2017年9月,此月不可以右滑。
如果滑动12个月后显示2018年9月,此月不可以左滑。
2017年9月-2018年9月之间的月份则可以左右滑动。

问题:

源码中左右滑动为viewpager,item数:2147483647,首次进入页面当前页为1000,意味着可以无限左右滑动,

解决:

1、首先需要设置viewpager的滑动拦截事件,重写ViewPager的dispatchTouchEvent

public class MyMonthPager extends MonthPager {
    private int beforeX;
    private boolean isCanScroll = true;

    private int orientation = 0;//默认左右都可以滑动
    // 0,左右可滑,
    // -1,禁止左滑,
    // 1,禁止右滑

    public MyMonthPager(Context context) {
        super(context);
    }

    public MyMonthPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (isCanScroll) {
            return super.dispatchTouchEvent(ev);
        } else {

            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    beforeX = (int) ev.getX();
                    break;
                case MotionEvent.ACTION_MOVE:
                    int currentX = ((int) ev.getX());
                    int moveValue = currentX - beforeX;// >0右滑,<0左滑
                    Log.e("666", "moveValue===" + moveValue);

                    //向右滑或者向左滑的判断
                    if ((moveValue > 0 && orientation == 1) || (moveValue < 0 && orientation == (-1))) {
                        return false;//不可滑动
                    }
                    break;
            }
            return super.dispatchTouchEvent(ev);
        }
    }

    public int getOrientation() {
        return orientation;
    }

    public void setScrollble(int orientation, boolean isCanScroll) {
        this.isCanScroll = isCanScroll;
        this.orientation = orientation;
    }
}

2、oncreate中设置默认:

monthPager.setScrollble(1, false);//设置默认,不可右滑

3、viewpager的onPageSelected的监听中设置:

 //本年本月
CalendarDate today = new CalendarDate();
if (date.getYear() == today.getYear() && date.getMonth() == today.getMonth()) {//本月:如2017年9月
      monthPager.setScrollble(1, false);//不可右滑
      Log.e("666", "=== 本月===");
      isCurrentMonth = true;
      isNextYearCurrentMonth = false;
      //下年的本月
} else if (date.getYear() == today.getYear() + 1 && date.getMonth() == today.getMonth()) {//下年的本月:如2018年9月
     monthPager.setScrollble(-1, false);//不可左滑
     Log.e("666", "=== 下年本月===");
     isCurrentMonth = false;
     isNextYearCurrentMonth = true;
     //其他月
} else {
     monthPager.setScrollble(0, true);//可左右滑动
     Log.e("666", "=== 其他月 ===");
     isCurrentMonth = false;
     isNextYearCurrentMonth = false;
}

二、背景显示问题

功能需求:

点击今日不显示顶部今日的背景框,点击其他则显示今日的背景框

效果如图:
点击今日,不显示顶部今日的背景框:

Android-日历_第2张图片

点击不是今日,显示今日的背景框:

Android-日历_第3张图片

解决:

1、oncreate中设置默认:

backToday.setBackgroundResource(0);//"字体今天"背景设置1

2、点击顶部今天的监听设置:

 //回到今天
        backToday.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                CalendarDate today = new CalendarDate();
                calendarAdapter.notifyDataChanged(today);
                textViewYearDisplay.setText(today.getYear() + "年");
                textViewMonthDisplay.setText(today.getMonth() + "月");
                backToday.setBackgroundResource(0);//"字体今天"背景设置2
                monthPager.setScrollble(1, false);
            }
        });

3、点击日期的监听中设置:

         @Override
            public void onSelectDate(CalendarDate date) {

                //"字体今天"背景设置3
                CalendarDate today = new CalendarDate();
                if (date.getYear() == today.getYear() && date.getMonth() == today.getMonth() && date.getDay() == today.getDay()) {//今日不需要背景
                    backToday.setBackgroundResource(0);
                } else {//非今日都需要背景
                    backToday.setBackgroundResource(R.drawable.button_bg);
                }


                currentDate = date;
                textViewYearDisplay.setText(date.getYear() + "年");
                textViewMonthDisplay.setText(date.getMonth() + "月");
            }

三、点击跳转问题

功能需求:

点击本月(如:2017年9月)显示的上月日期不可跳转,点击下年本月(如:2018年9月)的下月日期不可跳转

解决:

1、定义变量:
判断是否是本月(如:2017年9月,默认为true)、
判断是否是下年本月(如:2018年9月,默认为false)

并且点击回到当前月时设置 isCurrentMonth = true ; isNextYearCurrentMonth = false;//非当前月


    private boolean isCurrentMonth = true;
    private boolean isNextYearCurrentMonth = false;


   //回到今天
        backToday.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                CalendarDate today = new CalendarDate();
                calendarAdapter.notifyDataChanged(today);
                textViewYearDisplay.setText(today.getYear() + "年");
                textViewMonthDisplay.setText(today.getMonth() + "月");
                backToday.setBackgroundResource(0);//"字体今天"背景设置2
                monthPager.setScrollble(1, false);

                isCurrentMonth = true;//当前月
                isNextYearCurrentMonth = false;//非当前月
            }
        });

2、viewpager的onPageSelected监听中设置:

 @Override
            public void onPageSelected(int position) {
                mCurrentPage = position;
                currentCalendars = calendarAdapter.getPagers();
                if (currentCalendars.get(position % currentCalendars.size()) instanceof Calendar) {
                    CalendarDate date = currentCalendars.get(position % currentCalendars.size()).getSeedDate();
                    currentDate = date;
                    textViewYearDisplay.setText(date.getYear() + "年");
                    textViewMonthDisplay.setText(date.getMonth() + "月");


                    //本年本月
                    CalendarDate today = new CalendarDate();
                    if (date.getYear() == today.getYear() && date.getMonth() == today.getMonth()) {
                        monthPager.setScrollble(1, false);
                        Log.e("666", "=== 本月===");
                        isCurrentMonth = true;//是本月
                        isNextYearCurrentMonth = false;//不是下年本月
                        //下年的本月
                    } else if (date.getYear() == today.getYear() + 1 && date.getMonth() == today.getMonth()) {
                        monthPager.setScrollble(-1, false);
                        Log.e("666", "=== 下年本月===");
                        isCurrentMonth = false;//不是本月
                        isNextYearCurrentMonth = true;//是下年本月
                        //其他月
                    } else {
                        monthPager.setScrollble(0, true);
                        Log.e("666", "=== 其他月 ===");
                        isCurrentMonth = false;//不是本月
                        isNextYearCurrentMonth = false;//不是下年本月
                    }

                }
            }

3、在点击跳转月份的onSelectOtherMonth方法中,设置:

  @Override
            public void onSelectOtherMonth(int offset) {
                Log.e("666", "=== offset ===" + offset);
                //偏移量 -1表示刷新成上一个月数据 , 1表示刷新成下一个月数据
                if (!isCurrentMonth && !isNextYearCurrentMonth) {//不是本月也不是下年本月可左右跳转
                    monthPager.selectOtherMonth(offset);
                    Toast.makeText(MainActivity.this, "哈哈,我是本月和下年本月之间的月份", Toast.LENGTH_SHORT).show();
                } else if (isCurrentMonth && offset == 1) {//本月可跳转下个月
                    monthPager.selectOtherMonth(1);
                    Toast.makeText(MainActivity.this, "呵呵,我是本月", Toast.LENGTH_SHORT).show();
                } else if (isNextYearCurrentMonth && offset == (-1)) {//下年本月可调转上个月
                    monthPager.selectOtherMonth(-1);
                    Toast.makeText(MainActivity.this, "嘻嘻,我是下年本月", Toast.LENGTH_SHORT).show();
                }
            }

四、日历字体颜色设置:

需求:

显示的本月今日的日期一直显示白色
显示的本月非今日的日期一直显示黑色
显示的非本月日期一直显示灰色

解决:

CustomDayView类中

    private void renderSelect(State state) {
        //字体背景设置
        if (state == State.SELECT) {//本月选中
            selectedBackground.setVisibility(VISIBLE);
//            dateTv.setTextColor(Color.WHITE);
        } else if (state == State.NEXT_MONTH || state == State.PAST_MONTH) {//非本月日期
            selectedBackground.setVisibility(GONE);
//            dateTv.setTextColor(Color.parseColor("#d5d5d5"));
        } else {//本月未选中
            selectedBackground.setVisibility(GONE);
//            dateTv.setTextColor(Color.parseColor("#111111"));
        }

        //字体颜色设置
        if (state == State.NEXT_MONTH || state == State.PAST_MONTH) {//非本月日期
            dateTv.setTextColor(Color.parseColor("#d5d5d5"));//灰色
        } else {//本月日期
            if (today.getYear() == day.getDate().getYear() &&
                    today.getMonth() == day.getDate().getMonth() &&
                    today.getDay() == day.getDate().getDay()) {
                dateTv.setTextColor(Color.WHITE);//白色
            } else {
                dateTv.setTextColor(Color.parseColor("#111111"));//黑色
            }
        }
    }

四、设置标记

MainActivity中:

  /**
     * 初始化标记数据,HashMap的形式,可自定义
     *
     * @return void
     */
    private void initMarkData() {
        HashMap markData = new HashMap<>();
        markData.put("2017-9-1", "1");//参数为:日期,显示样式
        markData.put("2017-9-2", "0");
        markData.put("2017-9-3", "1");
        markData.put("2017-9-4", "0");
        calendarAdapter.setMarkData(markData);
    }

custom_day.xml中可设置marker的位置、大小等


<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="51.4dp"
    android:layout_height="45dp"
    android:orientation="vertical">

    <View
        android:id="@+id/today_background"
        android:layout_width="33dp"
        android:layout_height="33dp"
        android:layout_centerInParent="true"
        android:background="@drawable/today_background"
        android:visibility="gone" />

    <View
        android:id="@+id/selected_background"
        android:layout_width="33dp"
        android:layout_height="33dp"
        android:layout_centerInParent="true"
        android:background="@drawable/selected_background"
        android:visibility="gone" />

    <TextView
        android:id="@+id/date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:text="19" />

    <ImageView
        android:id="@+id/maker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="8dp"
        android:background="@drawable/view_syllabus_mark_background"
        android:visibility="visible" />
RelativeLayout>

五、其他:

CalendarDate today = new CalendarDate();//可获取今日日期

遇到问题一:

Error:Execution failed for task ':app:processDebugManifest'.
> Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 17 declared in library [com.github.MagicMashRoom:SuperCalendar:v1.4] C:\Users\lenovo\.android\build-cache\33a3dfeb0aa43d28d9f45fd4dd6f6c01a5a8d3a5\output\AndroidManifest.xml
    Suggestion: use tools:overrideLibrary="com.ldf.mi.calendar" to force usage

原因:我项目中的minSdkVersion 15,但是导入依赖需要大于17,

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"
    defaultConfig {
        applicationId "com.example.lenovo.mycalendertest"
        minSdkVersion 15
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }

解决:manifest中添加下面即可:

    <uses-sdk tools:overrideLibrary="com.ldf.mi.calendar"/>

参考:【Android】Suggestion: use tools:overrideLibrary=”” to force usage

你可能感兴趣的:(项目常见,框架使用)