在 Android 多产材料日历视图中的日期下方添加多个点指示器

Sha*_* GN 5 android android-layout android-fragments

我已经在我的 Android 应用程序中使用 Android 多产材料 CalendarView 外部库实现了 CalendarView。现在,我必须在某些日期下方添加多个点指示器,以指示每个日期中的事件数量。我尝试过,但只在日期下方得到一个点。请帮忙

这是我的日历片段和装饰器类:

public class CalendarFragment extends Fragment {
    private View v;
    private List<Schedule> schedules = new ArrayList<Schedule>( );
    private MaterialCalendarView calendarView;

    public CalendarFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        try {
        v = inflater.inflate(R.layout.fragment_calendar, container, false);
        initViews();
        schedules = ScheduleDAO.getInstance().getScheduleListWithId();
            highlightDates(schedules);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return v;
    }

    private void highlightDates(List<Schedule>scheduleList) throws ParseException {
        for (int position = 0;position<scheduleList.size();position++)
        {
            Schedule schedule = scheduleList.get(position);
            if (schedule.getSessionStatus().equals("Incomplete")){
                int color = R.color.colorPrimaryDark;
                CurrentDayDecorator decorator = new CurrentDayDecorator(new Date(schedule.getScheduledDate()),color);
                calendarView.addDecorator(decorator);

            }else {
                int color = R.color.lightgray;
                CurrentDayDecorator decorator = new CurrentDayDecorator(new Date(schedule.getScheduledDate()),color);
                calendarView.addDecorator(decorator);
            }
        }
    }

    private void initViews() {
        calendarView = v.findViewById(R.id.calendarView);
    }
}

Decorator class
public class CurrentDayDecorator implements DayViewDecorator {
    private final int color;
    private final CalendarDay day;

    public CurrentDayDecorator(Date date,int color) {
        this.color = color;
        this.day = CalendarDay.from(date);
    }
    @Override
    public boolean shouldDecorate(CalendarDay day) {
        if (this.day.equals(day)){
            return true;
        }
        return false;
    }

    @Override
    public void decorate(DayViewFacade view) {
        view.addSpan(new DotSpan(3,color));
    }
}
Run Code Online (Sandbox Code Playgroud)

led*_*r96 2

我遇到了类似的问题,发现这篇文章非常有帮助。

MaterialViewCalendar API 不支持您想要执行的操作,因此您需要添加一些额外的帮助程序类。请注意,一个装饰器映射到一个点。因此,如果您想要给定日期下有两个点,那么该日期必须绑定到两个装饰器等。

解决该问题的一种方法是执行以下操作:

decorate将类中的 -method更改CurrentDayDecorator为以下内容:

@Override
    public void decorate(DayViewFacade view) {
        LineBackgroundSpan span = new CustomSpan(color, xOffsets[spanType]);
        view.addSpan(span);
    }
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,我们需要向您的类添加一个新类 ( CustomSpan) 和两个字段 (xOffsetsspanType) CurrentDayDecorator。LineBackgroundSpan 是包中包含的接口。

private static class CustomSpan extends DotSpan{
    private int color;
    private int xOffset;
    private float radius = 3;
    CustomSpan(int color, int xOffset){
        this.color = color;
        this.xOffset = xOffset;
    }

        /*Note! The following code is more or less copy-pasted from the DotSpan class. I have commented the changes below.*/
    @Override
    public void drawBackground(Canvas canvas, Paint paint, int left, int right, int top, int baseline,
                               int bottom, CharSequence text, int start, int end, int lnum) {
        int oldColor = paint.getColor();
        if (color != 0) {
            paint.setColor(color);
        }
        int x = ((left + right) / 2); /*This is the x-coordinate right 
    below the date. If we add to x, we will draw the 
    circle to the right of the date and vice versa if we subtract from x.*/
        canvas.drawCircle(x + xOffset, bottom + radius, radius, paint);
        paint.setColor(oldColor);
    }
}
Run Code Online (Sandbox Code Playgroud)

所以剩下的就是向我们的 CustomSpan 提供一个偏移量。在我自己的装饰器方法中,我有一系列偏移量可供选择。我选择哪一个取决于我要创建哪个点。在我的应用程序中,我最多可以在日期下方放置 4 个点。CurrentDayDecorator在绘制之前,我需要告诉我它“代表”4 个点中的哪一个。

这就是我的类的样子(对于您来说,只需将“EventDecorator”更改为“CurrentDayDecorator”)

 private static class EventDecorator implements DayViewDecorator {

    private static final float DEFAULT_DOT_RADIUS = 4;
    //Note that negative values indicate a relative offset to the LEFT
    private static final int[] xOffsets = new int[]{0,-10,10,-20};
    private int color;
    private HashSet<CalendarDay> dates;
    private float dotRadius;
    private int spanType;

    private EventDecorator(int color, float dotRadius, int spanType) {
        this.color = color;
        this.dotRadius = dotRadius;
        this.dates = new HashSet<>();
        this.spanType = spanType;
    }
    /*Note! I added this method so that I can add dates after object creation!*/
    public boolean addDate(CalendarDay day){
        return dates.add(day);
    }

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

    @Override
    public void decorate(DayViewFacade view) {
        LineBackgroundSpan span = new CustomSpan(color, xOffsets[spanType],DEFAULT_DOT_RADIUS);
        view.addSpan(span);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在棘手的部分变成知道何时创建具有正确对应的 DayViewDecorator spanType。如果一天应该有两个点,那么它就需要两个DayViewDecorators(具有不同的值spanType)。我所做的是用“事件”来跟踪所有日子,并将每个“多事的日子”与一个计数器相关联。换句话说,aHashMap将 a 映射CalendarDay到 an Integer。然后,您遍历地图中的每个条目,并将给定的日期添加到 X 数量的装饰器中,其中 X 是事件的总数。在代码中它看起来像这样:

EventDecorator[] decoratorArray = new EventDecorator[4]; //Max 4 dots
for(int i = 0; i<decoratorArray.length; i++)
        decoratorArray[i] = new EventDecorator(myColor,myRadius,i);

/*dayInstanceMap contains all the mappings.*/
for(Map.Entry<CalendarDay,Integer> entry : dayInstanceMap.entrySet()){
      CalendarDay currDay = entry.getKey();
      Integer currDayCount = entry.getValue(); //If you have max amount of dots, check here if currDay is too large.
      for(int i = 0; i<currDayCount; i++)
          decoratorArray[i].addDate(currDay);
}
Run Code Online (Sandbox Code Playgroud)

之后,只需将装饰器添加到 MaterialCalendarView 中即可。