[안드로이드] 커스텀 달력 만들기

Jang Seok Woo·2021년 8월 9일
0

Android Studio

목록 보기
15/20

커스텀 달력을 만들어보았다.

생각보다 할 일이 많고, 고려해야할 것도 많다.

그냥 날짜만 나오는 것이 아닌,

  1. 공휴일, 음력 정보를 함께 포함하고

  2. 스케쥴 입력시 해당 스케쥴이 있는 날짜는 dot로 표시되며

  3. 해당 날짜 터치하면 색상있는 원형으로 표시가 되고,

  4. 바로 아래에 달력이 열리며 생긴 공간에 선택된 날짜의 스케쥴 정보 혹은 스케쥴이 없는 날짜라면, 음력일자와 공휴일이라면 공휴일 정보까지 나오는 달력을 만들어보았다.

-> 이미지 추가할 것


어떤식으로 구현을 할지 먼저 계획과 생각을 하는 시간을 가져야한다.

  • 달력은 어떻게 만들어야 하나

calendarView를 사용
구글링해서 library를 사용

gridView - gridView는 setAdapter가 가능하나(어댑터 사용 가능), 각 칸별로 크기가 일정해야한다. 각 칸의 크기가 서로 크기가 다르게 구성해야하는 나로써는 적절치 않은 옵션이다.

gridLayout - GridView와 다르게 gridlayoutmanager를 통해 각 칸의 간격을 달리할 수 있다. -> 나의 목적에 부합함
하지만 gridLayout은 setAdapter가 되지 않아, 스케쥴을 저장한 곳은 다르게 이미지를 출력하고, 선택시 선택 날짜의 이미지를 변경해서 출력하려는 나의 의도와는 맞지 않는다.

            StaggeredGridLayoutManager.LayoutParams layoutParams =
                    (StaggeredGridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams();
//fullspan을 이용해 해당 row의 span을 최대로 늘릴 수 있음
            layoutParams.setFullSpan(true);

하지만 내가 원하는 4번 내용(날짜 선택시 바로 아래에 공간이 열리면서, 스케쥴 메모를 띄우기)은 직접구현해야 하기 때문에 위 방법은 불가능하고
공부도 할 겸 그냥 수작업으로 한땀 한땀 만들어야겠다고 결정했다.

recyclerView
구글링시 가장 많이 사용된다. 하지만 세로나 가로로 만 개수를 늘릴 수 있는 방식이라고 알고있었다.

하지만 방법이 있었다.

recyclerView를 사용하여 adapter를 연동해 조건에 따라 다른 이미지를 출력하는 것이 가능하고, 동시에 recyclerView에 staggeredGridlayoutmanager를 set하여 칸의 너비에 변동을 줄 수 있다.

//fullspan을 위한 staggeredGridlayout manager 사용
final StaggeredGridLayoutManager layoutManager =
new StaggeredGridLayoutManager(7, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);

데이터 저장은 Preference를 이용하였다.

이 작업을 통해

Activity와 adpter의 설계와 구조를 이해하는데 도움이 되었고,
View, model, Presenter의 구분을 좀 더 명확히 느낄 수 있었다.

Activity는 View로써의 역할,
Adapter는 View 중의 recyclerView에 뷰를 동적으로 뿌려 내가 '조작'할 수 있게 만들어주는 recyclerView에 특화된 역할
Preference는 쿼리는 없지만 DB와 같은 역할
Model은 API를 연동하여 공휴일 정보를 가져오는 클래스들 데이터를 담을 공간
Presenter는 DB에서 가져온 데이터를 내가 원하는대로 만지작거리거나 조작하여 View의 위치에있는 Activity로 전달해준다.

다시말해 Activity에선 Presenter에서 잘 다듬어놓은 결과값을 받아와 View와 연결시켜주는 역할만 하면 된다.

아직까지 내가 이해한 MVP의 구조는 이렇다.

코드를 차후에 올리도록 하겠다.

CalendarInfoPresenter.java

//달력의 기본정보를 DB(preference)에 생성하고 저장해주는 작업
public class CalenderInfoPresenter implements RestContract.ActivityView {
    private static final String TAG = CalenderInfoPresenter.class.getSimpleName();
    String PREFERENCE_KEY = "WeatherKok.SharedPreference";
    String mYear;
    String mMonth;
    BaseDateInfoList mBaseDateInfoList = new BaseDateInfoList();
    ArrayList<BaseDateInfo> mDateInfoList;
    Context mContext;

    public void initCal(String year, String month, Context context){
        this.mContext = context;

        clearList(year, month);
        //양력, 음력 날짜를 preference에 저장 + 요일, 1일을 위한 공백 추가
        setLunaOnThePreference(year, month);
        //해당 월의 공휴일을 저장
        setHolidayOnPreference(year, month);
        //처음에만
        makeDummySchedule();
    }

    private BaseDateInfoList settingDay(BaseDateInfoList baseDateInfoList){
        //gridview 요일 표시

        //어레이 앞에 추가한것임
        ArrayList<BaseDateInfo> listDay = new ArrayList<>();

        for(int i =0;i<7;i++) {
            //토 = 100 금101,목 102,...(어댑터에서 구분할 예정
            BaseDateInfo baseDateInfo = new BaseDateInfo();
            baseDateInfo.setDate(100+i);
            listDay.add(baseDateInfo);
            baseDateInfo = new BaseDateInfo();
        }

        baseDateInfoList.getBaseDateInfoList().addAll(0,listDay);

        return baseDateInfoList;
    }

    private int check1stDayOfTheMonth(String year, String month){

        Calendar calendar = Calendar.getInstance();
        int intYear = Integer.parseInt(year);
        int intMonth = Integer.parseInt(month);
        //이번달 1일 무슨요일인지 판단 mCal.set(Year,Month,Day)
        calendar.set(intYear, intMonth-1, 1);
        int dayNum = calendar.get(Calendar.DAY_OF_WEEK);
        Log.i(TAG, "check1st day of the month" + dayNum);
        return dayNum;

    }

    //1일이 무슨요일인지 계산해서 99를 넣어 어댑터에서 빈칸으로 만들 것
    private BaseDateInfoList setting1stDay(BaseDateInfoList baseDateInfoList, int dayNum){

        BaseDateInfo baseDateInfo = new BaseDateInfo();
        baseDateInfo.setDate(99);

        //99 = 빈칸
        for (int i = 1; i < dayNum; i++) {
            baseDateInfoList.getBaseDateInfoList().add(0,baseDateInfo);
        }

        return baseDateInfoList;
    }

    private void clearList(String year, String month){
        SharedPreferences pref = mContext.getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();
        editor.remove(year+month);
    }

    private BaseDateInfoList getDateInfoFromSP(String year, String month){

        //Preference에 날씨 정보 객체 불러오기

        SharedPreferences pref = mContext.getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();

        Gson gson = new GsonBuilder().create();

        BaseDateInfoList baseDateInfoList = new BaseDateInfoList();

        //null일 경우 처리할것.
        String loaded = pref.getString(year+month,"");

        baseDateInfoList = gson.fromJson(loaded, BaseDateInfoList.class);
        //Preference에 저장된 데이터 class 형태로 불러오기 완료

        return baseDateInfoList;
    }

    private void setDateInfoToSP(BaseDateInfoList baseDateInfoList,String year, String month){

        SharedPreferences pref = mContext.getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();

        Gson gson = new GsonBuilder().create();

        //Preference에 정보 객체 저장하기
        //JSON으로 변환
        String jsonString = gson.toJson(baseDateInfoList, BaseDateInfoList.class);
        Log.i("jsonString : ",jsonString);

        //초기화
        editor.remove(year+month);

        editor.putString(year+month,jsonString);
        editor.commit();
        //저장완료

    }

    //해당 년, 월 정보를 받아와서 그 달의 음력 날짜를 월,일 단위로 preference에 저장한다. 접근 key값은 ex)base201208
    //년 월 정보 가져오기, 해당 달은 몇일인지 31,30,29,28일 구한 뒤 mDateInfoList에 저장한다.
    public void setLunaOnThePreference(String year, String month){
        //연, 월 데이터 저장
        mYear = year;
        mMonth = month;

        int intYear = Integer.parseInt(year);
        int intMonth = Integer.parseInt(month);

        //정보 불러와서 추가하기로 접근해야 한다.
        //BaseDateInfoList 클래스 형태로 저장 및 불러오기를 한다.

        //Preference에 날씨 정보 객체 불러오기
        Log.i(TAG, "year_month key : " + year + month);
        SharedPreferences pref = mContext.getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();

        //preference에 저장되어있는 날짜 정보 가져오기
        //preference가 null일 경우 처리할것
        BaseDateInfoList baseDateInfoList = getDateInfoFromSP(year, month);

        //null일시(최초로 불러올 시), 해당 리스트 메모리를 할당한다.
        if(baseDateInfoList.getBaseDateInfoList()==null)
        {
            baseDateInfoList = new BaseDateInfoList();
        }

        //음력 계산 및 계산된 음력 날짜 리스트 생성
        Calendar calendar = Calendar.getInstance();

        calendar.set(Calendar.YEAR,intYear);
        calendar.set(Calendar.MONTH,intMonth);

        ArrayList<String> lunaList = new ArrayList<>();

        for(int i =1;i<calendar.getActualMaximum(Calendar.DAY_OF_MONTH)+1;i++){
            String date = String.valueOf(i);

            if(date.length()<2){
                date = "0"+date;
            }
            //양력문자열 년월일 yyyymmdd 완성
            String temp = year + month + date;
            //음력 계산
            temp = LunaCalendar.Solar2Lunar(temp);
            temp = temp.substring(4);

            //구조체를 만들어 리스트에 넣는다.
            BaseDateInfo baseDateInfo = new BaseDateInfo();
            baseDateInfo.setDate(Integer.parseInt(date));
            baseDateInfo.setLuna(temp);

            // i+1일 의 데이터가 들어간다 ex) 13일은 리스트의 12번째에 들어간다.(앞에 0 때문에)
            baseDateInfoList.getBaseDateInfoList().add(i-1, baseDateInfo);
        }

        //1일 언제 시작하는지 계산 후 빈칸 추가
        int dayNum = check1stDayOfTheMonth(year, month);
        baseDateInfoList = setting1stDay(baseDateInfoList, dayNum);
        //요일 추가
        baseDateInfoList=settingDay(baseDateInfoList);

        //데이터 리스트 음력 추가 완료

        setDateInfoToSP(baseDateInfoList, year, month);

    }


    //해당 년, 월 정보를 받아와서 그 달의 공휴일 정보를 공휴일 이름, 몇일인지 저장한다.
    //공휴일 Api로부터 데이터를 받아와서 공휴일 이름, 몇일인지 데이터를 구하고 해당 일자에 저장한다.
    public void setHolidayOnPreference(String year, String month){
        //연, 월 데이터 저장
        mYear = year;
        mMonth = month;

        int intYear = Integer.parseInt(year);
        int intMonth = Integer.parseInt(month);

        //정보 불러와서 추가하기로 접근해야 한다.
        //BaseDateInfoList 클래스 형태로 저장 및 불러오기를 한다.

        //Preference에 날씨 정보 객체 불러오기

        SharedPreferences pref = mContext.getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
        SharedPreferences.Editor editor = pref.edit();

        //preference에 저장되어있는 날짜 정보 가져오기
        //preference가 null일 경우 처리할것
        BaseDateInfoList baseDateInfoList = getDateInfoFromSP(year, month);


        //공휴일 데이터 추가하기
        getFromholidayApi(year, month);

        //기존의 가져온 데이터에서 탐색을 해서,
        //해당 날짜가 같은 혹은 해당 배열의 위치가 같은 곳에 공휴일을 추가로 집어넣는다.
        //mBaseDateInfoList는 공휴일 정보 저장 리스트.
        for(int i=0;i<mBaseDateInfoList.getBaseDateInfoList().size();i++) {
            //받아온 공휴일 리스트에서 날짜를 가져온다.
            int temp = mBaseDateInfoList.getBaseDateInfoList().get(i).getDate();

            for(int j =0;j<baseDateInfoList.getBaseDateInfoList().size();j++) {
                //공휴일 날짜(temp) =
                if (temp == baseDateInfoList.getBaseDateInfoList().get(j).getDate()){
                    baseDateInfoList.getBaseDateInfoList().get(j).setNameOfDay(mBaseDateInfoList.getBaseDateInfoList().get(i).getNameOfDay());
                }
            }

        }


        //데이터 리스트 음력 추가 완료

        setDateInfoToSP(baseDateInfoList, year, month);

    }

    private void getFromholidayApi(String year, String month){
        Log.i(TAG, "starting : getFromholidayApi");

        String serviceKey = "Lhp0GWghhWvVn4aUZSfe1rqUFsdQkNLvT+ZLt5RNHiFocjZjrbruHxVFaiKBOmTnOypgiM7WqtCcWTSLbAmIeA==";
        String type = "json";

        CalendarService calendarService = new CalendarService(this);
        calendarService.getRestInfo(year, month, serviceKey, type);

    }


    @Override
    public void validateSuccess(boolean isSuccess, ResponseParams responseParams) {
    //데이터를 가져와서 preference 해당 위치에 넣기 - 이름, 날짜


        //클래스 하나 만들어서 데이터 저장시키고
        BaseDateInfo baseDateInfo = new BaseDateInfo();

        for(int i=0;i<responseParams.getResponse().getBody().getItems().getItem().size();i++) {
            //이름 넣고
            baseDateInfo.setNameOfDay(responseParams.getResponse().getBody().getItems().getItem().get(i).getDateName());
            //날짜 넣고
            int temp = responseParams.getResponse().getBody().getItems().getItem().get(i).getLocdate();
            temp %= 100;
            baseDateInfo.setDate(temp);
            //데이터 저장한 리스트 만들기
            mBaseDateInfoList.getBaseDateInfoList().add(baseDateInfo);
        }

    }

    @Override
    public void validateSuccessSingle(boolean isSuccess, ResponseSingle responseSingle) {
        //데이터를 가져와서 preference 해당 위치에 넣기 - 이름, 날짜


        //클래스 하나 만들어서 데이터 저장시키고
        BaseDateInfo baseDateInfo = new BaseDateInfo();

            //이름 넣고
            baseDateInfo.setNameOfDay(responseSingle.getResponse().getBody().getItems().getItem().getDateName());
            //날짜 넣고
            int temp = responseSingle.getResponse().getBody().getItems().getItem().getLocdate();
            temp %= 100;
            baseDateInfo.setDate(temp);
            //데이터 저장한 리스트 만들기
            mBaseDateInfoList.getBaseDateInfoList().add(baseDateInfo);

    }

    @Override
    public void validateFailure(String message) {
        //공휴일이 1달에 하루 뿐이라, 리스트가 아닌, 하나의 객체로 여기로 떨어지는 경우.
        Log.i(TAG, "starting : vlidateFailure");

        String serviceKey = "Lhp0GWghhWvVn4aUZSfe1rqUFsdQkNLvT+ZLt5RNHiFocjZjrbruHxVFaiKBOmTnOypgiM7WqtCcWTSLbAmIeA==";
        String type = "json";

        CalendarService calendarService = new CalendarService(this);
        calendarService.getRestInfoForOneDay(mYear, mMonth, serviceKey, type);
    }

    private void makeDummySchedule(){
        //preference 동작 준비
        SharedPreferences sp = mContext.getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();
        //더미 스케쥴
        String dummy_year="2021";
        String dummy_month_aug="08";
        String dummy_month_sep="09";
        String dummy_date_1="10";
        String dummy_date_2="20";
        String dummy_date_3="11";
        String dummy_date_4="12";
        String dummy_where = "성동구 성수동 서울숲";
        String dummy_who = "홍고은";
        String dummy_who2 = "장석우";
        ArrayList<String> whoList = new ArrayList<>();
        whoList.add(dummy_who);
        whoList.add(dummy_who2);

        Schedule dum1 = new Schedule();
        Schedule dum2 = new Schedule();
        Schedule dum3 = new Schedule();
        Schedule dum4 = new Schedule();

        dum1.setYear(dummy_year);
        dum1.setMonth(dummy_month_aug);
        dum1.setDate(dummy_date_1);
        dum1.setWhere(dummy_where);
        dum1.setWho(whoList);

        dum2.setYear(dummy_year);
        dum2.setMonth(dummy_month_aug);
        dum2.setDate(dummy_date_2);
        dum2.setWhere(dummy_where);
        dum2.setWho(whoList);

        dum3.setYear(dummy_year);
        dum3.setMonth(dummy_month_sep);
        dum3.setDate(dummy_date_3);

        dum4.setYear(dummy_year);
        dum4.setMonth(dummy_month_sep);
        dum4.setDate(dummy_date_4);

        //친구정보는 리스트로 받아야한다!
        BaseDateInfoList baseDateInfoList = new BaseDateInfoList();

        //리스트를 불러옴
        baseDateInfoList = getDateInfoFromSP("2021","08");

        setSchedule(baseDateInfoList, dum1);

        setSchedule(baseDateInfoList, dum2);

        setDateInfoToSP(baseDateInfoList, "2021", "08");

        baseDateInfoList = getDateInfoFromSP("2021","09");

        setSchedule(baseDateInfoList, dum3);

        setSchedule(baseDateInfoList, dum4);

        setDateInfoToSP(baseDateInfoList, "2021", "09");
        //더미 preference 저장 완료

    }

    private BaseDateInfoList setSchedule(BaseDateInfoList baseDateInfoList, Schedule dum1) {
        //스케쥴 날짜
        int temp = Integer.parseInt(dum1.getDate());

        //더미 데이터 세팅
        //해당 일자
        for(int i=0;i<baseDateInfoList.getBaseDateInfoList().size();i++) {
            //받아온 공휴일 리스트에서 날짜를 가져온다.
            int temp2 = baseDateInfoList.getBaseDateInfoList().get(i).getDate();

            //스케쥴 날짜(temp) = 해당 월의 날짜,음력 데이터가 들어있는 리스트에서의 양력 날짜 구조체에 추가
            if (temp == temp2) {
                baseDateInfoList.getBaseDateInfoList().get(i).setSchedule(dum1);
            }
        }


        return baseDateInfoList;
    }

}

RecyclerViewAdapter.java

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
    String PREFERENCE_KEY = "WeatherKok.SharedPreference";
    private static final String TAG = "RecyclerViewAdapter";
    private BaseDateInfoList List;
    Context mContext;
    String mSelected;
    String mToday;
    String mYMD;
    private final int HEADER_VIEW = 0;
    private final int FOOTER_VIEW = 1;

    public RecyclerViewAdapter(Context context, BaseDateInfoList List) {
        Log.i(TAG, "Constructor");
        this.mContext = context;
        this.List = List;
        mSelected = ((CalendarActivity) mContext).getmSelectedDate();
        mToday = ((CalendarActivity) mContext).getmToday();

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int type) {
        Log.i(TAG, "onCreateViewHolder");
        LayoutInflater inflater = (LayoutInflater) viewGroup.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = inflater.inflate(R.layout.item_main_calendar, viewGroup, false);
        return new ViewHolder(view);

    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int positionItem) {
        //양력 날짜 가져오기
        int item = List.getBaseDateInfoList().get(positionItem).getDate();

        SharedPreferences pref = mContext.getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);

        //resultSplit[0]년도, [1] 월, [2] 일
        String[] resultSplit = new String[3];
        resultSplit = String.valueOf(mSelected).split("/");

        Calendar calendar = Calendar.getInstance();

        //일요일 빨강
        calendar.set(Calendar.YEAR, Integer.parseInt(resultSplit[0]));
        calendar.set(Calendar.MONTH, Integer.parseInt(resultSplit[1]));
        calendar.set(Calendar.DATE, List.getBaseDateInfoList().get(positionItem).getDate());

        Log.i(TAG, "year : " + resultSplit[0] + "month : " + resultSplit[1] + "day : " + resultSplit[2]);

        int seldate = Integer.parseInt(resultSplit[2]);

        if (item == 200) {
            Log.i(TAG, "메시지 빈칸 for selected : " + mSelected);

            //선택된 날짜의 주차를 계산 후 아래칸의 메모공간을 만들어야함
            //선택되었을 때 특정일자 정보 표시

            //full span!!
            StaggeredGridLayoutManager.LayoutParams layoutParams =
                    (StaggeredGridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams();
            layoutParams.setFullSpan(true);

            //스케쥴 문자열로 구현
            //어디로? : ㅇㅇㅇ, 누구랑? : ㅇㅇㅇ, ㅇㅇㅇ

            String scheduleMemo;

            String friends = "";
            //친구 여러명일시, 문자열 만들기
            if (List.getBaseDateInfoList().get(seldate).getSchedule().getWho() != null) {
                for (int i = 0; i < List.getBaseDateInfoList().get(seldate).getSchedule().getWho().size(); i++) {
                    friends += List.getBaseDateInfoList().get(seldate).getSchedule().getWho().get(i);
                    //마지막엔 콤마 없이
                    if ((i + 1) != List.getBaseDateInfoList().get(seldate).getSchedule().getWho().size()) {
                        friends += ", ";
                    }
                }
            }

            if (List.getBaseDateInfoList().get(seldate).getSchedule().getWhere() != null) {
                scheduleMemo = "어디로? : " + List.getBaseDateInfoList().get(seldate).getSchedule().getWhere() + ", 누구랑? : " + friends;
                viewHolder.tv.setText(scheduleMemo);

            } else {
                scheduleMemo = "어디로? : " + ", 누구랑? : " + friends;
                viewHolder.tv.setText(scheduleMemo);
            }

            //스케쥴이 없을 시 분기 구현
            if (List.getBaseDateInfoList().get(seldate).getSchedule().getWhere() == null
                    && List.getBaseDateInfoList().get(seldate).getSchedule().getWho() == null) {

                String luna = List.getBaseDateInfoList().get(seldate).getLuna();
                if (List.getBaseDateInfoList().get(seldate).getNameOfDay() != null) {
                    String holiday = List.getBaseDateInfoList().get(seldate).getNameOfDay();
                    viewHolder.tv.setText("음력 : " + luna + " ," + holiday);
                } else {
                    viewHolder.tv.setText("음력 : " + luna);
                }

            }
            //요일 구분하기
        }else if(item==100||item==101||item==102||item==103||item==104||item==105||item==106||item==99){

            switch(item){
                case 100: viewHolder.tv.setText("토"); viewHolder.tv.setTextColor(mContext.getResources().getColor(R.color.purple_700));
                case 101: viewHolder.tv.setText("금");
                case 102: viewHolder.tv.setText("목");
                case 103: viewHolder.tv.setText("수");
                case 104: viewHolder.tv.setText("화");
                case 105: viewHolder.tv.setText("월");
                case 106: viewHolder.tv.setText("일"); viewHolder.tv.setTextColor(mContext.getResources().getColor(R.color.red));
                case 99: viewHolder.tv.setText("");
            }

        }
        //딱히 스케쥴 없는 날짜라면,
        else if ((List.getBaseDateInfoList().get(positionItem).getSchedule())!=null
                    &&(List.getBaseDateInfoList().get(positionItem).getSchedule().getWhere())!=null) {
            Log.i(TAG, "schedule dot" + item + "일");
            //item = item.substring(1);
            viewHolder.tv.setText(String.valueOf(item));
            viewHolder.tvScheduled.setBackground((Drawable) mContext.getResources().getDrawable(R.drawable.selected_dot));

            //음력표시 -> 나중에 버튼 클릭시 보이는 것으로 변경할 것
            if(List.getBaseDateInfoList().get(positionItem).getLuna()!=null) {
                String luna = List.getBaseDateInfoList().get(positionItem).getLuna();
                String luna_month = luna.substring(0, 2);
                String luna_day = luna.substring(2);
                luna = luna_month + "." + luna_day;
                viewHolder.tvLuna.setText(luna);
            }

            int day = calendar.get(Calendar.DAY_OF_WEEK);
            if (day == 1) {
                viewHolder.tv.setTextColor(mContext.getResources().getColor(R.color.red));
            }


            //토요일 파랑
            if (day == 7) {
                viewHolder.tv.setTextColor(mContext.getResources().getColor(R.color.purple_700));
            }

            //오늘 날짜 black
            if (mToday.equals(String.valueOf(item))) { //오늘 day 텍스트 컬러 변경
                viewHolder.tv.setTextColor(mContext.getResources().getColor(R.color.black));
            }
            //사용자가 선택한 날짜일 경우
            } else if(seldate==List.getBaseDateInfoList().get(positionItem).getDate()){
            //날짜 세팅하고
            viewHolder.tv.setText(String.valueOf(item));

            //오늘 날짜 black
            if (mToday.equals(String.valueOf(item))) { //오늘 day 텍스트 컬러 변경
                viewHolder.tv.setTextColor(mContext.getResources().getColor(R.color.black));
            }

            //음력표시 -> 나중에 버튼 클릭시 보이는 것으로 변경할 것
            if(List.getBaseDateInfoList().get(positionItem).getLuna()!=null) {
                String luna = List.getBaseDateInfoList().get(positionItem).getLuna();
                String luna_month = luna.substring(0, 2);
                String luna_day = luna.substring(2);
                luna = luna_month + "." + luna_day;
                viewHolder.tvLuna.setText(luna);
            }

            //배그라운드 표시
            Log.i(TAG, "selected date");
            viewHolder.tv.setBackground((Drawable) mContext.getResources().getDrawable(R.drawable.bg_selected_calendar_day));

        } else {
            //스케쥴도 없고 선택된 날짜도 아닌경우
            Log.i(TAG, "works");
            //일자 텍스트뷰에 표시
            viewHolder.tv.setText(String.valueOf(item));

            //오늘 날짜 black
            if (mToday.equals(item)) { //오늘 day 텍스트 컬러 변경
                viewHolder.tv.setTextColor(mContext.getResources().getColor(R.color.black));
            }

            //음력표시 -> 나중에 버튼 클릭시 보이는 것으로 변경할 것
            if(List.getBaseDateInfoList().get(positionItem).getLuna()!=null) {
                String luna = List.getBaseDateInfoList().get(positionItem).getLuna();
                String luna_month = luna.substring(0, 2);
                String luna_day = luna.substring(2);
                luna = luna_month + "." + luna_day;
                viewHolder.tvLuna.setText(luna);
            }

            //일요일 빨강
            calendar.set(Calendar.YEAR, Integer.parseInt(resultSplit[0]));
            calendar.set(Calendar.MONTH, Integer.parseInt(resultSplit[1]) - 1);
            calendar.set(Calendar.DATE, List.getBaseDateInfoList().get(positionItem).getDate());

            int day = calendar.get(Calendar.DAY_OF_WEEK);
            if (day == 1) {
                viewHolder.tv.setTextColor(mContext.getResources().getColor(R.color.red));
            }

            //토요일 파랑
            if (day == 7) {
                viewHolder.tv.setTextColor(mContext.getResources().getColor(R.color.purple_700));
            }
        }

    }

    @Override
    public int getItemCount() {
        return List.getBaseDateInfoList().size();
    }

public interface OnItemClickListener {
    void onItemClick(View v, int position);
}

    private OnItemClickListener mListener;

    public void setOnItemClickListener(OnItemClickListener listener) {
        this.mListener = listener;
    }

public class ViewHolder extends RecyclerView.ViewHolder {
    TextView tv;
    TextView tvScheduled;
    TextView tvLuna;
    String where_from_holder;

    ViewHolder(View view) {
        super(view);
        tv = view.findViewById(R.id.tv_item);
        tvScheduled = view.findViewById(R.id.tv_item_scheduled);
        tvLuna = view.findViewById(R.id.tv_item_luna);

        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Context context = view.getContext();

                where_from_holder = tv.getText().toString();
                int pos = getAdapterPosition();
                Log.i(TAG, "pos : " + pos);
                if (pos != RecyclerView.NO_POSITION) {
                    mListener.onItemClick(v, pos);
                }
                //preference 동작 준비
                SharedPreferences pref = context.getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
                SharedPreferences.Editor editor = pref.edit();
                // key값에 value값을 저장한다.
                // String, boolean, int, float, long 값 모두 저장가능하다.
                //기존에 있던 주소를 잠시 저장해두고,
                //preference에 저장

                String date = pref.getString("when", "");
                Log.i("when should be y/m : ", date);

                //특정 스케쥴을 저장할 리스트도 구현하기
                String temp = tv.getText().toString();

                //일자 한자리수일때 앞에 0 붙이기
                if (temp.length() < 2) {
                    temp = "0" + temp;
                }

                date = date + "/" + temp;
                editor.putString("when", date);
                mYMD = date;
                // 메모리에 있는 데이터를 저장장치에 저장한다.
                editor.commit();

                String temp2 = pref.getString("when", "");

                Log.i(TAG, "from the preference : " + temp2);

                //set the selected date on the calendar.
                ((CalendarActivity) mContext).parsingDate(temp2);

            }
        });
    }

}

    private String getKey(String YMD) {

        String key = "";
        if (YMD != null) {
            String[] split = new String[3];
            split = YMD.split("/");
            key = split[0] + split[1];
        }
        return key;
    }

    private void checkWeekend(){



    }

}

CalendarActivity.java

public class CalendarActivity extends BaseActivity implements RestContract.ActivityView {
    private static final String TAG = CalendarActivity.class.getSimpleName();
        RecyclerViewAdapter adapter;
        RecyclerView recyclerView;
        Context mContext;
        private TextView tvYearMonthTop;
        String year_month;
        TextView mTvSelBtn;
        private ArrayList<String> dayList;
        String mSelectedDate;
        ArrayList<String> mScheduledDateList;
        String mToday;

        private RecyclerView gridView;

        private Calendar mCal;
        String PREFERENCE_KEY = "WeatherKok.SharedPreference";

        public Calendar getmCal() {
            return mCal;
        }

        public void setmCal(Calendar mCal) {
            this.mCal = mCal;
        }

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            mContext = getBaseContext();

            initView();

            setCurrentYearMonth();

            mCal = Calendar.getInstance();


            SharedPreferences pref = getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
            SharedPreferences.Editor editor = pref.edit();

            //when 초기화
            editor.putString("when", "");
            editor.commit();
            Log.i(TAG,"click_listener : " + year_month);

            editor.putString("when",year_month);
            editor.putString("year_month",year_month);
            editor.commit();

            mTvSelBtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    String resultDate = mSelectedDate;

                    Log.i(TAG, "result : " + mSelectedDate);

                    String[] resultSplit = new String[3];
                    resultSplit = resultDate.split("/");

                    Schedule resultOnDate = new Schedule();

                    resultOnDate.setYear(resultSplit[0]);
                    resultOnDate.setMonth(resultSplit[1]);
                    resultOnDate.setDate(resultSplit[2]);

                    //구조체 to json
                    //Preference에 날짜 정보 객체 저장하기
                    Gson gson = new GsonBuilder().create();
                    //JSON으로 변환
                    String jsonString = gson.toJson(resultOnDate, Schedule.class);
                    Log.i("jsonString : ",jsonString);
                    //Preference에 저장
                    //누구랑, 어디서와 함께 저장하기 위해 우선 temp로 가져갈것
                    editor.putString("temp",jsonString);
                    editor.commit();

                    //인텐트로 Main으로 이동
                    Intent intent = new Intent(CalendarActivity.this, MainActivity.class);
                    //intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
                    startActivity(intent);
                }
            });

        }

        private void initView(){
            setContentView(R.layout.activity_calendar);

            gridView = findViewById(R.id.rv_calendar);

            tvYearMonthTop = (TextView) findViewById(R.id.tv_year_month_top);

            mTvSelBtn = findViewById(R.id.tv_calendar_selection_btn);
        }

        private Date getToday(){
            // 오늘에 날짜를 세팅 해준다.
            long now = System.currentTimeMillis();
            final Date date = new Date(now);

            return date;
        }

        public void setmSelectedDate(String selectedYMD){

            this.mSelectedDate = selectedYMD;
        }

        public String getmSelectedDate() {
            return mSelectedDate;
        }

        private void setCurrentYearMonth(){

            Date date = getToday();

            //연,월,일을 따로 저장
            final SimpleDateFormat curYearFormat = new SimpleDateFormat("yyyy", Locale.KOREA);
            final SimpleDateFormat curMonthFormat = new SimpleDateFormat("MM", Locale.KOREA);
            final SimpleDateFormat curDayFormat = new SimpleDateFormat("dd", Locale.KOREA);

            //현재 년,월을 구해 저장한다.(주의:월 정보는 +1해줘야한다)
            String currentYear = curYearFormat.format(date);

            int temp = Integer.parseInt(curMonthFormat.format(date));
            String currentMonth = String.valueOf(temp);
            if(temp<10) {
                currentMonth = "0"+currentMonth;
            }
            String currentDay = curDayFormat.format(date);
            //오늘일자에 저장
            setmToday(currentYear+currentMonth+currentDay);
            //선택일자에 저장
            setmSelectedDate(currentYear+"/"+currentMonth+"/"+currentDay);

            //현재 날짜 텍스트뷰에 뿌려줌
            tvYearMonthTop.setText(currentYear + "/" + currentMonth);
            year_month = tvYearMonthTop.getText().toString();
            Log.i(TAG,"month : " + temp + ", stirng : " + currentMonth);
            //년,월의 정보를 갖고 해당 월의 양력,음력,공휴일 정보를 preference에 세팅한다.
            //DB세팅
            loadScheduleData(currentYear, currentMonth);
            //달력 정보 리스트 세팅
            setUnselectedCalendar(currentYear, currentMonth);

        }

    public void setmToday(String s) {
            this.mToday = s;
        }

        public String getmToday() {
            return mToday;
        }

    private BaseDateInfoList settingDay(BaseDateInfoList baseDateInfoList){
            //gridview 요일 표시

            //어레이 앞에 추가한것임
            BaseDateInfo baseDateInfo = new BaseDateInfo();
            //토 = 100 (어댑터에서 구분할 예정
            baseDateInfo.setDate(100);
            baseDateInfoList.getBaseDateInfoList().add(0,baseDateInfo);
            //금 = 101
            baseDateInfo.setDate(101);
            baseDateInfoList.getBaseDateInfoList().add(0,baseDateInfo);
            //목
            baseDateInfo.setDate(102);
            baseDateInfoList.getBaseDateInfoList().add(0,baseDateInfo);
            //수
            baseDateInfo.setDate(103);
            baseDateInfoList.getBaseDateInfoList().add(0,baseDateInfo);
            //화
            baseDateInfo.setDate(104);
            baseDateInfoList.getBaseDateInfoList().add(0,baseDateInfo);
            //월
            baseDateInfo.setDate(105);
            baseDateInfoList.getBaseDateInfoList().add(0,baseDateInfo);
            //일
            baseDateInfo.setDate(106);
            baseDateInfoList.getBaseDateInfoList().add(0,baseDateInfo);


            return baseDateInfoList;
        }

        private int check1stDayOfTheMonth(int year, int month){

            //이번달 1일 무슨요일인지 판단 mCal.set(Year,Month,Day)
            mCal.set(year, month-1, 1);
            int dayNum = mCal.get(Calendar.DAY_OF_WEEK);
            Log.i(TAG, "check1st day of the month" + dayNum);
            return dayNum;

        }

        private BaseDateInfoList setting1stDay(BaseDateInfoList baseDateInfoList, int dayNum){

            BaseDateInfo baseDateInfo = new BaseDateInfo();
            baseDateInfo.setDate(99);

            //99 = 빈칸
            for (int i = 1; i < dayNum; i++) {
                baseDateInfoList.getBaseDateInfoList().add(0,baseDateInfo);
            }

            return baseDateInfoList;
        }

        public void parsingDate(String selectedYMD){

            setmSelectedDate(selectedYMD);

            //String test_date = "2021-08-15 09:15:00";
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd");
            Date date = new Date();
            try {
                date = dateFormat.parse(selectedYMD);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            Log.i(TAG, "parsingDate : " + date);

            divideYmd(selectedYMD);

        }

        public void divideYmd(String selectedYMD){

            String[] temp = new String[3];
            temp = selectedYMD.split("/");

            int year = Integer.parseInt(temp[0]);
            int month = Integer.parseInt(temp[1]);
            int date = Integer.parseInt(temp[2]);

            Log.i(TAG, "divideYMD : " + year + month + date);
            //Preference에서 스케줄 데이터 불러오기
            loadScheduleData(Integer.toString(year), Integer.toString(month));

            setCalendarDate(year, month, date);

        }


        public void setCalendarDate(int year, int month, int date) {

            //set(월별달력, 몇월(0-11))
            Log.i(TAG, "starting setCalendarDate : " + year + month + date);

            //약속일자 몇째주인지 확인
            Calendar scheduledDate = Calendar.getInstance();
            scheduledDate.set(Calendar.YEAR, year);
            scheduledDate.set(Calendar.MONTH, month-1);
            scheduledDate.set(Calendar.DATE, date);

            //약속일자 몇째주인지 week로 받아옴
            int week = scheduledDate.get(Calendar.WEEK_OF_MONTH) + 1;

            Log.i(TAG, "num of week : " + week);

            //preference에서 한달의 모든 정보 가져오기
            SharedPreferences pref = getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
            String key = String.valueOf(year) + String.valueOf(month);
            String jsonMonth = pref.getString(key, "");
            BaseDateInfoList baseDateInfoList = FromJsonToList(jsonMonth);

            //스케쥴을 보여주는 full-span-row가 한번만 실행되도록
            boolean checker = false;
            for (int i = 0; i < scheduledDate.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
                scheduledDate.set(Calendar.DATE, i + 1);
                int temp = scheduledDate.get(Calendar.WEEK_OF_MONTH);

                //약속일자 몇째주인지와 달력에 뿌리는일자 몇째주인지 비교해서 같으면 빈공간 투입(클릭시 메시지 띄울 공간)
                if (temp == week && !checker) {
                    for (int j = 0; j < 1; j++) {
                        Log.i(TAG, "빈칸!!!");

                        //날짜에 200을 넣어 빈공간 투입 구분
                        BaseDateInfo baseDateInfo = new BaseDateInfo();
                        baseDateInfo.setDate(200);
                        baseDateInfoList.getBaseDateInfoList().add(i,baseDateInfo);
                    }
                    checker = true;
                }

            }

            setUpRecView(baseDateInfoList);

        }

    /**
     * 해당 월에 표시할 일 수 구함
     *
     * @param month
     */
    private void setUnselectedCalendar(String year, String month) {
        Log.i(TAG, "setUnselectedCalendar");
        //한달 모든 정보 가져오기

        //preference에서 한달의 모든 정보 가져오기
        SharedPreferences pref = getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
        String key = year + month;
        String jsonMonth = pref.getString(key, "");
        BaseDateInfoList baseDateInfoList = FromJsonToList(jsonMonth);

        Log.i(TAG, "list size : " + String.valueOf(baseDateInfoList.getBaseDateInfoList().size()));

        setUpRecView(baseDateInfoList);

    }

    private BaseDateInfoList FromJsonToList(String json) {

        //Preference에 한달 모든 정보 객체 불러오기

        Gson gson = new GsonBuilder().create();

        BaseDateInfoList baseDateInfoList = new BaseDateInfoList();

        baseDateInfoList = gson.fromJson(json, BaseDateInfoList.class);
        //Preference에 저장된 데이터 class 형태로 불러오기 완료

        return baseDateInfoList;

    }

    private ArrayList<String> checkDateOnScheduled(ArrayList<String> list,ArrayList<String> scheduledList){

        for(int i=0;i<scheduledList.size();i++){

            for(int j=0;j<list.size();j++){
                if(scheduledList.get(i).equals(list.get(j))) {
                    list.set(j,"+" + String.valueOf(j));
                        break;
                }
            }

        }

        return list;

    }


        @Override protected void onResume() {
            super.onResume();
            Log.i(TAG, "onResume()");

//            if (adapter == null) {
//                setUpRecView();
//            }
        }

        private void setUpRecView(BaseDateInfoList baseDateInfoList) {

            Log.i(TAG, "starting setUpRecView" + baseDateInfoList.getBaseDateInfoList().size());
            adapter = new RecyclerViewAdapter(this, baseDateInfoList);
            recyclerView = (RecyclerView) findViewById(R.id.rv_calendar);

            //빈칸 fullspan을 위한 staggeredGridlayout manager 사용
            final StaggeredGridLayoutManager layoutManager =
                    new StaggeredGridLayoutManager(7, StaggeredGridLayoutManager.VERTICAL);
            recyclerView.setLayoutManager(layoutManager);

            //recyclerView.addOnScrollListener(scrollListener);
            recyclerView.setAdapter(adapter);
            adapter.notifyDataSetChanged();
            //뷰를 다시 그린다?
            recyclerView.invalidate();

            //preference 동작 준비
            SharedPreferences sp = getSharedPreferences(PREFERENCE_KEY, MODE_PRIVATE);
            SharedPreferences.Editor editor = sp.edit();

            adapter.setOnItemClickListener(new RecyclerViewAdapter.OnItemClickListener() {
                @Override
                public void onItemClick(View v, int position) {
                    editor.putString("when",year_month);
                    editor.commit();
                }
            });
        }

    private void loadScheduleData(String year, String month){

        CalenderInfoPresenter baseCalenderInfo = new CalenderInfoPresenter();
        //preference에 더미 데이터 및 해당 년,월의 음력, 공휴일 데이터를 생성해준다.
        baseCalenderInfo.initCal(year, month, mContext);
    }
    @Override
    public void validateSuccess(boolean isSuccess, ResponseParams responseRest) {

        Log.i(TAG, "responseRest : " + responseRest.getResponse().getBody().getItems().getItem().get(0).getDateName() );

    }

    @Override
    public void validateSuccessSingle(boolean isSuccess, ResponseSingle responseSingle) {
        //한달에 1개의 휴일이 있을 경우
        Log.i(TAG, "responseSingle : " + responseSingle.getResponse().getBody().getItems().getItem().getDateName() );

    }

    @Override
    public void validateFailure(String message) {
        //공휴일이 1달에 하루 뿐이라, 리스트가 아닌, 하나의 객체로 여기로 떨어지는 경우.
        Log.i(TAG, "starting : vlidateFailure");

        SharedPreferences sp = getSharedPreferences(PREFERENCE_KEY,MODE_PRIVATE);
        SharedPreferences.Editor editor = sp.edit();

        String year = "2021";
        String solmont = "08";
        String serviceKey = "Lhp0GWghhWvVn4aUZSfe1rqUFsdQkNLvT+ZLt5RNHiFocjZjrbruHxVFaiKBOmTnOypgiM7WqtCcWTSLbAmIeA==";
        String type = "json";

        CalendarService calendarService = new CalendarService(this);
        calendarService.getRestInfoForOneDay(year, solmont, serviceKey, type);
    }
}

아직 부분부분 수정중인 부분이 있다 어댑터의 음력 계산 부분이라던지 아직 중복 코드들이 많아 함수를 만들어 대체하면 된다.

profile
https://github.com/jsw4215

0개의 댓글