RadCalendar events, EventRenderer,(custom painting of events)

7 posts, 1 answers
  1. zabdiel
    zabdiel avatar
    1 posts
    Member since:
    Dec 2014

    Posted 14 Dec 2014 Link to this post

    Hello telerik. I just want to ask if there is any sample code that shows how to use a custom EventRenderer for painting of the events in a calendar cell? I have an attached file that represents a sample calendar cell, with small-rounded-colored shapes below that represents events. Below is my sample code so far. any help would be greatly appreciated. Thanks.



    private RadCalendarView radCalendar;

        @Override
        protected void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_rad_calendar_sample);

            radCalendar = (RadCalendarView) findViewById(R.id.calendarView);
           
            Calendar calendar = Calendar.getInstance();
            long eventStart = calendar.getTimeInMillis();
            calendar.add(Calendar.HOUR, 1);
            long eventEnd = calendar.getTimeInMillis();


            Event event1 = new Event("", eventStart, eventEnd);
            Event event2 = new Event("", eventStart, eventEnd);
            Event event3 = new Event("", eventStart, eventEnd);

            List<Event> events = new ArrayList<Event>();
            events.add(event1);
            events.add(event2);
            events.add(event3);


            radCalendar.getEventAdapter().setRenderer(new MyEventRenderer(this));
            radCalendar.getEventAdapter().setEvents(events);
            radCalendar.notifyDataChanged();
        }   

       private class MyEventRenderer extends EventRenderer {

            private int shapeRadius;
            private Paint paint;

            public MyEventRenderer(Context context) {
                super(context);

                paint = new Paint();
                paint.setAntiAlias(true);
            }

            @Override
            public void renderEvents(Canvas canvas, CalendarCell cell) {


                shapeRadius = cell.getWidth() > cell.getHeight() ? cell.getHeight() : cell.getWidth();
                shapeRadius *= 0.45;

                Rect borderRect = cell.calcBorderRect();
                int centerX = (borderRect.left + borderRect.right) / 2;
                int centerY = (borderRect.top + borderRect.bottom) / 2;

                paint.setColor(Color.RED);
                MyEventRenderer.this.drawCircle(canvas, centerX, centerY);
            }

            private void drawCircle(Canvas canvas, int x, int y) {
                canvas.drawCircle(x, y, (int) (this.shapeRadius * 0.9f), this.paint);
            }
        }








  2. Answer
    Todor
    Admin
    Todor avatar
    778 posts

    Posted 16 Dec 2014 Link to this post

    Hi Zabdiel,

    Thank you for your interest in RadCalendarView.

    Since your image seems to have four events in different colors, I updated your events' setup:

    Event event1 = new Event("", eventStart, eventEnd);
    event1.setEventColor(Color.parseColor("#C8E140"));
    Event event2 = new Event("", eventStart, eventEnd);
    event2.setEventColor(Color.parseColor("#227665"));
    Event event3 = new Event("", eventStart, eventEnd);
    event3.setEventColor(Color.parseColor("#414B95"));
    Event event4 = new Event("", eventStart, eventEnd);
    event4.setEventColor(Color.parseColor("#FF0000"));
     
    List<Event> events = new ArrayList<Event>();
    events.add(event1);
    events.add(event2);
    events.add(event3);
    events.add(event4);

    Then, in order to correctly render them, you need to do this in you EventRenderer implementation:

    public class MyEventRenderer extends EventRenderer {
        private Paint paint;
     
        public MyEventRenderer(Context context) {
            super(context);
     
            paint = new Paint();
            paint.setAntiAlias(true);
        }
     
        @Override
        public void renderEvents(Canvas canvas, CalendarCell cell) {
     
            int desiredOffset = 20;
            int shapeRadius = 10;
            int locationX = desiredOffset;
            int locationY = cell.getHeight() - desiredOffset;
            for(Event e : cell.getEvents()) {
                if(locationX >= cell.getWidth()) {
                    return;
                }
                this.paint.setColor(e.getEventColor());
                canvas.drawCircle(locationX, locationY, shapeRadius, this.paint);
                locationX += shapeRadius + desiredOffset;
            }
        }
    }

    In short, the renderEvents method is called for each cell that contains events and the information about them is contained within the cell itself, you simply need to iterate over each event and draw a proper representation on the presented canvas.

    I hope this information helps.

    Regards,
    Todor
    Telerik
     

    Check out the Telerik Platform - the only platform that combines a rich set of UI tools with powerful cloud services to develop web, hybrid and native mobile apps.

     
  3. DevCraft banner
  4. Kyle
    Kyle avatar
    30 posts
    Member since:
    Dec 2014

    Posted 15 Jul 2015 in reply to Todor Link to this post

    I've tried to follow this but I am running into issues.  I only ever have 1 event per day maximum, but I'm looking to be able to position the event color and text starting in the bottom corner of the cell.  I copied the above code pretty much exactly, but I'm only ever getting a colored circle drawn in the very first cell, as seen in the attached image.  It looks like they are all just drawing the circle over one another, or drawing it in the same place.

     

     

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Paint;
     
    import com.telerik.widget.calendar.CalendarDayCell;
    import com.telerik.widget.calendar.events.Event;
    import com.telerik.widget.calendar.events.EventRenderer;
     
    public class MyEventRenderer extends EventRenderer {
        private Paint paint;
     
        public MyEventRenderer(Context context) {
            super(context);
     
            paint = new Paint();
            paint.setAntiAlias(true);
        }
     
        @Override
        public void renderEvents(Canvas canvas, CalendarDayCell cell) {
     
            int desiredOffset = 20;
            int shapeRadius = 10;
            int locationX = desiredOffset;
            int locationY = cell.getHeight() - desiredOffset;
            for(Event e : cell.getEvents()) {
                if(locationX >= cell.getWidth()) {
                    return;
                }
                this.paint.setColor(e.getEventColor());
                canvas.drawCircle(locationX, locationY, shapeRadius, this.paint);
                locationX += shapeRadius + desiredOffset;
                String test = "test";
            }
     
        }
    }

     

    Here is where I have my events and set my adapter

    calendar = new RadCalendarView(myActivity);
     
            calendar.setHorizontalScroll(true);
            calendar.setSelectionMode(CalendarSelectionMode.Single);
            calendar.getAdapter().setTodayCellBorderColor(Color.WHITE);
            calendar.getAdapter().setTodayCellTypeFace(Typeface.DEFAULT);
            calendar.getAdapter().setTodayCellTextColor(Color.GRAY);
            calendar.getEventAdapter().setRenderer(new MyEventRenderer(myActivity));

     

    The images below are using the exact same data set.

     

    Thank you,

     

  5. Todor
    Admin
    Todor avatar
    778 posts

    Posted 17 Jul 2015 Link to this post

    Hi Kyle,

    Thank you for writing.

    This is an old thread and indeed since then there was a change in the way the calendar cells are rendered and this change reflects in the code from my previous post. What's changed is that now the canvas that you receive as a parameter is the whole calendar, while it used to be only the part taken by a particular cell. This means that, as you have correctly observed, all dots are drawn one over the other since the coordinates start from the top-left corner of the calendar and not by the corner of each cell. The solution is simple, you just have to adjust the coordinates for drawing depending on the current cell's coordinates:

    public class MyEventRenderer extends EventRenderer {
     
        private Paint paint;
     
        public MyEventRenderer(Context context) {
            super(context);
     
            paint = new Paint();
            paint.setAntiAlias(true);
        }
     
        @Override
        public void renderEvents(Canvas canvas, CalendarDayCell cell) {
     
            int desiredOffset = 20;
            int shapeRadius = 10;
            int locationX = cell.getLeft() + desiredOffset;
            int locationY = cell.getTop() + cell.getHeight() - desiredOffset;
            for(Event e : cell.getEvents()) {
                this.paint.setColor(e.getEventColor());
                canvas.drawCircle(locationX, locationY, shapeRadius, this.paint);
                locationX += shapeRadius + desiredOffset;
            }
        }
    }

    I hope this information helps. And thanks again for writing in this thread so others can also see how the code should be updated.

    Regards,
    Todor
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  6. Kyle
    Kyle avatar
    30 posts
    Member since:
    Dec 2014

    Posted 17 Jul 2015 in reply to Todor Link to this post

    Thank you very much!  It looks much better now.  My next question, is how do I render the event title next to the rendered shape?

     

     

  7. Kyle
    Kyle avatar
    30 posts
    Member since:
    Dec 2014

    Posted 20 Jul 2015 in reply to Kyle Link to this post

    So I got text to render by using something like this:

    this.paint.setTextSize(20);
    this.paint.setFakeBoldText(true);
    canvas.drawText(e.getTitle(),(float)locationX+20,(float)locationY+8,this.paint);

     

    The issue i'm having now, is that I need to support both normal android devices, very small screens, and tablets.  The above render looks great on normal size phone screens, however is is much much too large on the small screens and the circles overtake the cell.  Are the integers we are using Px instead of DP?  If so, is there anyway to handle multiple screen sizes with a custom renderer other than create multiple instances?

     

  8. Todor
    Admin
    Todor avatar
    778 posts

    Posted 22 Jul 2015 Link to this post

    Hi Kyle,

    Here's how you can create a size that is dependent on the screen size:

    float value = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 20, Resources.getSystem().getDisplayMetrics());
    this.paint.setTextSize(value);

    Now depending on the current device's screen, the value will be correctly converted.

    I hope this information helps.

    Regards,
    Todor
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Back to Top
DevCraft banner