Using multiple DotSpan's in MaterialCalendarView

心不动则不痛 提交于 2019-12-03 00:36:17

You are overriding the first DotSpan with the second. The given DotSpan class, lets you create a centered colored dot below the text, so if you put one on top of the other, the first won't be visible.

I've managed to create few DotSpans at the same DayViewFacade view, I'm not sure if that's the exact solution you searched for but I'm sure it'll be helpful:

So you have to create a custom Decorator class that implements DayViewDecorator, let's call it OrangeDecorator.

You'll have to create another custom class that implements LineBackgroundSpan, and we'll call it MyCustomOrangeSpan.

Both classes are almost the same as the original DotSpan and EventDecorator taken from the original library, but you can customize the classes for your needs.

At the "decorate" function (OrangeDecorator class) use your custom LineBackgroundSpan like so:

@Override
public void decorate(DayViewFacade view) {
    view.addSpan(new MyCustomOrangeSpan(6, ContextCompat.getColor(mContext, R.color.AppOrange)));
}

At the "drawBackground" function (MyCustomOrangeSpan class) you'll be able to position the circle inside the canvas, so let's do it:

@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);
        }

        canvas.drawCircle((left + right) / 2 - 20, bottom + radius, radius, paint);
        paint.setColor(oldColor);

    }

This way, we can create multiple DayViewDecorators and LineBackgroundSpan (for different positioning):

BlueDecorator blueDecorator = new BlueDecorator(getActivity(),eventsDays,eventsMap);
OrangeDecorator orangeDecorator = new OrangeDecorator(getActivity(),eventsDays,eventsMap);
GreenDecorator greenDecorator = new GreenDecorator(getActivity(),eventsDays,eventsMap);
materialCalendarView.addDecorator(blueDecorator);
materialCalendarView.addDecorator(orangeDecorator);
materialCalendarView.addDecorator(greenDecorator);

I had to figure a way to add multiple dots, the selected answer definitely helped me figure things out:

First off, you need a custom DotSpan class, which is just ever so slightly altered:

public class CustmMultipleDotSpan implements LineBackgroundSpan {


    private final float radius;
    private int[] color = new int[0];


    public CustmMultipleDotSpan() {
        this.radius = DEFAULT_RADIUS;
        this.color[0] = 0;
    }


    public CustmMultipleDotSpan(int color) {
        this.radius = DEFAULT_RADIUS;
        this.color[0] = 0;
    }


    public CustmMultipleDotSpan(float radius) {
        this.radius = radius;
        this.color[0] = 0;
    }


    public CustmMultipleDotSpan(float radius, int[] color) {
        this.radius = radius;
        this.color = color;
    }

    @Override
    public void drawBackground(
            Canvas canvas, Paint paint,
            int left, int right, int top, int baseline, int bottom,
            CharSequence charSequence,
            int start, int end, int lineNum
    ) {

        int total = color.length > 5 ? 5 : color.length;
        int leftMost = (total - 1) * -10;

        for (int i = 0; i < total; i++) {
            int oldColor = paint.getColor();
            if (color[i] != 0) {
                paint.setColor(color[i]);
            }
            canvas.drawCircle((left + right) / 2 - leftMost, bottom + radius, radius, paint);
            paint.setColor(oldColor);
            leftMost = leftMost + 20;
        }
    }
}

You will also need an ever so slightly altered EventDecorator:

public class EventDecorator implements DayViewDecorator {

    private final int[] colors;
    private final HashSet<CalendarDay> dates;


    public EventDecorator(Collection<CalendarDay> dates, int[] colors) {
        //this.color = color;
        this.dates = new HashSet<>(dates);

        this.colors = colors;

    }


    public EventDecorator(List<MainActivity.Filter> filteredEvents) {
        //this.color = color;

        this.dates = new HashSet<>(filteredEvents.get(0).calDayArr);
        int[] colors = new int[1];
        colors[0] = filteredEvents.get(0).color;
        this.colors = colors;

    }

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

    @Override
    public void decorate(DayViewFacade view) {

        view.addSpan((new CustmMultipleDotSpan(5,colors)));

    }


}

And that is basically it.

Now find your calendarview in your activity, and give it some dates, and colors to show on those dates. In my particular case, I sort my dates in 5 different lists based on the amount of events per day, so you will end up with something like

calendarView.addDecorator(new EventDecorator(threeEventDays,threeColors));

Where threeEventDays is a Collection of CalendarDay and threeColors is an int array

int[] threeColors = {
Color.rgb(0, 0, 255),
Color.rgb(0, 255, 0),
Color.rgb(255, 0, 0)};

It's nowhere near as ideal as it should be, but what it does is it expects an array of colors. Calculates the leftmost position, based on the array size, so for a size one, the left most position is the middle dot we all know and love. For size 2 the left most position is -10, for size 3 it's -20 and so on. Then loops through and paints the dots.

It's limited to 5 event dots as it gets quite ugly above that, and though currently not on my roadmap, if it turns out to be a requirement I might add support for a second line of dots.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!