안드로이드

안드로이드 주간 달력을 만들어보자!! Android Week Calendar

알통몬_ 2019. 2. 12. 09:10
반응형

 

 

 

 

공감 및 댓글은 포스팅 하는데

 아주아주 큰 힘이 됩니다!!

포스팅 내용이 찾아주신 분들께 

도움이 되길 바라며

더 깔끔하고 좋은 포스팅을 

만들어 나가겠습니다^^

 

 

 

 

안드로이드 주간 달력을 만들어 보았습니다.

기존에는 잘 나와있는 라이브러리를 썼었는데, 디자인을 수정하는데 있어서

약간의 불편함이 있어서 그냥 만들어보자 해서 만들어 봤습니다.

물론 라이브러리로 만든 건 아닙니다 ㅎㅎ

 

년 월 일이 나오는 Layout 하나

일 ~ 토   요일이 나오는 Layout 하나 

그리고 마지막으로 일을 들어가는 RecyclerView가 사용되었습니다.

그리고 물론 데이터 바인딩을 사용했습니다.

 

레이아웃

1. activitiy_main.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        tools:context=".activity.PatientDetailActivity">
    <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        <!-- year month week layout -->
        <android.support.constraint.ConstraintLayout
                android:background="@color/lgt_gray"
                app:layout_constraintTop_toTopOf="parent"
                android:id="@+id/ymwLayout"
                app:layout_constraintDimensionRatio="7:0.85"
                android:layout_width="match_parent"
                android:layout_height="0dp">
            <!--            <android.support.v7.widget.AppCompatImageButton
                                android:id="@+id/ymwPrevImgBtn"
                                android:src="@drawable/ic_arrow_back"
                                android:background="@android:color/transparent"
                                app:layout_constraintStart_toStartOf="parent"
                                app:layout_constraintDimensionRatio="1:1"
                                android:layout_width="0dp"
                                android:layout_height="match_parent"/>-->
            <android.support.v7.widget.AppCompatTextView
                    android:id="@+id/ymwTxtView"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintEnd_toEndOf="parent"
                    android:gravity="center"
                    android:textColor="@color/black"
                    android:textSize="20sp"
                    android:layout_width="0dp"
                    android:layout_height="match_parent"/>
            <!--            <android.support.v7.widget.AppCompatImageButton
                                android:id="@+id/ymwNextImgBtn"
                                android:src="@drawable/ic_arrow_forward"
                                android:background="@android:color/transparent"
                                app:layout_constraintEnd_toEndOf="parent"
                                app:layout_constraintDimensionRatio="1:1"
                                android:layout_width="0dp"
                                android:layout_height="match_parent"/>-->
        </android.support.constraint.ConstraintLayout>
        <android.support.constraint.ConstraintLayout
                android:background="@color/lgt_gray"
                android:id="@+id/daysLayout"
                app:layout_constraintTop_toBottomOf="@+id/ymwLayout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content">
            <android.support.v7.widget.AppCompatTextView
                    android:text="@string/txt_sun"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintDimensionRatio="2:1"
                    app:layout_constraintStart_toStartOf="parent"
                    app:layout_constraintEnd_toStartOf="@+id/monTxtView"
                    android:id="@+id/sunTxtView"
                    style="@style/days_style"/>
            <android.support.v7.widget.AppCompatTextView
                    android:text="@string/txt_mon"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintDimensionRatio="2:1"
                    app:layout_constraintStart_toEndOf="@+id/sunTxtView"
                    app:layout_constraintEnd_toStartOf="@+id/tueTxtView"
                    android:id="@+id/monTxtView"
                    style="@style/days_style"/>
            <android.support.v7.widget.AppCompatTextView
                    android:text="@string/txt_tue"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintDimensionRatio="2:1"
                    app:layout_constraintStart_toEndOf="@+id/monTxtView"
                    app:layout_constraintEnd_toStartOf="@+id/wedTxtView"
                    android:id="@+id/tueTxtView"
                    style="@style/days_style"/>
            <android.support.v7.widget.AppCompatTextView
                    android:text="@string/txt_wed"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintDimensionRatio="2:1"
                    app:layout_constraintStart_toEndOf="@+id/tueTxtView"
                    app:layout_constraintEnd_toStartOf="@+id/thuTxtView"
                    android:id="@+id/wedTxtView"
                    style="@style/days_style"/>
            <android.support.v7.widget.AppCompatTextView
                    android:text="@string/txt_thu"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintDimensionRatio="2:1"
                    app:layout_constraintStart_toEndOf="@+id/wedTxtView"
                    app:layout_constraintEnd_toStartOf="@+id/friTxtView"
                    android:id="@+id/thuTxtView"
                    style="@style/days_style"/>
            <android.support.v7.widget.AppCompatTextView
                    android:text="@string/txt_fri"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintDimensionRatio="2:1"
                    app:layout_constraintStart_toEndOf="@+id/thuTxtView"
                    app:layout_constraintEnd_toStartOf="@+id/satTxtView"
                    android:id="@+id/friTxtView"
                    style="@style/days_style"/>
            <android.support.v7.widget.AppCompatTextView
                    android:text="@string/txt_sat"
                    app:layout_constraintTop_toTopOf="parent"
                    app:layout_constraintDimensionRatio="2:1"
                    app:layout_constraintStart_toEndOf="@+id/friTxtView"
                    app:layout_constraintEnd_toEndOf="parent"
                    android:id="@+id/satTxtView"
                    style="@style/days_style"/>

        </android.support.constraint.ConstraintLayout>
        <android.support.v7.widget.RecyclerView
                android:background="@color/lgt_gray"
                app:layout_constraintTop_toBottomOf="@+id/daysLayout"
                android:id="@+id/daysRecyclerView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
    </android.support.constraint.ConstraintLayout>
</layout>

주석처리된 버튼들은 좌우 스크롤 말고 뒤로가기 앞으로가기 버튼으로

날짜를 이동하고 싶을 때 주석을 풀어서 사용하면 됩니다.

 

2. item_day.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools">



    <android.support.constraint.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        <android.support.v7.widget.AppCompatTextView
                tools:text="1"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintDimensionRatio="1:1"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toStartOf="@+id/monTxtView"
                android:id="@+id/sunTxtView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:gravity="center"
                android:textSize="16sp"
                android:textColor="@android:color/black"/>
        <android.support.v7.widget.AppCompatTextView
                tools:text="2"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintDimensionRatio="1:1"
                app:layout_constraintStart_toEndOf="@+id/sunTxtView"
                app:layout_constraintEnd_toStartOf="@+id/tueTxtView"
                android:id="@+id/monTxtView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:gravity="center"
                android:textSize="16sp"
                android:textColor="@android:color/black"/>
        <android.support.v7.widget.AppCompatTextView
                tools:text="3"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintDimensionRatio="1:1"
                app:layout_constraintStart_toEndOf="@+id/monTxtView"
                app:layout_constraintEnd_toStartOf="@+id/wedTxtView"
                android:id="@+id/tueTxtView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:gravity="center"
                android:textSize="16sp"
                android:textColor="@android:color/black"/>
        <android.support.v7.widget.AppCompatTextView
                tools:text="4"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintDimensionRatio="1:1"
                app:layout_constraintStart_toEndOf="@+id/tueTxtView"
                app:layout_constraintEnd_toStartOf="@+id/thuTxtView"
                android:id="@+id/wedTxtView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:gravity="center"
                android:textSize="16sp"
                android:textColor="@android:color/black"/>
        <android.support.v7.widget.AppCompatTextView
                tools:text="5"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintDimensionRatio="1:1"
                app:layout_constraintStart_toEndOf="@+id/wedTxtView"
                app:layout_constraintEnd_toStartOf="@+id/friTxtView"
                android:id="@+id/thuTxtView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:gravity="center"
                android:textSize="16sp"
                android:textColor="@android:color/black"/>
        <android.support.v7.widget.AppCompatTextView
                tools:text="6"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintDimensionRatio="1:1"
                app:layout_constraintStart_toEndOf="@+id/thuTxtView"
                app:layout_constraintEnd_toStartOf="@+id/satTxtView"
                android:id="@+id/friTxtView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:gravity="center"
                android:textSize="16sp"
                android:textColor="@android:color/black"/>
        <android.support.v7.widget.AppCompatTextView
                tools:text="7"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintDimensionRatio="1:1"
                app:layout_constraintStart_toEndOf="@+id/friTxtView"
                app:layout_constraintEnd_toEndOf="parent"
                android:id="@+id/satTxtView"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:gravity="center"
                android:textSize="16sp"
                android:textColor="@android:color/black"/>
    </android.support.constraint.ConstraintLayout>
</layout>

 

DTO

1. Day

package al.tong.mon.weekcalendar

data class Day(var year : String, var month : String, var day : String)

2. Week

package al.tong.mon.weekcalendar

data class Week(var day1 : Day, var day2 : Day, var day3 : Day, var day4 : Day, var day5 : Day, var day6 : Day, var day7 : Day)

 

[ 광고 보고 가시죠! ]


 


[ 감사합니다! ]

 

 

Adapter

MainAdapter

package al.tong.mon.weekcalendar

import al.tong.mon.weekcalendar.databinding.ItemDayBinding
import android.app.Activity
import android.content.Context
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import java.util.*

class MainAdapter() :
RecyclerView.Adapter<MainAdapter.MainViewHolder>() {


constructor(activity: Activity, weeks: Vector<Week>, today: String, startDay: String) : this() {
	this.activity = activity
	this.weeks = weeks
	this.today = today
	this.startDay = startDay
	this.iToday = today.replace("-","").toInt()
	this.iStartDay = startDay.replace("-", "").toInt()
	this.context = activity.applicationContext
}


private lateinit var activity : Activity
private lateinit var weeks : Vector<Week>
private lateinit var context : Context

private lateinit var today : String
private lateinit var startDay: String
private var iToday: Int = 0
private var iStartDay: Int = 0

private lateinit var txtViews: Array<TextView>

override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): MainViewHolder{
	val binding = ItemDayBinding.inflate(LayoutInflater.from(context), viewGroup, false)
	
	return MainViewHolder(binding)
}


override fun onBindViewHolder(viewHolder: MainViewHolder, position: Int) {
	val binding = viewHolder.binding
	val week = weeks[position]
	txtViews = arrayOf(
	binding.sunTxtView,
	binding.monTxtView,
	binding.tueTxtView,
	binding.wedTxtView,
	binding.thuTxtView,
	binding.friTxtView,
	binding.satTxtView
)

binding.sunTxtView.text = week.day1.day
binding.monTxtView.text = week.day2.day
binding.tueTxtView.text = week.day3.day
binding.wedTxtView.text = week.day4.day
binding.thuTxtView.text = week.day5.day
binding.friTxtView.text = week.day6.day
binding.satTxtView.text = week.day7.day

//오늘 날짜를 크기를 크게
for(i in 0 until txtViews.size) {
val today = todays(position, i)
if (today == this.today) {
txtViews[i].scaleX = 1.75f
txtViews[i].scaleY = 1.75f
} else {
txtViews[i].scaleX = 1.0f
txtViews[i].scaleY = 1.0f
}

}
}

override fun getItemCount(): Int {
return weeks.size
}

class MainViewHolder : RecyclerView.ViewHolder {

var binding: ItemDayBinding

constructor(binding: ItemDayBinding) : super(binding.root) {
this.binding = binding
}

}

fun todays(pos1 : Int, pos2 : Int) : String {
val week = weeks[pos1]
var day: Day? = null
when(pos2) {
0 -> {
day = week.day1
}
1 -> {
day = week.day2
}
2 -> {
day = week.day3
}
3 -> {
day = week.day4
}
4 -> {
day = week.day5
}
5 -> {
day = week.day6
}
6 -> {
day = week.day7
}
}
return "${day!!.year}-${day.month}-${day.day}"
}

}

 

Activity

MainActivity

package al.tong.mon.weekcalendar


import al.tong.mon.weekcalendar.databinding.ActivityMainBinding
import android.databinding.DataBindingUtil
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.PagerSnapHelper
import android.support.v7.widget.RecyclerView
import android.util.Log
import java.text.SimpleDateFormat
import java.util.*

class MainActivity : AppCompatActivity() {

// lateinit var
private lateinit var binding: ActivityMainBinding
private lateinit var mainAdapter: MainAdapter
private lateinit var linearLayoutManager: LinearLayoutManager


private lateinit var mStrWeek: String

private var mYear: Int = 0
private var mMonth: Int = 0
private var mDay: Int = 0
private var mDayNum: Int = 0
private var mWeek: Int = 0
private var mCurPos: Int = 0
private var mStartDayNum: Int = 0

private lateinit var weeks: Vector<Week>

private var mEnd = 0


// init
private var mCalendar = GregorianCalendar(Locale.KOREA)
private var dayFormat = SimpleDateFormat("dd", Locale.KOREA)
private var monthFormat = SimpleDateFormat("MM", Locale.KOREA)
private var yearFormat = SimpleDateFormat("yyyy", Locale.KOREA)

var cdf = SimpleDateFormat("yyyy-MM-dd", Locale.KOREAN)


override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
val date = Date()
setDays(date)
}


private fun setDays(date: Date) {
val today = cdf.format(date)
val startDate = "2018-12-10"
mEnd = today.replace("-", "").toInt()
initCalendar(startDate, today)

}

private fun calcDateBetweenEndAndStart(end: String, start: String): Int {
val endDate = cdf.parse(end)
val startDate = cdf.parse(start)
val ymd = (start.split("-"))
val mCal = GregorianCalendar()
mCal.set(ymd[0].toInt(), ymd[1].toInt() + 1, ymd[2].toInt())
mStartDayNum = mCal.get(Calendar.DAY_OF_WEEK)
val diff = endDate.time - startDate.time
val diffDays = diff / (24 * 60 * 60 * 1000)
Log.e("날짜차이", diffDays.toString())
return diffDays.toInt() + 1
}

private fun initCalendar(startDate: String, today: String) {
Log.e("startDate", startDate)
Log.e("today", today)
val diff = calcDateBetweenEndAndStart(today, startDate)
linearLayoutManager = LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false)
binding.daysRecyclerView.layoutManager = linearLayoutManager
val snapHelper = PagerSnapHelper()
snapHelper.attachToRecyclerView(binding.daysRecyclerView)
mYear = mCalendar.get(Calendar.YEAR)
mMonth = mCalendar.get(Calendar.MONTH) + 1
mDay = mCalendar.get(Calendar.DAY_OF_MONTH)
mWeek = mCalendar.get(Calendar.WEEK_OF_MONTH)
mDayNum = mCalendar.get(Calendar.DAY_OF_WEEK)
mStrWeek = getStrWeek(mWeek)
mCalendar.set(mYear, mMonth, mDay)
val thisWeek = "${mYear}년 ${mMonth}월 $mStrWeek"
binding.ymwTxtView.text = thisWeek
val days = Vector<Day>()
val calendar = Calendar.getInstance()
for (i in -((mStartDayNum) + diff)..(7 - mDayNum)) {
calendar.set(mYear, mMonth - 1, mDay + i)
val date1 = calendar.time
days.add(
Day(
yearFormat.format(date1),
monthFormat.format(date1),
dayFormat.format(date1)
)
)
}
weeks = Vector()
for (i in 0 until (days.size / 7)) {
weeks.add(
Week(
days[(7 * i)],
days[(7 * i) + 1],
days[(7 * i) + 2],
days[(7 * i) + 3],
days[(7 * i) + 4],
days[(7 * i) + 5],
days[(7 * i) + 6]
)
)
}

mCurPos = weeks.size - 1
mainAdapter = MainAdapter(this, weeks, today, startDate)
binding.daysRecyclerView.adapter = mainAdapter
binding.daysRecyclerView.scrollToPosition(mCurPos)
mainAdapter.notifyDataSetChanged()
binding.daysRecyclerView.addOnScrollListener(scrollListener)

val dayss = Vector<Day>()

dayss.add(weeks[mCurPos].day1)
dayss.add(weeks[mCurPos].day2)
dayss.add(weeks[mCurPos].day3)
dayss.add(weeks[mCurPos].day4)
dayss.add(weeks[mCurPos].day5)
dayss.add(weeks[mCurPos].day6)
dayss.add(weeks[mCurPos].day7)
}

private fun getStrWeek(intWeek: Int): String {
val strWeek: String
when (intWeek) {
1 -> {
strWeek = "첫째주"
}
2 -> {
strWeek = "둘째주"
}
3 -> {
strWeek = "셋째주"
}
4 -> {
strWeek = "넷째주"
}
5 -> {
strWeek = "다섯째주"
}
else -> {
strWeek = ""
}
}
return strWeek
}


private var scrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
Log.e("newState ", "$newState")
if (newState == 0) {
mCurPos = linearLayoutManager.findFirstVisibleItemPosition()
Log.e("mCurPos", "$mCurPos")
val curWeek = mainAdapter.todays(mCurPos, 0)
val week = curWeek.split("-")
mCalendar.set(week[0].toInt(), week[1].toInt(), week[2].toInt())
mWeek = mCalendar.get(Calendar.WEEK_OF_MONTH)
mStrWeek = getStrWeek(mWeek)
val thisWeek = "${week[0].toInt()}년 ${week[1].toInt()}월 $mStrWeek"
binding.ymwTxtView.text = thisWeek
val dayss = Vector<Day>()

dayss.add(weeks[mCurPos].day1)
dayss.add(weeks[mCurPos].day2)
dayss.add(weeks[mCurPos].day3)
dayss.add(weeks[mCurPos].day4)
dayss.add(weeks[mCurPos].day5)
dayss.add(weeks[mCurPos].day6)
dayss.add(weeks[mCurPos].day7)
}
}

override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
}
}


}

 

이 코드들을 그대로 가져다 쓰면 주간 달력이 완성됩니다.

참고 하실 점들은 주간 달력이라는 점과

나오는 날짜를 오늘이 있는 주까지만 나오고

시작 날짜는 따로 설정해 줘야합니다.

MainActivity에서 setDays() 메소드를 보면

val startDate= "2018-12-10" 이 시작 날짜입니다.

 

실행 영상.

 

반응형