Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature/calendar2] 커스텀뷰 캘린더 #7

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
10 changes: 0 additions & 10 deletions .idea/runConfigurations.xml

This file was deleted.

38 changes: 19 additions & 19 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

android {
compileSdkVersion 30
compileSdkVersion 31
buildToolsVersion "30.0.3"

defaultConfig {
Expand All @@ -25,39 +25,39 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility(JavaVersion.VERSION_11)
targetCompatibility(JavaVersion.VERSION_11)
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = JavaVersion.VERSION_11
}
buildFeatures {
viewBinding = true
viewBinding true
}
}

dependencies {

implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.5.0'
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
implementation 'com.github.bumptech.glide:glide:4.11.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02'
implementation 'androidx.core:core-ktx:1.6.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0"
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-rc01'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 벌써 rc 나왔구나 코루틴 사용하기 더 편해지겠누

implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.1'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
def activity_version = "1.2.0"
def fragment_version = "1.3.0"
def activity_version = "1.3.1"
def fragment_version = "1.3.6"
implementation "androidx.activity:activity-ktx:$activity_version"
implementation "androidx.fragment:fragment-ktx:$fragment_version"
}
7 changes: 6 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,17 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.CatchMeSample">
<activity android:name="com.teamcatchme.calendar.CalendarActivity">
<activity
android:name="com.teamcatchme.calendar_customview.CustomCalendarActivity"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="com.teamcatchme.calendar.CalendarActivity">

</activity>
<activity android:name="com.teamcatchme.add_action_seojin.AddActionActivity">

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.teamcatchme.calendar_customview

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import android.view.View
import androidx.core.content.res.ResourcesCompat
import com.teamcatchme.catchmesample.R

class CalendarItemView @JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
private val date: Int? = null,
private val catchuList: Array<Int> = arrayOf(),
private val isPrevious: Boolean = false
) :
Comment on lines +11 to +19
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
class CalendarItemView @JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
private val date: Int? = null,
private val catchuList: Array<Int> = arrayOf(),
private val isPrevious: Boolean = false
) :
class CalendarItemView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
private val date: Int? = null,
private val catchuList: Array<Int> = arrayOf(),
private val isPrevious: Boolean = false
) : View(context, attrs, defStyleAttr) {

우선 생성자 형식은 저런데 뷰의 생성자에 저런 인자들이 들어가도 되나 나도 자세히 몰라서 확인해봐야할 듯

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오키 일단 해보고 우리 리얼 레포에 PR날리기 전까지 나도 확인해보겠음!!
안 돌아가진 않는데 위험할 수는 있을 것 같아

View(context, attrs, defStyleAttr) {
private var paint: Paint = Paint()

private fun drawDateRect(canvas: Canvas, date: Int) {
paint.textSize = 36f
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

실제에서는 이건 dp로 맞춰줘야할 것 같습니다.

if (isPrevious) paint.color = Color.GRAY
canvas.drawText(
date.toString(),
(width / 2).toFloat(),
((height / 2) - ((paint.descent() + paint.ascent()) / 2)),
paint
)
}

private fun drawDateWithCatchuRect(canvas: Canvas, date: Int, catchuList: Array<Int>) {
paint.textSize = 30f
paint.color = Color.GRAY
val contextResources = context.resources
val catchuDrawable =
ResourcesCompat.getDrawable(contextResources, R.drawable.ic_cachu1, null);
runCatching {
val catchuBitmap = catchuDrawable?.toBitmap()
canvas.drawBitmap(
requireNotNull(catchuBitmap),
(width / 2 - catchuBitmap.width / 2).toFloat(),
0f,
null
)
canvas.drawText(
date.toString(),
(width / 2).toFloat(),
(catchuBitmap.height + 28).toFloat(),
paint
)
}.onFailure { Log.e("error", it.toString()) }

// 누르면 프라그먼트 뿅 하게 리스너 추가하기
}

override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
paint.textAlign = Paint.Align.CENTER
if (canvas == null) return;
date?.run {
if (catchuList.isNotEmpty()) drawDateWithCatchuRect(canvas, this, catchuList)
else drawDateRect(canvas, this)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.teamcatchme.calendar_customview

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.core.view.children
import java.util.*

class CalendarView @JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : ViewGroup(context, attrs, defStyleAttr) {
fun drawCalendar(dateObject: Date) {
val dateCalendar = Calendar.getInstance()
dateCalendar.time = dateObject
dateCalendar.set(Calendar.DATE, 1)
val year = dateCalendar.get(Calendar.YEAR)
val month = dateCalendar.get(Calendar.MONTH) + 1
val firstDayOfMonth = dateCalendar.get(Calendar.DAY_OF_WEEK) - 1
val lastDateOfMonth = dateCalendar.getActualMaximum(Calendar.DATE)
Comment on lines +23 to +24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

변수명 굳

dateCalendar.set(Calendar.MONTH, month - 2)
val lastDateOfLastMonth = dateCalendar.getActualMaximum(Calendar.DATE)
if (firstDayOfMonth != 6) {
((lastDateOfLastMonth - firstDayOfMonth)..lastDateOfLastMonth).forEach { blank ->
addView(CalendarItemView(context = context, date = blank, isPrevious = true))
}
}
(1..lastDateOfMonth).forEach { date ->
if (date % 2 == 0) addView(
CalendarItemView(
context = context,
date = date,
catchuList = arrayOf(1, 2, 3)
)
)
else addView(CalendarItemView(context = context, date = date))
}
}

override fun onLayout(p0: Boolean, p1: Int, p2: Int, p3: Int, p4: Int) {
val iWidth = (width / 7).toFloat()
val iHeight = (width / 7).toFloat()
var index = 0
children.forEach { view ->
val left = (index % 7) * iWidth
val top = (index / 7) * iHeight
view.layout(left.toInt(), top.toInt(), (left + iWidth).toInt(), (top + iHeight).toInt())
index++
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.teamcatchme.calendar_customview

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.teamcatchme.catchmesample.R
import com.teamcatchme.catchmesample.databinding.ActivityCustomCalendarBinding

class CustomCalendarActivity : AppCompatActivity() {
lateinit var binding: ActivityCustomCalendarBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCustomCalendarBinding.inflate(layoutInflater)
setContentView(binding.root)
initCalendar()
}

private fun initCalendar() {
val calendarAdapter = CustomCalendarAdapter(this)
binding.viewpagerCustomCalendar.apply {
adapter = calendarAdapter
setCurrentItem(CustomCalendarAdapter.START_POSITION, true)
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.teamcatchme.calendar_customview

import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import java.util.*

class CustomCalendarAdapter(fragmentActivity: FragmentActivity) :
FragmentStateAdapter(fragmentActivity) {

private var startTime: Calendar = Calendar.getInstance()

override fun getItemCount(): Int = Int.MAX_VALUE

override fun createFragment(position: Int): Fragment {
val millsId = getItemId(position)
return CustomCalendarFragment.newInstance(millsId)
}

override fun getItemId(position: Int): Long {
val start = startTime.clone() as Calendar
start.add(Calendar.MONTH, position - START_POSITION)
return start.timeInMillis
}

companion object {
const val START_POSITION = Int.MAX_VALUE / 2
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.teamcatchme.calendar_customview

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.teamcatchme.catchmesample.databinding.FragmentCustomCalendarBinding
import java.util.*
import kotlin.properties.Delegates

class CustomCalendarFragment : Fragment() {

companion object {
private var MILLS_ID: String = "MILLS_ID"
private var millsId: Long = 0L

fun newInstance(millsId: Long): CustomCalendarFragment {
val fragment = CustomCalendarFragment()
val args = Bundle()
args.putLong(MILLS_ID, millsId)
fragment.arguments = args
Comment on lines +20 to +22
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
val args = Bundle()
args.putLong(MILLS_ID, millsId)
fragment.arguments = args
fragment.arguments = Bundle().also { putLong(MILLS_ID, millsId) }

3줄을 1줄로


return fragment
}
}

private var _binding: FragmentCustomCalendarBinding? = null
private val binding: FragmentCustomCalendarBinding
get() = requireNotNull(_binding)

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentCustomCalendarBinding.inflate(inflater, container, false)
arguments?.let {
millsId = it.getLong(MILLS_ID)
}
Comment on lines +38 to +40
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍🏻

initView()
return binding.root
}

private fun initView() {
val date = Date(millsId)
binding.text.text = date.toString()
binding.calendarView.drawCalendar(date)
}

override fun onDestroyView() {
super.onDestroyView()
_binding = null
}

}
23 changes: 23 additions & 0 deletions app/src/main/java/com/teamcatchme/calendar_customview/utils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.teamcatchme.calendar_customview

import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable


fun Drawable.toBitmap(): Bitmap? {
if (this is BitmapDrawable) {
return this.bitmap
}
val bitmap =
Bitmap.createBitmap(
this.intrinsicWidth,
this.intrinsicHeight,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
this.setBounds(0, 0, canvas.getWidth(), canvas.getHeight())
this.draw(canvas)
return bitmap
}
14 changes: 14 additions & 0 deletions app/src/main/res/layout/activity_custom_calendar.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.teamcatchme.calendar_customview.CustomCalendarActivity">

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager_custom_calendar"
android:layout_width="match_parent"
android:layout_height="match_parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
Loading