Material CalendarView如何设置日期的背景颜色?

11

我的目标是找到一个 Android 库,可以根据数组在日历视图上标记各种日期。这些日期可能是连续的,也可能不是。我理想的情况是更改每个日期的背景颜色。重要的复杂性在于,由于颜色来自服务器查询,所以我不知道这个颜色,直到运行时。

我已经研究了整整一天,我最好的希望似乎是 material-calendarviewgithub)。然而,我发现他们的代码有点难以理解,这是我的问题,但我完全陷入了困境。

我已经像这样在我的 XML 布局中添加了一个日历:

<com.prolificinteractive.materialcalendarview.MaterialCalendarView
        android:id="@+id/calendar_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginLeft="20dp"
        android:layout_marginRight="20dp"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        app:mcv_showOtherDates="all"
        app:mcv_selectionColor="#00F"/>

然后在我的活动中,我有这些实例变量:

private MaterialCalendarView calendarView;
private ArrayList<Date> markedDates;

并且这段代码在我的onCreateView()中。

calendarView = (MaterialCalendarView) view.findViewById(R.id.calendar_view);

好的,很简单。但是我无法弄清楚如何从我的日期数组中标记日历。我正在研究这种方法,但我不知道该如何在这里进一步处理:

private void initializeCalendar() {

        calendarView.setOnDateChangedListener(context);
        calendarView.setShowOtherDates(MaterialCalendarView.SHOW_ALL);

        Calendar calendar = Calendar.getInstance();
        calendarView.setSelectedDate(calendar.getTime());

        calendar.set(calendar.get(Calendar.YEAR), Calendar.JANUARY, 1);
        calendarView.setMinimumDate(calendar.getTime());

        calendar.set(calendar.get(Calendar.YEAR), Calendar.DECEMBER, 31);
        calendarView.setMaximumDate(calendar.getTime());

        int bgColor = sharedVisualElements.getPrimaryColor();

        calendarView.addDecorators(new EventDecorator(bgColor, ????));
}

最后一行指的是这个内部类:

private class EventDecorator implements DayViewDecorator {

        private final int color;
        private final HashSet<CalendarDay> dates;

        public EventDecorator(int color, Collection<CalendarDay> dates) {
            this.color = color;
            this.dates = new HashSet<>(dates);
        }

        @Override
        public boolean shouldDecorate(CalendarDay day) {
            return dates.contains(day);
        }

        @Override
        public void decorate(DayViewFacade view) {
            view.addSpan(new DotSpan(5, color));
        }
    }

我想将我的ArrayList<Date> markedDates转换为他们所称的Collection<CalendarDay> dates,你同意吗?但这就是我卡壳的地方。这个数据结构对我来说很奇怪。当我试图通过调用new CalendarDay()来实例化它时,我的类立即扩展了约10个新方法,我不理解它们的作用或如何使用它们。显然,我已经偏离轨道了。它肯定不可能这么棘手。

有人用过这个库来完成这个任务并知道如何实现吗?我完全停滞了。此外,如果有一个更简单的库可以让我在运行时使用仅已知颜色设置背景颜色,我听取意见。

感谢任何帮助。我担心我写得很混乱,这是因为我完全糊涂了。

3个回答

4
我解决了这个问题,所以我会发布解决方案,以防其他人有同样的问题。如果有更有效的方法,请作为一个解决方案发布。
我提到我有一个包含日期列表的数组。我需要做的是迭代该数组,将每个Date转换为设置为适当年份、月份和日期的Calendar对象,然后将该对象添加到另一个ArrayList,这次是一个ArrayList。例如:
List<CalendarDay> list = new ArrayList<CalendarDay>();
Calendar calendar = Calendar.getInstance();

for (Date date : markedDates) {
    // might be a more elegant way to do this part, but this is very explicit
    int year = date.getYear();
    int month = date.getMonthOfYear() - 1; // months are 0-based in Calendar
    int day = date.getDayOfMonth();

    calendar.set(year, month, day);
    CalendarDay calendarDay = CalendarDay.from(calendar);
    list.add(calendarDay);
}

所以现在我们有了CalendarDay对象的列表,但还没有完成。创建数据结构的最后一步是将其“转换”为我在OP中提到的那个结构 - Collection<CalendarDay>。一旦到达这里,这实际上非常简单。只需像这样分配即可:
calendarDays = list;

接下来,当你想要添加装饰器时,你已经准备好了。只需执行以下操作:

calendarView.addDecorators(new EventDecorator(myColor, calendarDays));

还有一件事需要提及,这也是我困惑的主要原因。我不知道如何实例化这个Collection<CalendarDay>对象。在构造函数之前的实例变量部分,我加入了几乎所有由Android Studio自动填充的代码:

private Collection<CalendarDay> calendarDays = new Collection<CalendarDay>() {
        @Override
        public boolean add(CalendarDay object) {
            return false;
        }

        @Override
        public boolean addAll(Collection<? extends CalendarDay> collection) {
            return false;
        }

        @Override
        public void clear() {

        }

        @Override
        public boolean contains(Object object) {
            return false;
        }

        @Override
        public boolean containsAll(Collection<?> collection) {
            return false;
        }

        @Override
        public boolean isEmpty() {
            return false;
        }

        @NonNull
        @Override
        public Iterator<CalendarDay> iterator() {
            return null;
        }

        @Override
        public boolean remove(Object object) {
            return false;
        }

        @Override
        public boolean removeAll(Collection<?> collection) {
            return false;
        }

        @Override
        public boolean retainAll(Collection<?> collection) {
            return false;
        }

        @Override
        public int size() {
            return 0;
        }

        @NonNull
        @Override
        public Object[] toArray() {
            return new Object[0];
        }

        @NonNull
        @Override
        public <T> T[] toArray(T[] array) {
            return null;
        }
    };

我希望这能帮助到某些人。如果有更好的解决方案,请发帖,我会删除我的。


兄弟,当我这样做时,getYear()已经被弃用了,我该怎么替换它? - Anil Shrestha

4
如果您想通过编程方式更改所选项目的背景颜色,请使用以下方法:
MaterialCalendarView materialCalendar = (MaterialCalendarView)findViewById(R.id.materialCalenderView);
materialCalendar.setSelectionColor(Color.parseColor("#00BCD4"));

使用此代码会使所有选择器具有相同的颜色,因此如果您想根据条件拥有不同颜色的选择器,请使用decorator()。

2
为什么你使用了ArrayList而不是HashSet? 不能实例化Collection的原因是它是一个接口,因此你必须创建匿名类并覆盖方法。 以下是我类似的做法: 这个方法接收两个日历对象,并将两个日历日期之间的所有日期添加到CalendarDays的HashSet中。
private HashSet<CalendarDay> getCalendarDaysSet(Calendar cal1, Calendar cal2) {
    HashSet<CalendarDay> setDays = new HashSet<>();
    while (cal1.getTime().before(cal2.getTime())) {
        CalendarDay calDay = CalendarDay.from(cal1);
        setDays.add(calDay);
        cal1.add(Calendar.DATE, 1);
    }

    return setDays;
}

在onCreateView(...)方法中,我已经动态设置了两个日历日期,并将其之间的差异存储在HashSet中。但是,您也可以通过HashSet传递自己的随机日期集。

Calendar cal1 = Calendar.getInstance();
    cal1.set(2016, 8, 1);
    Calendar cal2 = Calendar.getInstance();
    cal2.set(2016, 9, 1);

    HashSet<CalendarDay> setDays = getCalendarDaysSet(cal1, cal2);
    int myColor = R.color.red;
    mCalendarView.addDecorator(new BookingDecorator(myColor, setDays));

在我的情况中,BookingDecorator是实现DayViewDecorator接口的类。
 private class BookingDecorator implements DayViewDecorator {
    private int mColor;
    private HashSet<CalendarDay> mCalendarDayCollection;

    public BookingDecorator(int color, HashSet<CalendarDay> calendarDayCollection) {
        mColor = color;
        mCalendarDayCollection = calendarDayCollection;
    }

    @Override
    public boolean shouldDecorate(CalendarDay day) {
        return mCalendarDayCollection.contains(day);
    }

    @Override
    public void decorate(DayViewFacade view) {
        view.addSpan(new ForegroundColorSpan(mColor));
        //view.addSpan(new BackgroundColorSpan(Color.BLUE));
        view.setBackgroundDrawable(ContextCompat.getDrawable(getContext(),R.drawable.greenbox));

    }
}

您的帖子非常有帮助。希望我的帖子也能帮助到其他人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接