반응형
공감 및 댓글은 포스팅 하는데 아주아주 큰 힘이 됩니다!! 포스팅 내용이 찾아주신 분들께 도움이 되길 바라며 더 깔끔하고 좋은 포스팅을 만들어 나가겠습니다^^
|
안드로이드 주간 달력을 만들어 보았습니다.
기존에는 잘 나와있는 라이브러리를 썼었는데, 디자인을 수정하는데 있어서
약간의 불편함이 있어서 그냥 만들어보자 해서 만들어 봤습니다.
물론 라이브러리로 만든 건 아닙니다 ㅎㅎ
년 월 일이 나오는 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" 이 시작 날짜입니다.
실행 영상.
반응형