본문으로 바로가기

[안드로이드]달력 만들기(calendar)

category Android 2017. 8. 7. 15:23

안녕하세요!! 오늘은 안드로이드에서 달력을 만들어 보겠습니다!!


안드로이드 달력은 수많은 예제가 있는데요 


이번 포스트에서는 Material Calendar 를 사용하여 달력을 만들어 보도록 하겠습니다! 

https://github.com/prolificinteractive/material-calendarview

Material Calendar 의 GitHub 주소입니다. 


사용하기에 앞서서 Build에 compile 'com.prolificinteractive:material-calendarview:1.4.3' 라이브러리를 추가 하도록 합니다.


Material Calendar 에서는 다양한 형태의 Calendar를 제공 합니다. 


우선 가장 기본적인 Calendar사용법을 알아보겠습니다.


xml에서는 

<com.prolificinteractive.materialcalendarview.MaterialCalendarView
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/calendarView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:mcv_selectionColor="#a9dbf0cb"
        app:mcv_showOtherDates="defaults" />


추가해줍니다.

// showOtherDates 에는 여러 옵션이 있습니다 

// 기본적으로 defaults 값은 현재 달(month)만 보여줍니다.

// 이전달의 날자와 다음달 날자의일부를 보여주는 옵션도 가능합니다.



java코드로 넘어와서 


@Bind(R.id.calendarView)
    MaterialCalendarView materialCalendarView;

MaterialCalendarView 를 바인드 해줍니다. (findViewById 로 얻어와도 됩니다)


MaterialCalendarView에는


materialCalendarView.state().edit()
                .setFirstDayOfWeek(Calendar.SUNDAY)
                .setMinimumDate(CalendarDay.from(2017, 0, 1))
                .setMaximumDate(CalendarDay.from(2030, 11, 31))
                .setCalendarDisplayMode(CalendarMode.MONTHS)
                .commit();View);

달력의 시작과 끝을 지정해줄수 있습니다.

 materialCalendarView.addDecorators(
                new SundayDecorator(),
                new SaturdayDecorator(),
                oneDayDecorator);

addDecorators 로 달력에 효과를 줄수있습니다.

예를들어



처럼 SundayDecorator()와 SaturdayDecorator()로 토요일,일요일에 색을 줄수 있고 onDayDecorator()로 오늘 날자에 지정색을 줄 수 있습니다.


SundayDecorator(),SaturdayDecorator(),onDayDecorator() 의 예시는 포스트 아래에 올려두겠습니다!


그 외에도 클릭이벤트(아래)

materialCalendarView.setOnDateChangedListener(new OnDateSelectedListener() {
            @Override
            public void onDateSelected(@NonNull MaterialCalendarView widget, @NonNull CalendarDay date, boolean selected) {
  }
} 

특정 날자에 효과표시 기능이 있습니다. (아래)

    private class ApiSimulator extends AsyncTask<Void, Void, List<CalendarDay>> {
 
        @Override
        protected List<calendarday> doInBackground(@NonNull Void... voids) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MONTH, -2);
            ArrayList<calendarday> dates = new ArrayList<>();
            for (int i = 0; i < 30; i++) {
                CalendarDay day = CalendarDay.from(calendar);
                dates.add(day);
                calendar.add(Calendar.DATE, 5);
            }
 
            return dates;
        }
 
        @Override
        protected void onPostExecute(@NonNull List<calendarday> calendarDays) {
            super.onPostExecute(calendarDays);
 
            if (isFinishing()) {
                return;
            }
 
            materialCalendarView.addDecorator(new EventDecorator(Color.RED, calendarDays));        }
    }

위 예제는 

 calendar.add(Calendar.MONTH, -2);
            ArrayList<calendarday> dates = new ArrayList<>();
            for (int i = 0; i < 30; i++) {
                CalendarDay day = CalendarDay.from(calendar);
                dates.add(day);
                calendar.add(Calendar.DATE, 5);
            }

현재 달(month)의 2달전부터 5일 간격으로 30개의 (i<30) 
widget.addDecorator(new EventDecorator(Color.RED, calendarDays));

빨간점을 찍는 이벤트로 되어있습니다.

이부분을 사용자에 맞게 변형시키면 원하는 날자에 특별한 효과를 줄 수 있습니다.

이상으로 아~주 기본적인 material calendar 에 대해 알아보았습니다.
 
자세한 내용은 GitHub를 참고해주세요.

SundayDecorator.JAVA
public class SundayDecorator implements DayViewDecorator {
 
    private final Calendar calendar = Calendar.getInstance();
 
    public SundayDecorator() {
    }
 
    @Override
    public boolean shouldDecorate(CalendarDay day) {
        day.copyTo(calendar);
        int weekDay = calendar.get(Calendar.DAY_OF_WEEK);
        return weekDay == Calendar.SUNDAY;
    }
 
    @Override
    public void decorate(DayViewFacade view) {
        view.addSpan(new ForegroundColorSpan(Color.RED));
    }
}

SaturdayDecorator.JAVA

public class SaturdayDecorator implements DayViewDecorator {
 
    private final Calendar calendar = Calendar.getInstance();
 
    public SaturdayDecorator() {
    }
 
    @Override
    public boolean shouldDecorate(CalendarDay day) {
        day.copyTo(calendar);
        int weekDay = calendar.get(Calendar.DAY_OF_WEEK);
        return weekDay == Calendar.SATURDAY;
    }
 
    @Override
    public void decorate(DayViewFacade view) {
        view.addSpan(new ForegroundColorSpan(Color.BLUE));
    }
}

onDatDecorator.JAVA

public class OneDayDecorator implements DayViewDecorator {
 
    private CalendarDay date;
 
    public OneDayDecorator() {
        date = CalendarDay.today();
    }
 
    @Override
    public boolean shouldDecorate(CalendarDay day) {
        return date != null && day.equals(date);
    }
 
    @Override
    public void decorate(DayViewFacade view) {
        view.addSpan(new StyleSpan(Typeface.BOLD));
        view.addSpan(new RelativeSizeSpan(1.4f));
        view.addSpan(new ForegroundColorSpan(Color.GREEN));
    }
 
    /**
     * We're changing the internals, so make sure to call {@linkplain MaterialCalendarView#invalidateDecorators()}
     */
    public void setDate(Date date) {
        this.date = CalendarDay.from(date);
    }
}

EventDecorator.java

package com.project.sample_calendar.decorators;

import android.app.Activity;
import android.graphics.drawable.Drawable;

import com.project.sample_calendar.R;
import com.prolificinteractive.materialcalendarview.CalendarDay;
import com.prolificinteractive.materialcalendarview.DayViewDecorator;
import com.prolificinteractive.materialcalendarview.DayViewFacade;

import java.util.Collection;
import java.util.HashSet;

/**
 * Decorate several days with a dot
 */
public class EventDecorator implements DayViewDecorator {

    private final Drawable drawable;
    private int color;
    private HashSet<CalendarDay> dates;

    public EventDecorator(int color, Collection<CalendarDay> dates,Activity context) {
        drawable = context.getResources().getDrawable(R.drawable.more);
        this.color = color;
        this.dates = new HashSet<>(dates);
    }

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

    @Override
    public void decorate(DayViewFacade view) {
        view.setSelectionDrawable(drawable);
        //view.addSpan(new DotSpan(5, color)); // 날자밑에 점
    }
}

달력예제는 포스트 처음 github 로 가시면 다운받을수 있습니다!!

혹시 제가 사용한 달력 예제를 원하시면 댓글로 남겨주세요.



-----------------------------------------------------------------------------------------------------------------

예제를 원하시는분이 많아 git에 올려두었습니다.

https://github.com/dolsanta/Sample_Calendar



댓글을 달아 주세요

  1. 이전 댓글 더보기
  2. 머리아픈공대생 2018.06.11 17:56

    혹시 메일이나 이런걸로 여쭤보아도 될까요??

  3. 구구 2018.07.06 15:03

    안녕하세요 코드 예제 공유 감사합니다. 이것저것 해보고 있는데 혹시 버튼을 클릭하면 투데이로 이동하는 메서드는 없을까요?
    goToNext, goToPrevious 월별로 이동하고 setDataSelected(true)값을 줘서 간단하게 만들기는 했는데 년도차이가 심할경우는 좀 복잡해지네요
    좋은 글 감사합니다

  4. 궁금 2018.10.29 11:53

    포스팅 잘 봤습니다.
    궁금한게 하나 있는데요.
    저 빨간 점 대신 그 자리에 textview를 넣고싶은데
    어떤식으로 구현해야 할 지 모르겠네요 ㅜ
    힌트좀 주실 수 있으실까요~?

  5. BlogIcon 궁금합니다 2018.10.31 19:49

    포스트 잘 봤습니당~덕분에 해결이 되었습니다^^그런데 혹시..하루에 2개 이상의 점을 찍을 수 있나요??

  6. 질문이욧 2018.11.30 06:00

    월~금 요일을 하얀색으로 하려면 어떤걸 불러와야 할까요?

  7. ddwlwl 2018.12.19 15:41

    덕분에 해결하고 갑니다 감사합니다 :)

  8. navy 2019.01.01 14:53

    포스트 잘 봤습니다 감사합니다.

  9. 제발급해요 2019.01.07 18:40

    달력에 어느분보니까 1월 2019 라고되어있는데 제 xml에도 분명 1월 2019라고뜨던데 실행하면 애뮬에서는 왜 January 2019 라고뜨는지 아세요?ㅠㅠㅠ 전 2019년 1월 이렇게 고치고싶은데 방법이 없는건가요?

  10. 안녕하세욤 2019.01.25 13:46

    material calendar view랑 그냥 calendar view랑 차이가 있는건가요?

  11. 링딩동링 2019.02.13 11:04

    혹시 코드 받을 수 있을까요 ㅜㅜ sdr0113@naver.com 부탁해용

  12. 안녕하세요 2019.05.27 18:12

    혹시 이 공동개발 API의 라이센스 정보가 어떻게 되나요? 깃허브 들어가 보아도 확인을 못하겠네요.

  13. 2019.08.04 16:20

    비밀댓글입니다

  14. 아일 2019.11.11 03:51

    덕분에 달력 완성하였습니다 감사합니다.
    다만 깃헙에 있는 예시대로 특정날짜에 점을 표시하였는데
    스트링 배열값의 마지막 날짜는 표시가 안되고 그대신에 오늘 날짜에 점이 표시되는데 무엇이 잘못된걸까요?

    • 안녕하세요.
      시간이 많이 지났지만 다른 분들께 도움이 될까 답글 남깁니다.

      문제의 원인은 CalendarDay day = CalendarDay.from(calendar); 선언 위치 때문에 발생한 문제입니다.

      깃허브 소스코드(Sample_Calendar/app/src/main/java/com/project/sample_calendar/MainActivity.java ) 에서 107,113,114번째 라인을 주석처리하고

      114번째 라인에

      calendar.set(year, month - 1, dayy);
      CalendarDay day = CalendarDay.from(calendar);
      dates.add(day);
      이렇게 순서를 바꿔서 작성해주시면 정상적으로 표시 됩니다.

      아래 링크에 해당 부분 수정한 소스 있습니다.
      주석은 있지만 저만 보려고 한거라 이해가 안되실거예요..^^;;
      https://59595959.tistory.com/4


  15. 김전기 2019.12.01 16:21

    ERROR: Could not find method implementation() for arguments [directory 'libs'] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
    빌드과정에서 발생한 에러인데 어떻게 해결하나요?

  16. 코딩김 2019.12.10 17:14

    지정된 날짜에 도트를 넣어주는거는 안돼나요? add문말고요

  17. 졸업하고싶어요 2020.05.12 23:56

    좀 다른 이야기이지만 gradle.properits 라는 파일은 자동 생성 된것인가요? 한번도 본 적이 없는 파일이라서요

  18. dd 2020.05.19 16:18

    drawable = context.getResources().getDrawable(R.drawable.more);
    여기서 more은 어떤걸 넣으면 되나요?>

  19. 김승미 2020.12.02 04:40

    코드를 사용해 보려고 하는데 copyTo메서드를 사용 못하네요
    Cannot resolve method 'copyTo' in 'CalendarDay'
    이렇게 떠요 import 도 잘 됬는데 무슨 문제일까요

  20. 드로이드안 2021.01.17 13:06

    버튼을 누르면 당일 날짜에 점 표시가 찍히게하려면 코드를 어떤식으로 짜야되나요??

  21. 2021.08.30 16:35

    비밀댓글입니다