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

时间:2017-11-16 10:46:57

标签: 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));
    }
}

2 个答案:

答案 0 :(得分:1)

我遇到了类似的问题,发现this post非常有帮助。

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

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

decorate课程中的CurrentDayDecorator - 方法更改为以下内容:

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

如您所见,我们需要向您的CustomSpan课程添加新课程(xOffsets)和两个字段(spanTypeCurrentDayDecorator)。 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);
    }
}

所以剩下的就是给我们的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);
    }
}

现在,棘手的部分知道何时使用正确的相应spanType创建DayViewDecorator。如果一天应该有两个点,则需要两个DayViewDecoratorsspanType的值不同)。我所做的是我用“事件”跟踪所有日子,并用计数器将每个“多事之日”联系起来。换句话说,HashMapCalendarDay映射到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);
}

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

答案 1 :(得分:0)

  1. 创建一个自定义LineBackgroundSpan,从左到右绘制点
class MultiDotSpan(
    private val radius: Float = 3f,
    private val colors: List<Int>
) : LineBackgroundSpan {

    override fun drawBackground(
        canvas: Canvas, paint: Paint,
        left: Int, right: Int, top: Int, baseline: Int, bottom: Int,
        charSequence: CharSequence,
        start: Int, end: Int, lineNum: Int
    ) {

        var position = (left + right) / 2 - (colors.size - 1) * radius

        if (colors.size > 1) {
            position - 2
        }

        colors.forEach { color ->
            val oldColor = paint.color
            if (color != 0) {
                paint.color = color
            }
            canvas.drawCircle(position, bottom + radius, radius, paint)
            paint.color = oldColor

            position += radius * 2 + 2
        }
    }
}
  1. 将其添加到装饰器中
class EventDecorator(
    private val colors: List<Int>,
    private var dates: List<CalendarDay> = emptyList()
) : DayViewDecorator {

    override fun shouldDecorate(day: CalendarDay) = dates.contains(day)

    override fun decorate(view: DayViewFacade) = with(view) {
        addSpan(MultiDotSpan(8f, colors))
    }
}
  1. 将装饰器添加到您的日历视图中
val eventDecorator = MCVEventDecorator(colors, events)
calendarView.addDecorator(eventDecorator)

注意:您将需要对不同数量的点(例如,单,双,三等)使用不同的装饰器