Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using multiple DotSpan's in MaterialCalendarView

Is there any way of attaching more than 1 DotSpan's to a date with Android MaterialCalendarView? Altough I have 2 DotSpan's added to my CalendarView it's still displaying only 1 DotSpan... I'm using the following code:

@Override
public boolean shouldDecorate(CalendarDay day) {
    day.copyTo(calendar);
    for (int i = 0; i < weekDayStrTmp.size(); i++) {
        if (weekDayStrTmp.contains(day)) {
            return true;
        } else {
            return false;
        }
    }
    return false;
}

@Override
public void decorate(DayViewFacade view) {
    view.addSpan(new DotSpan(8, myContext.getResources().getColor(R.color.myColor3)));
    view.addSpan(new DotSpan(8, myContext.getResources().getColor(R.color.myColor3)));
}
like image 760
user754730 Avatar asked Oct 26 '15 21:10

user754730


People also ask

What is material-calendar-view?

Material-Calendar-View is a simple and customizable calendar widget for Android based on Material Design. The widget has two funcionalities: a date picker to select dates (available as an XML widget and a dialog) and a classic calendar. The date picker can work either as a single day picker, many days picker or range picker.

How do I display a dot in a material calendarview?

This is not a feature from the Material CalendarView but you can do without it. Just set an OnDateChangedListener. When a new date is selected, populate a list with your events. Use the decorator to display the dot, and that should be it.

How to integrate material calendarview with jcenter?

The first thing we have to do is import the Material CalendarView library. To do it, open the project’s build.gradle file and make sure you have defined the jcenter repository like below: If yes, open the module’s build.gradle file and simply add the following line to the dependency part:

How to pass more than one calendar object to method above?

Don't pass more than one calendar object to method above if your calendar type is CalendarView.ONE_DAY_PICKER. If your calendar type is CalendarView.RANGE_PICKER you have to pass full dates range. To get it you can use our utils method CalendarUtils.getDatesRange (Calendar firstDay, Calendar lastDay).


2 Answers

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);
like image 182
Juvi Avatar answered Oct 14 '22 09:10

Juvi


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.

like image 37
Иво Недев Avatar answered Oct 14 '22 07:10

Иво Недев