diff --git a/Heather/.gitignore b/Heather/.gitignore
index e43b0f98..263e24c9 100644
--- a/Heather/.gitignore
+++ b/Heather/.gitignore
@@ -1 +1,3 @@
.DS_Store
+.DS_Store
+../.DS_Store
diff --git a/Heather/FLOClone/.gitignore b/Heather/FLOClone/.gitignore
new file mode 100644
index 00000000..aa724b77
--- /dev/null
+++ b/Heather/FLOClone/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/Heather/FLOClone/.idea/.gitignore b/Heather/FLOClone/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/Heather/FLOClone/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/Heather/FLOClone/.idea/appInsightsSettings.xml b/Heather/FLOClone/.idea/appInsightsSettings.xml
new file mode 100644
index 00000000..371f2e29
--- /dev/null
+++ b/Heather/FLOClone/.idea/appInsightsSettings.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/.idea/compiler.xml b/Heather/FLOClone/.idea/compiler.xml
new file mode 100644
index 00000000..b589d56e
--- /dev/null
+++ b/Heather/FLOClone/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/.idea/deploymentTargetSelector.xml b/Heather/FLOClone/.idea/deploymentTargetSelector.xml
new file mode 100644
index 00000000..b268ef36
--- /dev/null
+++ b/Heather/FLOClone/.idea/deploymentTargetSelector.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/.idea/gradle.xml b/Heather/FLOClone/.idea/gradle.xml
new file mode 100644
index 00000000..0897082f
--- /dev/null
+++ b/Heather/FLOClone/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/.idea/kotlinc.xml b/Heather/FLOClone/.idea/kotlinc.xml
new file mode 100644
index 00000000..fdf8d994
--- /dev/null
+++ b/Heather/FLOClone/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/.idea/migrations.xml b/Heather/FLOClone/.idea/migrations.xml
new file mode 100644
index 00000000..f8051a6f
--- /dev/null
+++ b/Heather/FLOClone/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/.idea/misc.xml b/Heather/FLOClone/.idea/misc.xml
new file mode 100644
index 00000000..8978d23d
--- /dev/null
+++ b/Heather/FLOClone/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/.idea/vcs.xml b/Heather/FLOClone/.idea/vcs.xml
new file mode 100644
index 00000000..64713b81
--- /dev/null
+++ b/Heather/FLOClone/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/.gitignore b/Heather/FLOClone/app/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/Heather/FLOClone/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/Heather/FLOClone/app/build.gradle.kts b/Heather/FLOClone/app/build.gradle.kts
new file mode 100644
index 00000000..0bd118a4
--- /dev/null
+++ b/Heather/FLOClone/app/build.gradle.kts
@@ -0,0 +1,54 @@
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin.android)
+}
+
+android {
+ namespace = "com.example.floclone"
+ compileSdk = 34
+
+ defaultConfig {
+ applicationId = "com.example.floclone"
+ minSdk = 34
+ targetSdk = 34
+ versionCode = 1
+ versionName = "1.0"
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+ buildFeatures {
+ viewBinding = true
+ }
+}
+
+dependencies {
+
+ implementation(libs.androidx.core.ktx)
+ implementation(libs.androidx.appcompat)
+ implementation(libs.material)
+ implementation(libs.androidx.activity)
+ implementation(libs.androidx.constraintlayout)
+ implementation("me.relex:circleindicator:2.1.6")
+ implementation("com.google.code.gson:gson:2.11.0")
+ implementation("androidx.core:core-splashscreen:1.0.0")
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.androidx.junit)
+ androidTestImplementation(libs.androidx.espresso.core)
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/proguard-rules.pro b/Heather/FLOClone/app/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/Heather/FLOClone/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/androidTest/java/com/example/floclone/ExampleInstrumentedTest.kt b/Heather/FLOClone/app/src/androidTest/java/com/example/floclone/ExampleInstrumentedTest.kt
new file mode 100644
index 00000000..35edf7c6
--- /dev/null
+++ b/Heather/FLOClone/app/src/androidTest/java/com/example/floclone/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.example.floclone
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.example.floclone", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/AndroidManifest.xml b/Heather/FLOClone/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..d99c14eb
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/AndroidManifest.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/Album.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/Album.kt
new file mode 100644
index 00000000..dd89f1d3
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/Album.kt
@@ -0,0 +1,10 @@
+package com.example.floclone
+
+import java.util.*
+
+data class Album(
+ var title: String? = "",
+ var singer: String? = "",
+ var coverImg: Int? = null,
+ var songs: ArrayList? = null
+)
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/AlbumFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/AlbumFragment.kt
new file mode 100644
index 00000000..fd26805c
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/AlbumFragment.kt
@@ -0,0 +1,53 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.google.android.material.tabs.TabLayoutMediator
+import com.example.floclone.databinding.FragmentAlbumBinding
+import com.google.gson.Gson
+
+class AlbumFragment : Fragment() {
+
+ lateinit var binding: FragmentAlbumBinding
+ private var gson: Gson = Gson()
+
+ private val information = arrayListOf("수록곡", "상세정보", "영상")
+
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentAlbumBinding.inflate(inflater, container, false)
+
+ // 뒤로가기 버튼
+ binding.albumBackIv.setOnClickListener {
+ (context as MainActivity).supportFragmentManager.beginTransaction()
+ .replace(R.id.main_frm, HomeFragment()).commitAllowingStateLoss()
+ }
+
+ val albumJson = arguments?.getString("album")
+ val album = gson.fromJson(albumJson, Album::class.java)
+ setInit(album)
+
+ // ViewPager랑 TabLayout 연결
+ val albumAdapter = AlbumVPAdapter(this)
+ binding.albumContentVp.adapter = albumAdapter
+ TabLayoutMediator(binding.albumContentTb, binding.albumContentVp) { tab, position ->
+ tab.text = information[position]
+ }.attach()
+
+ return binding.root
+ }
+
+ private fun setInit(album: Album) {
+ binding.albumAlbumIv.setImageResource(album.coverImg!!)
+ binding.albumMusicTitleTv.text = album.title.toString()
+ binding.albumSingerNameTv.text = album.singer.toString()
+ }
+
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/AlbumRVAdapter.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/AlbumRVAdapter.kt
new file mode 100644
index 00000000..f4c7091d
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/AlbumRVAdapter.kt
@@ -0,0 +1,68 @@
+package com.example.floclone
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.example.floclone.databinding.ItemAlbumBinding
+
+class AlbumRVAdapter(private val albumList: ArrayList) :
+ RecyclerView.Adapter(){
+
+ // 클릭 인터페이스 정의
+ interface MyItemClickListener{
+ fun onItemClick(album: Album)
+ fun onRemoveAlbum(position: Int)
+ fun onPlayAlbum(album: Album) // 오늘 발매 음악에서 재생 버튼 클릭 시 호출될 메서드
+ }
+
+ // 리스너 객체를 전달받는 함수랑 리스너 객체를 저장할 변수
+ private lateinit var mItemClickListener: MyItemClickListener
+
+ fun setMyItemClickListener(itemClickListener: MyItemClickListener){
+ mItemClickListener = itemClickListener
+ }
+
+ // 뷰홀더를 생성해줘야 할 때 호출되는 함수 => 아이템 뷰 객체를 만들어서 뷰홀더에 던져줌
+ override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): AlbumRVAdapter.ViewHolder {
+ val binding: ItemAlbumBinding = ItemAlbumBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
+
+ return ViewHolder(binding)
+ }
+
+ fun addItem(album: Album){
+ albumList.add(album)
+ notifyDataSetChanged()
+ }
+
+ fun removeItem(position: Int){
+ albumList.removeAt(position)
+ notifyDataSetChanged()
+ }
+
+ // 뷰홀더에 데이터를 바인딩해줘야 할 때마다 호출되는 함수 => 엄청나게 많이 호출
+ override fun onBindViewHolder(holder: AlbumRVAdapter.ViewHolder, position: Int) {
+ holder.bind(albumList[position])
+ holder.itemView.setOnClickListener { mItemClickListener.onItemClick(albumList[position]) }
+
+// holder.binding.itemAlbumTitleTv.setOnClickListener { mItemClickListener.onRemoveAlbum(position) } // 삭제 테스트
+ }
+
+ // 데이터 세트 크기를 알려주는 함수 => 리사이클러뷰가 마지막이 언제인지를 알게 됨
+ override fun getItemCount(): Int = albumList.size
+
+ // 뷰홀더
+ inner class ViewHolder(val binding: ItemAlbumBinding):
+ RecyclerView.ViewHolder(binding.root){
+
+ fun bind(album: Album){
+ binding.itemAlbumTitleTv.text = album.title
+ binding.itemAlbumSingerTv.text = album.singer
+ binding.itemAlbumCoverImgIv.setImageResource(album.coverImg!!)
+
+ // 재생 버튼 클릭 리스너 추가
+ binding.itemAlbumPlayImgIv.setOnClickListener {
+ mItemClickListener.onPlayAlbum(album)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/AlbumVPAdapter.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/AlbumVPAdapter.kt
new file mode 100644
index 00000000..abbeb44b
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/AlbumVPAdapter.kt
@@ -0,0 +1,16 @@
+package com.example.floclone
+
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+class AlbumVPAdapter(fragment:Fragment) : FragmentStateAdapter(fragment) {
+ override fun getItemCount(): Int = 3
+
+ override fun createFragment(position: Int): Fragment {
+ return when(position){
+ 0 -> SongFragment()
+ 1 -> DetailFragment()
+ else -> VideoFragment()
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/BannerFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/BannerFragment.kt
new file mode 100644
index 00000000..3f98830c
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/BannerFragment.kt
@@ -0,0 +1,23 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.floclone.databinding.FragmentBannerBinding
+
+class BannerFragment(val imgRes: Int) : Fragment() {
+
+ lateinit var binding : FragmentBannerBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentBannerBinding.inflate(inflater, container, false)
+ binding.bannerImageIv.setImageResource(imgRes) // 전달받은 imgRes 사용
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/BannerVPAdapter.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/BannerVPAdapter.kt
new file mode 100644
index 00000000..326d1728
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/BannerVPAdapter.kt
@@ -0,0 +1,18 @@
+package com.example.floclone
+
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+class BannerVPAdapter(fragment: Fragment) :FragmentStateAdapter(fragment) {
+
+ private val fragmentlist : ArrayList = ArrayList()
+
+ override fun getItemCount(): Int = fragmentlist.size
+
+ override fun createFragment(position: Int): Fragment = fragmentlist[position]
+
+ fun addFragment(fragment: Fragment) {
+ fragmentlist.add(fragment)
+ notifyItemInserted(fragmentlist.size-1)
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/DetailFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/DetailFragment.kt
new file mode 100644
index 00000000..a515a604
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/DetailFragment.kt
@@ -0,0 +1,24 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.floclone.databinding.FragmentDetailBinding
+
+class DetailFragment : Fragment() {
+
+ lateinit var binding: FragmentDetailBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentDetailBinding.inflate(inflater,container,false)
+
+ return binding.root
+ }
+
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/HomeFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/HomeFragment.kt
new file mode 100644
index 00000000..d23331d3
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/HomeFragment.kt
@@ -0,0 +1,168 @@
+package com.example.floclone
+
+import android.content.Context
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.viewpager2.widget.ViewPager2
+import com.example.floclone.databinding.FragmentHomeBinding
+import me.relex.circleindicator.CircleIndicator3
+import android.os.Handler
+import android.os.Looper
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.google.gson.Gson
+
+class HomeFragment : Fragment() {
+
+ lateinit var binding: FragmentHomeBinding
+ lateinit var handler: Handler
+ lateinit var runnable: Runnable
+ private var albumDatas = ArrayList()
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentHomeBinding.inflate(inflater, container, false)
+
+// binding.homeAlbumImgIv1.setOnClickListener {
+// (context as MainActivity).supportFragmentManager.beginTransaction()
+// .replace(R.id.main_frm, AlbumFragment()).commitAllowingStateLoss()
+// }
+
+ // 데이터 리스트 생성 더미 데이터
+// albumDatas.apply {
+// add(Album("Butter", "방탄소년단 (BTS)", R.drawable.img_album_exp))
+// add(Album("Lilac", "아이유 (IU)", R.drawable.img_album_exp2))
+// add(Album("Next Level", "에스파 (AESPA)", R.drawable.img_album_exp3))
+// add(Album("Boy with Luv", "방탄소년단 (BTS)", R.drawable.img_album_exp4))
+// add(Album("BBoom BBoom", "모모랜드 (MOMOLAND)", R.drawable.img_album_exp5))
+// add(Album("Weekend", "태연 (Tae Yeon)", R.drawable.img_album_exp6))
+// }
+
+ // 노래 목록이 있어야 그 중 첫 번째 곡을 재생할 수 있기 때문에 songs 배열 추가
+ albumDatas.apply {
+ add(Album("Butter", "방탄소년단 (BTS)", R.drawable.img_album_exp,
+ songs = arrayListOf(
+ Song("Butter", "방탄소년단 (BTS)", 0, 180, false, "butter"),
+ Song("Butter(Hotter Remix)", "방탄소년단 (BTS)", 0, 180, false, "butterHotter")
+ )
+ ))
+ add(Album("Lilac", "아이유 (IU)", R.drawable.img_album_exp2,
+ songs = arrayListOf(
+ Song("Lilac", "아이유 (IU)", 0, 180, false, "lilac"),
+ Song("Flu", "아이유 (IU)", 0, 180, false, "flu")
+ )
+ ))
+ add(Album("Next Level", "에스파 (AESPA)", R.drawable.img_album_exp3,
+ songs = arrayListOf(
+ Song("Next Level", "에스파 (AESPA)", 0, 180, false, "nextlevel"),
+ Song("Black Mamba", "에스파 (AESPA)", 0, 180, false, "blackmamba")
+ )
+ ))
+ add(Album("Boy with Luv", "방탄소년단 (BTS)", R.drawable.img_album_exp4,
+ songs = arrayListOf(
+ Song("Boy with Luv", "방탄소년단 (BTS)", 0, 180, false, "boywithluv"),
+ Song("Dynamite", "방탄소년단 (BTS)", 0, 180, false, "dynamite")
+ )
+ ))
+ add(Album("BBoom BBoom", "모모랜드 (MOMOLAND)", R.drawable.img_album_exp5,
+ songs = arrayListOf(
+ Song("BBoom BBoom", "모모랜드 (MOMOLAND)", 0, 180, false, "bboombboom"),
+ Song("BAAM", "모모랜드 (MOMOLAND)", 0, 180, false, "baam")
+ )
+ ))
+ add(Album("Weekend", "태연 (Tae Yeon)", R.drawable.img_album_exp6,
+ songs = arrayListOf(
+ Song("Weekend", "태연 (Tae Yeon)", 0, 180, false, "weekend"),
+ Song("Rain", "태연 (Tae Yeon)", 0, 180, false, "rain")
+ )
+ ))
+ }
+
+ // 레이아웃 매니저 설정
+ val albumRVAdapter = AlbumRVAdapter(albumDatas)
+ binding.homeTodayMusicAlbumRv.adapter = albumRVAdapter
+ binding.homeTodayMusicAlbumRv.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
+
+ albumRVAdapter.setMyItemClickListener(object: AlbumRVAdapter.MyItemClickListener {
+ override fun onItemClick(album: Album) {
+ changeAlbumFragment(album)
+ }
+
+ override fun onRemoveAlbum(position: Int) {
+ albumRVAdapter.removeItem(position)
+ }
+
+ override fun onPlayAlbum(album: Album) {
+ // 앨범의 첫 번째 곡 가져옴
+ album.songs?.let { songs ->
+ if (songs.isNotEmpty()) {
+ val firstSong = songs[0]
+
+ // SharedPreferences로 노래 정보 저장
+ val sharedPreferences = requireActivity().getSharedPreferences("song", Context.MODE_PRIVATE)
+ val editor = sharedPreferences.edit()
+
+ // Song 객체를 JSON으로 변환
+ val gson = Gson()
+ val songJson = gson.toJson(firstSong)
+
+ editor.putString("songData", songJson)
+ editor.apply()
+ }
+ }
+ }
+ })
+
+ // ViewPager 설정
+ val bannerAdapter = BannerVPAdapter(this)
+ bannerAdapter.addFragment(BannerFragment(R.drawable.img_home_viewpager_exp))
+ bannerAdapter.addFragment(BannerFragment(R.drawable.img_home_viewpager_exp2))
+ binding.homeBannerVp.adapter = bannerAdapter
+ binding.homeBannerVp.orientation = ViewPager2.ORIENTATION_HORIZONTAL
+
+ val panelAdpater = PanelVPAdapter(this)
+ panelAdpater.addFragment(PanelFragment(R.drawable.img_first_album_default))
+ panelAdpater.addFragment(PanelFragment(R.drawable.img_first_album_default))
+ binding.homePanelBackgroundVp.adapter = panelAdpater
+ binding.homePanelBackgroundVp.orientation = ViewPager2.ORIENTATION_HORIZONTAL
+
+ // Indicator 설정
+ val indicator: CircleIndicator3 = binding.homePanelIndicator
+ indicator.setViewPager(binding.homeBannerVp)
+
+ // 자동 슬라이드 구현
+ handler = Handler(Looper.getMainLooper())
+ runnable = object : Runnable {
+ override fun run() {
+ if (binding.homePanelBackgroundVp.currentItem == bannerAdapter.itemCount - 1) {
+ binding.homePanelBackgroundVp.currentItem = 0
+ } else {
+ binding.homePanelBackgroundVp.currentItem = binding.homePanelBackgroundVp.currentItem + 1
+ }
+ handler.postDelayed(this, 3000) // 3초마다 슬라이드
+ }
+ }
+ handler.postDelayed(runnable, 3000) // 최초 실행
+
+
+ return binding.root
+ }
+
+ private fun changeAlbumFragment(album: Album) {
+ (context as MainActivity).supportFragmentManager.beginTransaction()
+ .replace(R.id.main_frm, AlbumFragment().apply {
+ arguments = Bundle().apply {
+ val gson = Gson()
+ val albumJson = gson.toJson(album)
+ putString("album", albumJson)
+ }
+ })
+ .commitAllowingStateLoss()
+ }
+
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/LockFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/LockFragment.kt
new file mode 100644
index 00000000..8c328af6
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/LockFragment.kt
@@ -0,0 +1,59 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [LockFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class LockFragment : Fragment() {
+ // TODO: Rename and change types of parameters
+ private var param1: String? = null
+ private var param2: String? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ param1 = it.getString(ARG_PARAM1)
+ param2 = it.getString(ARG_PARAM2)
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_lock, container, false)
+ }
+
+ companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @param param1 Parameter 1.
+ * @param param2 Parameter 2.
+ * @return A new instance of fragment LockFragment.
+ */
+ // TODO: Rename and change types and number of parameters
+ @JvmStatic
+ fun newInstance(param1: String, param2: String) =
+ LockFragment().apply {
+ arguments = Bundle().apply {
+ putString(ARG_PARAM1, param1)
+ putString(ARG_PARAM2, param2)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/LockerFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/LockerFragment.kt
new file mode 100644
index 00000000..b7d0eb06
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/LockerFragment.kt
@@ -0,0 +1,31 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.floclone.databinding.FragmentLockerBinding
+import com.google.android.material.tabs.TabLayoutMediator
+
+
+class LockerFragment : Fragment() {
+ lateinit var binding: FragmentLockerBinding
+ private val information = arrayListOf("저장한곡", "음악파일")
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ binding = FragmentLockerBinding.inflate(inflater, container, false)
+
+ val lockerAdapter = LockerVPAdapter(this)
+ binding.lockerContentVp.adapter = lockerAdapter
+ TabLayoutMediator(binding.lockerContentTb, binding.lockerContentVp) { tab, position ->
+ tab.text = information[position]
+ }.attach()
+
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/LockerVPAdapter.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/LockerVPAdapter.kt
new file mode 100644
index 00000000..7493eac8
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/LockerVPAdapter.kt
@@ -0,0 +1,15 @@
+package com.example.floclone
+
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+class LockerVPAdapter (fragment : Fragment) : FragmentStateAdapter(fragment) {
+ override fun getItemCount(): Int = 2
+
+ override fun createFragment(position: Int): Fragment {
+ return when(position){
+ 0 -> SavedSongFragment()
+ else -> MusicFileFragment()
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/MainActivity.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/MainActivity.kt
new file mode 100644
index 00000000..bdc13afa
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/MainActivity.kt
@@ -0,0 +1,139 @@
+package com.example.floclone
+
+import android.content.Intent
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
+import com.example.floclone.databinding.ActivityMainBinding
+import com.google.gson.Gson
+
+
+class MainActivity : AppCompatActivity() {
+
+ lateinit var binding: ActivityMainBinding
+
+ private var song: Song = Song()
+ private var gson: Gson = Gson()
+
+ private val handler = Handler(Looper.getMainLooper())
+ private val updateSeekBar = object : Runnable {
+ override fun run() {
+ val sharedPreferences = getSharedPreferences("song", MODE_PRIVATE)
+ val songJson = sharedPreferences.getString("songData", null)
+
+ if (songJson != null) {
+ song = gson.fromJson(songJson, Song::class.java)
+ setMiniPlayer(song)
+ }
+
+ handler.postDelayed(this, 200) // 200ms마다 업데이트
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ handler.post(updateSeekBar)
+ }
+
+ override fun onPause() {
+ super.onPause()
+ handler.removeCallbacks(updateSeekBar)
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ Thread.sleep(3000)
+ installSplashScreen()
+
+ super.onCreate(savedInstanceState)
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ initBottomNavigation()
+
+ binding.mainPlayerCl.setOnClickListener {
+ val intent = Intent(this, SongActivity::class.java)
+ }
+
+ binding.mainPlayerCl.setOnClickListener {
+ val intent = Intent(this, SongActivity::class.java)
+ intent.putExtra("title", song.title)
+ intent.putExtra("singer", song.singer)
+ intent.putExtra("second", song.second)
+ intent.putExtra("playTime", song.playTime)
+ intent.putExtra("isPlaying", song.isPlaying)
+ intent.putExtra("music", song.music)
+ startActivity(intent)
+ }
+ }
+
+ private fun initBottomNavigation(){
+
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.main_frm, HomeFragment())
+ .commitAllowingStateLoss()
+
+ binding.mainBnv.setOnItemSelectedListener{ item ->
+ when (item.itemId) {
+
+ R.id.homeFragment -> {
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.main_frm, HomeFragment())
+ .commitAllowingStateLoss()
+ return@setOnItemSelectedListener true
+ }
+
+ R.id.lookFragment -> {
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.main_frm, LockFragment())
+ .commitAllowingStateLoss()
+ return@setOnItemSelectedListener true
+ }
+ R.id.searchFragment -> {
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.main_frm, SearchFragment())
+ .commitAllowingStateLoss()
+ return@setOnItemSelectedListener true
+ }
+ R.id.lockerFragment -> {
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.main_frm, LockerFragment())
+ .commitAllowingStateLoss()
+ return@setOnItemSelectedListener true
+ }
+ }
+ false
+ }
+ }
+
+ private fun setMiniPlayer(song : Song) {
+ binding.mainMiniplayerTitleTv.text = song.title
+ binding.mainMiniplayerSingerTv.text = song.singer
+
+ // SeekBar 최대값 설정
+ binding.mainMiniplayerProgressSb.max = song.playTime * 1000 // 노래 길이(밀리초 단위)
+
+ // progress 계산 수정
+ // 현재 재생 시간을 밀리초 단위로 SeekBar에 반영
+ binding.mainMiniplayerProgressSb.progress = song.second * 1000
+ }
+
+ override fun onStart() {
+ super.onStart()
+ val sharedPreferences = getSharedPreferences("song", MODE_PRIVATE)
+ // SharedPreferences 초기화
+ // sharedPreferences.edit().clear().apply()
+
+ val songJson = sharedPreferences.getString("songData", null)
+
+ song = if (songJson == null) {
+ Song("라일락", "아이유(IU)", 0,60, false, "music")
+ } else {
+ gson.fromJson(songJson, Song::class.java)
+ }
+
+ binding.mainMiniplayerProgressSb.max = song.playTime * 1000
+ setMiniPlayer(song)
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/MusicFileFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/MusicFileFragment.kt
new file mode 100644
index 00000000..cb0dcec7
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/MusicFileFragment.kt
@@ -0,0 +1,19 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.floclone.databinding.FragmentMusicFileBinding
+
+class MusicFileFragment: Fragment() {
+
+ lateinit var binding: FragmentMusicFileBinding
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ binding = FragmentMusicFileBinding.inflate(inflater, container, false)
+
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/PanelFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/PanelFragment.kt
new file mode 100644
index 00000000..fcb3a5ad
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/PanelFragment.kt
@@ -0,0 +1,26 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.floclone.databinding.FragmentPanelBinding
+
+class PanelFragment(val imgRes : Int) : Fragment() {
+ lateinit var binding : FragmentPanelBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentPanelBinding.inflate(inflater, container, false)
+ binding.pannelImageIv.setImageResource(imgRes)
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/PanelVPAdapter.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/PanelVPAdapter.kt
new file mode 100644
index 00000000..5d4df626
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/PanelVPAdapter.kt
@@ -0,0 +1,18 @@
+package com.example.floclone
+
+import androidx.fragment.app.Fragment
+import androidx.viewpager2.adapter.FragmentStateAdapter
+
+class PanelVPAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
+
+ private val fragmentList: ArrayList = ArrayList()
+
+ override fun getItemCount(): Int = fragmentList.size
+
+ override fun createFragment(position: Int): Fragment = fragmentList[position]
+
+ fun addFragment(fragment: Fragment) {
+ fragmentList.add(fragment)
+ notifyItemInserted(fragmentList.size - 1)
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/SavedSongFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/SavedSongFragment.kt
new file mode 100644
index 00000000..5b1ac329
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/SavedSongFragment.kt
@@ -0,0 +1,56 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.example.floclone.databinding.FragmentSavedSongBinding
+
+
+class SavedSongFragment : Fragment() {
+
+// private var albumDatas = ArrayList()
+ lateinit var binding : FragmentSavedSongBinding
+ private var songDatas = ArrayList()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentSavedSongBinding.inflate(inflater, container, false)
+
+ // 더미데이터 생성
+ songDatas.apply {
+ add(Song("Whiplash", "aespa", 0, 180, false, "whiplash", coverImg = R.drawable.img_album_exp7, isSwitchOn = false))
+ add(Song("APT.", "로제 (ROSÉ) & Bruno Mars", 0, 180, false, "apt", coverImg = R.drawable.img_album_exp8, isSwitchOn = false))
+ add(Song("HAPPY", "DAY6 (데이식스)", 0, 180, false, "happy", coverImg = R.drawable.img_album_exp9, isSwitchOn = false))
+ add(Song("POWER", "G-DRAGON", 0, 180, false, "power", coverImg = R.drawable.img_album_exp10, isSwitchOn = false))
+ add(Song("UP (KARINA Solo)", "aespa", 0, 180, false, "up", coverImg = R.drawable.img_album_exp11, isSwitchOn = false))
+ add(Song("Drowning", "WOODZ", 0, 180, false, "drowning", coverImg = R.drawable.img_album_exp12, isSwitchOn = false))
+ add(Song("내 이름 맑음", "QWER", 0, 180, false, "qwer", coverImg = R.drawable.img_album_exp13, isSwitchOn = false))
+ add(Song("Welcome to the show", "DAY6 (데이식스)", 0, 180, false, "welcomeToTheShow", coverImg = R.drawable.img_album_exp9, isSwitchOn = false))
+ }
+
+ val songRVAdapter = SongRVAdapter(songDatas)
+ binding.savedSongRv.apply {
+ adapter = songRVAdapter
+ layoutManager = LinearLayoutManager(context)
+ }
+
+ // 클릭 리스너 설정
+ songRVAdapter.setMyItemClickListener(object: SongRVAdapter.MyItemClickListener {
+ override fun onRemoveSong(position: Int) {
+ songRVAdapter.removeSong(position)
+ }
+ })
+
+ return binding.root
+ }
+
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/SearchFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/SearchFragment.kt
new file mode 100644
index 00000000..bb69a016
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/SearchFragment.kt
@@ -0,0 +1,59 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [SearchFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class SearchFragment : Fragment() {
+ // TODO: Rename and change types of parameters
+ private var param1: String? = null
+ private var param2: String? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ param1 = it.getString(ARG_PARAM1)
+ param2 = it.getString(ARG_PARAM2)
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_search, container, false)
+ }
+
+ companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @param param1 Parameter 1.
+ * @param param2 Parameter 2.
+ * @return A new instance of fragment SearchFragment.
+ */
+ // TODO: Rename and change types and number of parameters
+ @JvmStatic
+ fun newInstance(param1: String, param2: String) =
+ SearchFragment().apply {
+ arguments = Bundle().apply {
+ putString(ARG_PARAM1, param1)
+ putString(ARG_PARAM2, param2)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/Song.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/Song.kt
new file mode 100644
index 00000000..c7bdfe6b
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/Song.kt
@@ -0,0 +1,12 @@
+package com.example.floclone
+
+data class Song(
+ val title : String = "",
+ val singer : String = "",
+ var second: Int = 0,
+ var playTime: Int = 0,
+ var isPlaying: Boolean = false,
+ var music: String = "",
+ var coverImg: Int? = null,
+ var isSwitchOn: Boolean = false // 스위치 상태를 저장할 변수
+)
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/SongActivity.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/SongActivity.kt
new file mode 100644
index 00000000..4578a187
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/SongActivity.kt
@@ -0,0 +1,249 @@
+package com.example.floclone
+
+import android.content.Intent
+import android.graphics.PorterDuff
+import android.media.MediaPlayer
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.util.Log
+import android.view.View
+import android.widget.SeekBar
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import com.example.floclone.databinding.ActivitySongBinding
+import com.google.gson.Gson
+import java.util.Timer
+import java.util.concurrent.TimeUnit
+
+class SongActivity : AppCompatActivity() {
+
+ lateinit var binding: ActivitySongBinding
+ lateinit var song: Song
+ lateinit var timer: Timer
+ private var mediaPlayer: MediaPlayer? = null
+ private var gson: Gson = Gson()
+
+ private var isRepeatActive = false
+ private var isRandomActive = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding = ActivitySongBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ initSong()
+ setPlayer(song)
+
+ binding.songDownIb.setOnClickListener {
+ finish()
+ }
+
+ binding.songMiniplayerIv.setOnClickListener {
+ setPlayerStatus(true)
+ }
+
+ binding.songPauseIv.setOnClickListener {
+ setPlayerStatus(false)
+ }
+
+ // 반복 재생 버튼 클릭 리스너 추가
+ binding.songRepeatIv.setOnClickListener {
+ isRepeatActive = !isRepeatActive
+ if (isRepeatActive) {
+ binding.songRepeatIv.setColorFilter(
+ ContextCompat.getColor(this, R.color.select_color),
+ PorterDuff.Mode.SRC_IN
+ )
+ } else {
+ binding.songRepeatIv.clearColorFilter()
+ }
+ }
+
+ // 랜덤 재생 버튼 클릭 리스너 추가
+ binding.songRandomIv.setOnClickListener {
+ isRandomActive = !isRandomActive
+ if (isRandomActive) {
+ binding.songRandomIv.setColorFilter(
+ ContextCompat.getColor(this, R.color.select_color),
+ PorterDuff.Mode.SRC_IN
+ )
+ } else {
+ binding.songRandomIv.clearColorFilter()
+ }
+ }
+ }
+
+ private fun initSong() {
+ if(intent.hasExtra("title") && intent.hasExtra("singer")){
+ song = Song(
+ intent.getStringExtra("title")!!,
+ intent.getStringExtra("singer")!!,
+ intent.getIntExtra("second",0),
+ intent.getIntExtra("playTime",0),
+ intent.getBooleanExtra("isPlaying",false),
+ intent.getStringExtra("music")!!
+ )
+ }
+
+ // MediaPlayer 초기화 및 저장된 위치로 이동
+ val music = resources.getIdentifier(song.music, "raw", this.packageName)
+ mediaPlayer = MediaPlayer.create(this, music)
+ mediaPlayer?.seekTo(song.second * 1000) // 밀리초 단위로 변환해서 이동
+
+ startTimer(song.second * 1000L) // 저장된 second 값을 밀리초로 변환하여 전달
+ }
+
+ private fun setPlayer(song: Song) {
+ binding.songMusicTitleTv.text = intent.getStringExtra("title")!!
+ binding.songSingerNameTv.text = intent.getStringExtra("singer")!!
+ binding.songStartTimeTv.text = String.format("%02d:%02d",song.second / 60, song.second % 60)
+ binding.songEndTimeTv.text = String.format("%02d:%02d",song.playTime / 60, song.playTime % 60)
+
+ // SeekBar 설정
+ binding.songProgressSb.max = song.playTime * 1000
+ binding.songProgressSb.progress = song.second * 1000
+
+// val music = resources.getIdentifier(song.music, "raw", this.packageName)
+// mediaPlayer = MediaPlayer.create(this, music)
+
+ // SeekBar 클릭 이벤트 리스너 설정
+ binding.songProgressSb.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+ override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
+ if (fromUser) {
+ mediaPlayer?.seekTo(progress)
+ timer.mills = progress.toLong()
+ timer.second = progress / 1000
+ }
+ binding.songStartTimeTv.text = String.format("%02d:%02d",
+ TimeUnit.MILLISECONDS.toMinutes(progress.toLong()),
+ TimeUnit.MILLISECONDS.toSeconds(progress.toLong()) % 60)
+ }
+ override fun onStartTrackingTouch(seekBar: SeekBar?) {}
+ override fun onStopTrackingTouch(seekBar: SeekBar?) {}
+ })
+
+ setPlayerStatus(song.isPlaying)
+ }
+
+ private fun setPlayerStatus(isPlaying: Boolean) {
+ song.isPlaying = isPlaying
+ timer.isPlaying = isPlaying
+
+ if (isPlaying) {
+ binding.songMiniplayerIv.visibility = View.GONE
+ binding.songPauseIv.visibility = View.VISIBLE
+ // mediaPlayer?.start()
+
+ if (mediaPlayer?.isPlaying == false) {
+ mediaPlayer?.seekTo(binding.songProgressSb.progress) // 현재 위치로 이동
+ mediaPlayer?.start()
+ }
+ } else {
+ binding.songMiniplayerIv.visibility = View.VISIBLE
+ binding.songPauseIv.visibility = View.GONE
+ if (mediaPlayer?.isPlaying == true){
+ mediaPlayer?.pause()
+ }
+ }
+ }
+
+ private fun startTimer(initialMills: Long) { // initialMills 파라미터 추가
+ timer = Timer(song.playTime,song.isPlaying, initialMills)
+ timer.start()
+ }
+
+ inner class Timer(
+ private val playTime: Int,
+ var isPlaying: Boolean = true,
+ initialMills: Long = 0 // 생성자 파라미터 추가
+ ): Thread() {
+ var second: Int = (initialMills / 1000).toInt()
+ var mills: Long = initialMills // 초기값 설정
+
+ override fun run() {
+ super.run()
+ try {
+ while (true) {
+ if (mills >= playTime * 1000) {
+ if (isRepeatActive) {
+ // 반복 재생이 활성화 되어있으면 처음부터 다시 시작
+ mills = 0
+ second = 0
+ runOnUiThread {
+ binding.songProgressSb.progress = 0
+ binding.songStartTimeTv.text = "00:00"
+ mediaPlayer?.seekTo(0)
+ mediaPlayer?.start()
+
+ // 반복 재생 시작 시에도 SharedPreferences 업데이트
+ updateSharedPreferences()
+ }
+ } else {
+ runOnUiThread {
+ setPlayerStatus(false)
+ }
+ break
+ }
+ }
+
+ if (isPlaying) {
+ sleep(50)
+ mills += 50
+
+ runOnUiThread {
+ // progress를 밀리초 단위로 계산
+ binding.songProgressSb.progress = mills.toInt()
+
+ // 1초마다 SharedPreferences 업데이트
+ if (mills % 1000 == 0L) {
+ updateSharedPreferences()
+ }
+ }
+
+ if (mills % 1000 == 0L) {
+ second = (mills / 1000).toInt()
+ runOnUiThread {
+ binding.songStartTimeTv.text = String.format("%02d:%02d", second / 60, second % 60)
+ }
+ }
+ }
+ }
+ } catch (e: InterruptedException) {
+ Log.d("Song", "쓰레드가 죽었습니다. ${e.message}")
+ }
+ }
+
+ private fun updateSharedPreferences() {
+ song.second = (mills / 1000).toInt()
+ song.playTime = playTime
+ val sharedPreferences = getSharedPreferences("song", MODE_PRIVATE)
+ val editor = sharedPreferences.edit()
+ val songJson = gson.toJson(song)
+ editor.putString("songData", songJson)
+ editor.apply()
+ }
+ }
+
+ override fun onPause() {
+ super.onPause()
+ setPlayerStatus(false)
+ // 진행 시간 계산 방식 수정
+ song.second = (binding.songProgressSb.progress / 1000) // 밀리초를 초로 변환
+ val sharedPreferences = getSharedPreferences("song", MODE_PRIVATE)
+ val editor = sharedPreferences.edit() // 에디터
+ val songJson = gson.toJson(song)
+ editor.putString("songData", songJson)
+
+ editor.apply()
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ timer.interrupt()
+ mediaPlayer?.release()
+ mediaPlayer = null
+ }
+
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/SongFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/SongFragment.kt
new file mode 100644
index 00000000..cff81270
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/SongFragment.kt
@@ -0,0 +1,42 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.floclone.databinding.FragmentSongBinding
+
+class SongFragment : Fragment() {
+ lateinit var binding: FragmentSongBinding
+ private var isMixOn = false
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentSongBinding.inflate(inflater,container,false)
+
+ // Mix 버튼 토글 추가
+ binding.songMixoffTg.setOnClickListener {
+ toggleMixBtn()
+ }
+ binding.songMixonTg.setOnClickListener {
+ toggleMixBtn()
+ }
+
+ return binding.root
+ }
+
+ private fun toggleMixBtn() {
+ isMixOn = !isMixOn
+ if (isMixOn) {
+ binding.songMixoffTg.visibility = View.GONE
+ binding.songMixonTg.visibility = View.VISIBLE
+ } else {
+ binding.songMixoffTg.visibility = View.VISIBLE
+ binding.songMixonTg.visibility = View.GONE
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/SongRVAdapter.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/SongRVAdapter.kt
new file mode 100644
index 00000000..0264577a
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/SongRVAdapter.kt
@@ -0,0 +1,71 @@
+package com.example.floclone
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import com.example.floclone.databinding.ItemSongBinding
+
+class SongRVAdapter(private val songs: ArrayList) :
+ RecyclerView.Adapter() {
+
+ // 클릭 인터페이스 정의
+ interface MyItemClickListener {
+ fun onRemoveSong(position: Int)
+ }
+
+ private lateinit var mItemClickListener: MyItemClickListener
+
+ fun setMyItemClickListener(itemClickListener: MyItemClickListener) {
+ mItemClickListener = itemClickListener
+ }
+
+ // 아이템 삭제
+ fun removeSong(position: Int) {
+ songs.removeAt(position)
+ notifyDataSetChanged()
+ }
+
+ // 뷰 홀더
+ inner class ViewHolder(private val binding: ItemSongBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+
+ fun bind(song: Song) {
+ binding.itemSongTitleTv.text = song.title
+ binding.itemSongSingerTv.text = song.singer
+
+ // 앨범 이미지 설정 (null이 아닐 때만)
+ song.coverImg?.let { coverImg ->
+ binding.itemSongAlbumIv.setImageResource(coverImg)
+ }
+
+ // 더보기 버튼 클릭 리스너 설정
+ binding.itemSongMoreIv.setOnClickListener {
+ mItemClickListener.onRemoveSong(adapterPosition)
+ }
+
+ // 스위치 상태 설정
+ binding.itemSongSwitch.isChecked = song.isSwitchOn
+
+ // 스위치 상태 변경 리스너
+ binding.itemSongSwitch.setOnCheckedChangeListener { _, isChecked ->
+ song.isSwitchOn = isChecked
+ }
+
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val binding = ItemSongBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )
+ return ViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(songs[position])
+ }
+
+ override fun getItemCount(): Int = songs.size
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/java/com/example/floclone/VideoFragment.kt b/Heather/FLOClone/app/src/main/java/com/example/floclone/VideoFragment.kt
new file mode 100644
index 00000000..ae09cd79
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/java/com/example/floclone/VideoFragment.kt
@@ -0,0 +1,25 @@
+package com.example.floclone
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.floclone.databinding.FragmentVideoBinding
+
+
+class VideoFragment : Fragment() {
+
+ lateinit var binding: FragmentVideoBinding
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ binding = FragmentVideoBinding.inflate(inflater,container,false)
+
+ return binding.root
+ }
+
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/apple_44.png b/Heather/FLOClone/app/src/main/res/drawable/apple_44.png
new file mode 100644
index 00000000..f365d20c
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/apple_44.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btm_color_selector.xml b/Heather/FLOClone/app/src/main/res/drawable/btm_color_selector.xml
new file mode 100644
index 00000000..3ecf8a7a
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/btm_color_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_actionbar_close.png b/Heather/FLOClone/app/src/main/res/drawable/btn_actionbar_close.png
new file mode 100644
index 00000000..b6cc3cc0
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_actionbar_close.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_actionbar_instagram.png b/Heather/FLOClone/app/src/main/res/drawable/btn_actionbar_instagram.png
new file mode 100644
index 00000000..90bc0277
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_actionbar_instagram.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_arrow_black.png b/Heather/FLOClone/app/src/main/res/drawable/btn_arrow_black.png
new file mode 100644
index 00000000..cc38ca8c
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_arrow_black.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_arrow_more.png b/Heather/FLOClone/app/src/main/res/drawable/btn_arrow_more.png
new file mode 100644
index 00000000..59e410c5
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_arrow_more.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_input_password.png b/Heather/FLOClone/app/src/main/res/drawable/btn_input_password.png
new file mode 100644
index 00000000..8c2eb186
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_input_password.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_input_password_off.png b/Heather/FLOClone/app/src/main/res/drawable/btn_input_password_off.png
new file mode 100644
index 00000000..8234f538
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_input_password_off.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_main_arrow_more.png b/Heather/FLOClone/app/src/main/res/drawable/btn_main_arrow_more.png
new file mode 100644
index 00000000..59e410c5
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_main_arrow_more.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_main_mike.png b/Heather/FLOClone/app/src/main/res/drawable/btn_main_mike.png
new file mode 100644
index 00000000..9bddec69
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_main_mike.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_main_setting.png b/Heather/FLOClone/app/src/main/res/drawable/btn_main_setting.png
new file mode 100644
index 00000000..7a8d5d6a
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_main_setting.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_main_ticket.png b/Heather/FLOClone/app/src/main/res/drawable/btn_main_ticket.png
new file mode 100644
index 00000000..52b6d64f
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_main_ticket.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_miniplay_mvpause.png b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplay_mvpause.png
new file mode 100644
index 00000000..470e0467
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplay_mvpause.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_miniplay_mvplay.png b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplay_mvplay.png
new file mode 100644
index 00000000..d1186774
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplay_mvplay.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_miniplay_pause.png b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplay_pause.png
new file mode 100644
index 00000000..470e0467
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplay_pause.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_go_list.png b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_go_list.png
new file mode 100644
index 00000000..1b2d9774
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_go_list.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_next.png b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_next.png
new file mode 100644
index 00000000..3aedba3c
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_next.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_play.png b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_play.png
new file mode 100644
index 00000000..f6190725
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_play.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_previous.png b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_previous.png
new file mode 100644
index 00000000..d0bf1f66
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_miniplayer_previous.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_nugu.png b/Heather/FLOClone/app/src/main/res/drawable/btn_nugu.png
new file mode 100644
index 00000000..9bddec69
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_nugu.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_panel_play_large.png b/Heather/FLOClone/app/src/main/res/drawable/btn_panel_play_large.png
new file mode 100644
index 00000000..4ac71038
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_panel_play_large.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_player_eq_off.png b/Heather/FLOClone/app/src/main/res/drawable/btn_player_eq_off.png
new file mode 100644
index 00000000..f23d9c6c
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_player_eq_off.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_player_go_list.png b/Heather/FLOClone/app/src/main/res/drawable/btn_player_go_list.png
new file mode 100644
index 00000000..1b2d9774
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_player_go_list.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_player_more.png b/Heather/FLOClone/app/src/main/res/drawable/btn_player_more.png
new file mode 100644
index 00000000..a8ad9e62
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_player_more.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_player_play.png b/Heather/FLOClone/app/src/main/res/drawable/btn_player_play.png
new file mode 100644
index 00000000..f6c3201c
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_player_play.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_player_related.png b/Heather/FLOClone/app/src/main/res/drawable/btn_player_related.png
new file mode 100644
index 00000000..9026fe5e
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_player_related.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_player_setting.png b/Heather/FLOClone/app/src/main/res/drawable/btn_player_setting.png
new file mode 100644
index 00000000..0df8f69a
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_player_setting.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_player_unlike_off.png b/Heather/FLOClone/app/src/main/res/drawable/btn_player_unlike_off.png
new file mode 100644
index 00000000..b5395047
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_player_unlike_off.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_player_unlike_on.png b/Heather/FLOClone/app/src/main/res/drawable/btn_player_unlike_on.png
new file mode 100644
index 00000000..45a43cae
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_player_unlike_on.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_playlist_select_off.png b/Heather/FLOClone/app/src/main/res/drawable/btn_playlist_select_off.png
new file mode 100644
index 00000000..62ef45ca
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_playlist_select_off.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_playlist_select_on.png b/Heather/FLOClone/app/src/main/res/drawable/btn_playlist_select_on.png
new file mode 100644
index 00000000..2d3b6afe
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_playlist_select_on.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_setting_phone.png b/Heather/FLOClone/app/src/main/res/drawable/btn_setting_phone.png
new file mode 100644
index 00000000..d6de4c69
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_setting_phone.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_textbox_close.png b/Heather/FLOClone/app/src/main/res/drawable/btn_textbox_close.png
new file mode 100644
index 00000000..10f1f636
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_textbox_close.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_titlebar_close.png b/Heather/FLOClone/app/src/main/res/drawable/btn_titlebar_close.png
new file mode 100644
index 00000000..6615deff
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_titlebar_close.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_toggle_off.png b/Heather/FLOClone/app/src/main/res/drawable/btn_toggle_off.png
new file mode 100644
index 00000000..983360df
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_toggle_off.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/btn_toggle_on.png b/Heather/FLOClone/app/src/main/res/drawable/btn_toggle_on.png
new file mode 100644
index 00000000..fb609f46
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/btn_toggle_on.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/button_background_black_color.xml b/Heather/FLOClone/app/src/main/res/drawable/button_background_black_color.xml
new file mode 100644
index 00000000..cad3794f
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/button_background_black_color.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/button_background_flo_color.xml b/Heather/FLOClone/app/src/main/res/drawable/button_background_flo_color.xml
new file mode 100644
index 00000000..d5e92f35
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/button_background_flo_color.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/button_background_gray_color.xml b/Heather/FLOClone/app/src/main/res/drawable/button_background_gray_color.xml
new file mode 100644
index 00000000..dbcaae2b
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/button_background_gray_color.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/button_background_white_color.xml b/Heather/FLOClone/app/src/main/res/drawable/button_background_white_color.xml
new file mode 100644
index 00000000..32e95830
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/button_background_white_color.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/discovery_banner_aos.jpg b/Heather/FLOClone/app/src/main/res/drawable/discovery_banner_aos.jpg
new file mode 100644
index 00000000..c9055156
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/discovery_banner_aos.jpg differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/fragment_look_chart_background.xml b/Heather/FLOClone/app/src/main/res/drawable/fragment_look_chart_background.xml
new file mode 100644
index 00000000..64c040f5
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/fragment_look_chart_background.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/fragment_look_chip_off_background.xml b/Heather/FLOClone/app/src/main/res/drawable/fragment_look_chip_off_background.xml
new file mode 100644
index 00000000..43005ce6
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/fragment_look_chip_off_background.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/fragment_look_chip_on_background.xml b/Heather/FLOClone/app/src/main/res/drawable/fragment_look_chip_on_background.xml
new file mode 100644
index 00000000..ce894ed7
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/fragment_look_chip_on_background.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_home_no_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_home_no_select.png
new file mode 100644
index 00000000..69a8ab6c
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_home_no_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_home_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_home_select.png
new file mode 100644
index 00000000..c0ff48e7
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_home_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_locker_no_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_locker_no_select.png
new file mode 100644
index 00000000..a67dec39
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_locker_no_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_locker_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_locker_select.png
new file mode 100644
index 00000000..042489f1
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_locker_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_look_no_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_look_no_select.png
new file mode 100644
index 00000000..6c2f4f0c
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_look_no_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_look_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_look_select.png
new file mode 100644
index 00000000..3d169e48
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_look_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_my_no_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_my_no_select.png
new file mode 100644
index 00000000..a67dec39
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_my_no_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_my_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_my_select.png
new file mode 100644
index 00000000..042489f1
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_my_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_search_no_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_search_no_select.png
new file mode 100644
index 00000000..a77b8c57
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_search_no_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_search_select.png b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_search_select.png
new file mode 100644
index 00000000..d5c8a722
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_bottom_search_select.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_browse_arrow_right.png b/Heather/FLOClone/app/src/main/res/drawable/ic_browse_arrow_right.png
new file mode 100644
index 00000000..71b588bf
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_browse_arrow_right.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_flo_logo.png b/Heather/FLOClone/app/src/main/res/drawable/ic_flo_logo.png
new file mode 100644
index 00000000..643224de
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_flo_logo.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_launcher_background.xml b/Heather/FLOClone/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..07d5da9c
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_launcher_foreground.xml b/Heather/FLOClone/app/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 00000000..2b068d11
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_main_facebook.png b/Heather/FLOClone/app/src/main/res/drawable/ic_main_facebook.png
new file mode 100644
index 00000000..83e97321
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_main_facebook.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_main_facebook_btn.png b/Heather/FLOClone/app/src/main/res/drawable/ic_main_facebook_btn.png
new file mode 100644
index 00000000..83e97321
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_main_facebook_btn.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_main_instagram.png b/Heather/FLOClone/app/src/main/res/drawable/ic_main_instagram.png
new file mode 100644
index 00000000..398ce614
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_main_instagram.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_main_instagram_btn.png b/Heather/FLOClone/app/src/main/res/drawable/ic_main_instagram_btn.png
new file mode 100644
index 00000000..398ce614
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_main_instagram_btn.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_main_twitter.png b/Heather/FLOClone/app/src/main/res/drawable/ic_main_twitter.png
new file mode 100644
index 00000000..6ddc68ee
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_main_twitter.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_main_twitter_btn.png b/Heather/FLOClone/app/src/main/res/drawable/ic_main_twitter_btn.png
new file mode 100644
index 00000000..6ddc68ee
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_main_twitter_btn.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_main_youtube.png b/Heather/FLOClone/app/src/main/res/drawable/ic_main_youtube.png
new file mode 100644
index 00000000..0c4ec932
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_main_youtube.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_main_youtube_btn.png b/Heather/FLOClone/app/src/main/res/drawable/ic_main_youtube_btn.png
new file mode 100644
index 00000000..0c4ec932
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_main_youtube_btn.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_my_like_off.png b/Heather/FLOClone/app/src/main/res/drawable/ic_my_like_off.png
new file mode 100644
index 00000000..c06e139d
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_my_like_off.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ic_my_like_on.png b/Heather/FLOClone/app/src/main/res/drawable/ic_my_like_on.png
new file mode 100644
index 00000000..22577c0b
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ic_my_like_on.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/ico_20_logo_tid_white.png b/Heather/FLOClone/app/src/main/res/drawable/ico_20_logo_tid_white.png
new file mode 100644
index 00000000..c6f4d4f9
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/ico_20_logo_tid_white.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/icon_browse_arrow_right.png b/Heather/FLOClone/app/src/main/res/drawable/icon_browse_arrow_right.png
new file mode 100644
index 00000000..71b588bf
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/icon_browse_arrow_right.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp.png
new file mode 100644
index 00000000..6e3f38af
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp10.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp10.png
new file mode 100644
index 00000000..36c2f6aa
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp10.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp11.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp11.png
new file mode 100644
index 00000000..66345efb
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp11.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp12.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp12.png
new file mode 100644
index 00000000..4d0849a9
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp12.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp13.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp13.png
new file mode 100644
index 00000000..fd6d61e5
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp13.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp2.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp2.png
new file mode 100644
index 00000000..28ea3ee5
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp2.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp3.jpg b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp3.jpg
new file mode 100644
index 00000000..66416001
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp3.jpg differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp4.jpg b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp4.jpg
new file mode 100644
index 00000000..aecebb6a
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp4.jpg differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp5.jpg b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp5.jpg
new file mode 100644
index 00000000..6a8d8701
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp5.jpg differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp6.jpg b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp6.jpg
new file mode 100644
index 00000000..48202f2d
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp6.jpg differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp7.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp7.png
new file mode 100644
index 00000000..ceb908a7
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp7.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp8.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp8.png
new file mode 100644
index 00000000..6dc6638c
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp8.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_exp9.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp9.png
new file mode 100644
index 00000000..f5702ce6
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_exp9.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_album_lp.png b/Heather/FLOClone/app/src/main/res/drawable/img_album_lp.png
new file mode 100644
index 00000000..29fb1b4d
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_album_lp.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_default_4_x_1.png b/Heather/FLOClone/app/src/main/res/drawable/img_default_4_x_1.png
new file mode 100644
index 00000000..926d34f5
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_default_4_x_1.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_first_album_default.png b/Heather/FLOClone/app/src/main/res/drawable/img_first_album_default.png
new file mode 100644
index 00000000..926d34f5
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_first_album_default.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_home_viewpager_exp.png b/Heather/FLOClone/app/src/main/res/drawable/img_home_viewpager_exp.png
new file mode 100644
index 00000000..da780323
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_home_viewpager_exp.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_home_viewpager_exp2.png b/Heather/FLOClone/app/src/main/res/drawable/img_home_viewpager_exp2.png
new file mode 100644
index 00000000..50fa4be8
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_home_viewpager_exp2.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_jenre_exp_1.png b/Heather/FLOClone/app/src/main/res/drawable/img_jenre_exp_1.png
new file mode 100644
index 00000000..0d43e8e4
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_jenre_exp_1.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_jenre_exp_2.png b/Heather/FLOClone/app/src/main/res/drawable/img_jenre_exp_2.png
new file mode 100644
index 00000000..f03efb22
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_jenre_exp_2.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_jenre_exp_3.png b/Heather/FLOClone/app/src/main/res/drawable/img_jenre_exp_3.png
new file mode 100644
index 00000000..51de6849
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_jenre_exp_3.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_potcast_exp.png b/Heather/FLOClone/app/src/main/res/drawable/img_potcast_exp.png
new file mode 100644
index 00000000..50a46e03
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_potcast_exp.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/img_video_exp.png b/Heather/FLOClone/app/src/main/res/drawable/img_video_exp.png
new file mode 100644
index 00000000..7f6b05f2
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/img_video_exp.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/indicator_selected_circle.xml b/Heather/FLOClone/app/src/main/res/drawable/indicator_selected_circle.xml
new file mode 100644
index 00000000..063a7111
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/indicator_selected_circle.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/indicator_unselected_circle.xml b/Heather/FLOClone/app/src/main/res/drawable/indicator_unselected_circle.xml
new file mode 100644
index 00000000..20e39f6d
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/indicator_unselected_circle.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/kakako_44.png b/Heather/FLOClone/app/src/main/res/drawable/kakako_44.png
new file mode 100644
index 00000000..243298e0
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/kakako_44.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/main_btm_color_selector.xml b/Heather/FLOClone/app/src/main/res/drawable/main_btm_color_selector.xml
new file mode 100644
index 00000000..3ecf8a7a
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/main_btm_color_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/main_btm_home_selector.xml b/Heather/FLOClone/app/src/main/res/drawable/main_btm_home_selector.xml
new file mode 100644
index 00000000..b018478e
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/main_btm_home_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/main_btm_look_selector.xml b/Heather/FLOClone/app/src/main/res/drawable/main_btm_look_selector.xml
new file mode 100644
index 00000000..89ced75d
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/main_btm_look_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/main_btm_my_selector.xml b/Heather/FLOClone/app/src/main/res/drawable/main_btm_my_selector.xml
new file mode 100644
index 00000000..d6739bf2
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/main_btm_my_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/main_btm_search_selector.xml b/Heather/FLOClone/app/src/main/res/drawable/main_btm_search_selector.xml
new file mode 100644
index 00000000..e6e823fd
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/main_btm_search_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/naver_44.png b/Heather/FLOClone/app/src/main/res/drawable/naver_44.png
new file mode 100644
index 00000000..d9844877
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/naver_44.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_down.png b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_down.png
new file mode 100644
index 00000000..03a04c57
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_down.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_pause_32.png b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_pause_32.png
new file mode 100644
index 00000000..9388aa33
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_pause_32.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_play_32.png b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_play_32.png
new file mode 100644
index 00000000..b781e4c8
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_play_32.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_random_inactive.png b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_random_inactive.png
new file mode 100644
index 00000000..fe4f880b
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_random_inactive.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_repeat_inactive.png b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_repeat_inactive.png
new file mode 100644
index 00000000..1e4044dc
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_repeat_inactive.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_skip_next_32.png b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_skip_next_32.png
new file mode 100644
index 00000000..fc02f28f
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_skip_next_32.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_skip_previous_32.png b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_skip_previous_32.png
new file mode 100644
index 00000000..03ec854c
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/nugu_btn_skip_previous_32.png differ
diff --git a/Heather/FLOClone/app/src/main/res/drawable/splash.xml b/Heather/FLOClone/app/src/main/res/drawable/splash.xml
new file mode 100644
index 00000000..484f2854
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/splash.xml
@@ -0,0 +1,9 @@
+
+
+
+ -
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/drawable/textview_background_radius.xml b/Heather/FLOClone/app/src/main/res/drawable/textview_background_radius.xml
new file mode 100644
index 00000000..53beead7
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/textview_background_radius.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/textview_background_select_color_radius.xml b/Heather/FLOClone/app/src/main/res/drawable/textview_background_select_color_radius.xml
new file mode 100644
index 00000000..ea8dc88c
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/drawable/textview_background_select_color_radius.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/Heather/FLOClone/app/src/main/res/drawable/widget_black_play.png b/Heather/FLOClone/app/src/main/res/drawable/widget_black_play.png
new file mode 100644
index 00000000..0ec27005
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/drawable/widget_black_play.png differ
diff --git a/Heather/FLOClone/app/src/main/res/layout/activity_main.xml b/Heather/FLOClone/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..ca14f847
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/activity_song.xml b/Heather/FLOClone/app/src/main/res/layout/activity_song.xml
new file mode 100644
index 00000000..72b4d837
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/activity_song.xml
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_album.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_album.xml
new file mode 100644
index 00000000..0e6936b3
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_album.xml
@@ -0,0 +1,130 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_banner.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_banner.xml
new file mode 100644
index 00000000..37c2ef8d
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_banner.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_detail.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_detail.xml
new file mode 100644
index 00000000..413125cb
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_detail.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_home.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_home.xml
new file mode 100644
index 00000000..d1305e50
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_home.xml
@@ -0,0 +1,812 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_lock.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_lock.xml
new file mode 100644
index 00000000..578160af
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_lock.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_locker.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_locker.xml
new file mode 100644
index 00000000..1514c2c8
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_locker.xml
@@ -0,0 +1,105 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_music_file.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_music_file.xml
new file mode 100644
index 00000000..526b2dc1
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_music_file.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_panel.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_panel.xml
new file mode 100644
index 00000000..e2f6f9ee
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_panel.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_saved_song.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_saved_song.xml
new file mode 100644
index 00000000..ad1bc482
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_saved_song.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_search.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_search.xml
new file mode 100644
index 00000000..b6198d44
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_search.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_song.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_song.xml
new file mode 100644
index 00000000..533d0356
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_song.xml
@@ -0,0 +1,556 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/fragment_video.xml b/Heather/FLOClone/app/src/main/res/layout/fragment_video.xml
new file mode 100644
index 00000000..e86dad11
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/fragment_video.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/item_album.xml b/Heather/FLOClone/app/src/main/res/layout/item_album.xml
new file mode 100644
index 00000000..23ae9f72
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/item_album.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/layout/item_song.xml b/Heather/FLOClone/app/src/main/res/layout/item_song.xml
new file mode 100644
index 00000000..9257c779
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/layout/item_song.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/menu/bottom_nav_menu.xml b/Heather/FLOClone/app/src/main/res/menu/bottom_nav_menu.xml
new file mode 100644
index 00000000..9a55b1a3
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/menu/bottom_nav_menu.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/Heather/FLOClone/app/src/main/res/mipmap-anydpi/ic_launcher.xml
new file mode 100644
index 00000000..6f3b755b
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/mipmap-anydpi/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/Heather/FLOClone/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
new file mode 100644
index 00000000..6f3b755b
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/Heather/FLOClone/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 00000000..c209e78e
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/Heather/FLOClone/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..b2dfe3d1
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/Heather/FLOClone/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 00000000..4f0f1d64
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/Heather/FLOClone/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..62b611da
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/Heather/FLOClone/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 00000000..948a3070
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/Heather/FLOClone/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..1b9a6956
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/Heather/FLOClone/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..28d4b77f
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/Heather/FLOClone/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9287f508
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/Heather/FLOClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..aa7d6427
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/Heather/FLOClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9126ae37
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/Heather/FLOClone/app/src/main/res/raw/music.mp3 b/Heather/FLOClone/app/src/main/res/raw/music.mp3
new file mode 100644
index 00000000..ee477ff2
Binary files /dev/null and b/Heather/FLOClone/app/src/main/res/raw/music.mp3 differ
diff --git a/Heather/FLOClone/app/src/main/res/values-night/themes.xml b/Heather/FLOClone/app/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..e2fc596a
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/values/colors.xml b/Heather/FLOClone/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..a46d77b3
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/values/colors.xml
@@ -0,0 +1,20 @@
+
+
+ #FF000000
+ #FFFFFFFF
+
+ #3f3fff
+
+ #9cbee2
+ #062342
+ #424242
+ #6bb2ff
+
+ #00ff0000
+ #3f3fff
+ #a8a8a8
+ #3f3fff
+ #a8a8a8
+
+ #F11818
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/values/strings.xml b/Heather/FLOClone/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..72084881
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/values/strings.xml
@@ -0,0 +1,5 @@
+
+ FLOClone
+
+ Hello blank fragment
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/values/themes.xml b/Heather/FLOClone/app/src/main/res/values/themes.xml
new file mode 100644
index 00000000..d961810d
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/values/themes.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/xml/backup_rules.xml b/Heather/FLOClone/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 00000000..fa0f996d
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/main/res/xml/data_extraction_rules.xml b/Heather/FLOClone/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 00000000..9ee9997b
--- /dev/null
+++ b/Heather/FLOClone/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/FLOClone/app/src/test/java/com/example/floclone/ExampleUnitTest.kt b/Heather/FLOClone/app/src/test/java/com/example/floclone/ExampleUnitTest.kt
new file mode 100644
index 00000000..1edb7285
--- /dev/null
+++ b/Heather/FLOClone/app/src/test/java/com/example/floclone/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.example.floclone
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/build.gradle.kts b/Heather/FLOClone/build.gradle.kts
new file mode 100644
index 00000000..922f5511
--- /dev/null
+++ b/Heather/FLOClone/build.gradle.kts
@@ -0,0 +1,5 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.kotlin.android) apply false
+}
\ No newline at end of file
diff --git a/Heather/FLOClone/gradle.properties b/Heather/FLOClone/gradle.properties
new file mode 100644
index 00000000..20e2a015
--- /dev/null
+++ b/Heather/FLOClone/gradle.properties
@@ -0,0 +1,23 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. For more details, visit
+# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/Heather/FLOClone/gradle/libs.versions.toml b/Heather/FLOClone/gradle/libs.versions.toml
new file mode 100644
index 00000000..faf6ca23
--- /dev/null
+++ b/Heather/FLOClone/gradle/libs.versions.toml
@@ -0,0 +1,26 @@
+[versions]
+agp = "8.6.0"
+kotlin = "1.9.0"
+coreKtx = "1.13.1"
+junit = "4.13.2"
+junitVersion = "1.2.1"
+espressoCore = "3.6.1"
+appcompat = "1.7.0"
+material = "1.12.0"
+activity = "1.9.2"
+constraintlayout = "2.1.4"
+
+[libraries]
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
+androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
+androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
+androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+
diff --git a/Heather/FLOClone/gradle/wrapper/gradle-wrapper.jar b/Heather/FLOClone/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..e708b1c0
Binary files /dev/null and b/Heather/FLOClone/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/Heather/FLOClone/gradle/wrapper/gradle-wrapper.properties b/Heather/FLOClone/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..2d9548fb
--- /dev/null
+++ b/Heather/FLOClone/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sun Oct 13 18:19:16 KST 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/Heather/FLOClone/gradlew b/Heather/FLOClone/gradlew
new file mode 100755
index 00000000..4f906e0c
--- /dev/null
+++ b/Heather/FLOClone/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/Heather/FLOClone/gradlew.bat b/Heather/FLOClone/gradlew.bat
new file mode 100644
index 00000000..ac1b06f9
--- /dev/null
+++ b/Heather/FLOClone/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/Heather/FLOClone/settings.gradle.kts b/Heather/FLOClone/settings.gradle.kts
new file mode 100644
index 00000000..c65cd666
--- /dev/null
+++ b/Heather/FLOClone/settings.gradle.kts
@@ -0,0 +1,23 @@
+pluginManagement {
+ repositories {
+ google {
+ content {
+ includeGroupByRegex("com\\.android.*")
+ includeGroupByRegex("com\\.google.*")
+ includeGroupByRegex("androidx.*")
+ }
+ }
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.name = "FLOClone"
+include(":app")
diff --git a/Heather/Memo/.gitignore b/Heather/Memo/.gitignore
new file mode 100644
index 00000000..aa724b77
--- /dev/null
+++ b/Heather/Memo/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/Heather/Memo/.idea/.gitignore b/Heather/Memo/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/Heather/Memo/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/Heather/Memo/.idea/appInsightsSettings.xml b/Heather/Memo/.idea/appInsightsSettings.xml
new file mode 100644
index 00000000..371f2e29
--- /dev/null
+++ b/Heather/Memo/.idea/appInsightsSettings.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/.idea/compiler.xml b/Heather/Memo/.idea/compiler.xml
new file mode 100644
index 00000000..b589d56e
--- /dev/null
+++ b/Heather/Memo/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/.idea/deploymentTargetSelector.xml b/Heather/Memo/.idea/deploymentTargetSelector.xml
new file mode 100644
index 00000000..b268ef36
--- /dev/null
+++ b/Heather/Memo/.idea/deploymentTargetSelector.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/.idea/gradle.xml b/Heather/Memo/.idea/gradle.xml
new file mode 100644
index 00000000..0897082f
--- /dev/null
+++ b/Heather/Memo/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/.idea/kotlinc.xml b/Heather/Memo/.idea/kotlinc.xml
new file mode 100644
index 00000000..fdf8d994
--- /dev/null
+++ b/Heather/Memo/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/.idea/migrations.xml b/Heather/Memo/.idea/migrations.xml
new file mode 100644
index 00000000..f8051a6f
--- /dev/null
+++ b/Heather/Memo/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/.idea/misc.xml b/Heather/Memo/.idea/misc.xml
new file mode 100644
index 00000000..0ad17cbd
--- /dev/null
+++ b/Heather/Memo/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/.idea/vcs.xml b/Heather/Memo/.idea/vcs.xml
new file mode 100644
index 00000000..64713b81
--- /dev/null
+++ b/Heather/Memo/.idea/vcs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/.gitignore b/Heather/Memo/app/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/Heather/Memo/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/Heather/Memo/app/build.gradle.kts b/Heather/Memo/app/build.gradle.kts
new file mode 100644
index 00000000..07c98736
--- /dev/null
+++ b/Heather/Memo/app/build.gradle.kts
@@ -0,0 +1,51 @@
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin.android)
+}
+
+android {
+ namespace = "com.example.memo"
+ compileSdk = 35
+
+ defaultConfig {
+ applicationId = "com.example.memo"
+ minSdk = 34
+ targetSdk = 34
+ versionCode = 1
+ versionName = "1.0"
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+ buildFeatures {
+ viewBinding = true
+ }
+}
+
+dependencies {
+
+ implementation(libs.androidx.core.ktx)
+ implementation(libs.androidx.appcompat)
+ implementation(libs.material)
+ implementation(libs.androidx.activity)
+ implementation(libs.androidx.constraintlayout)
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.androidx.junit)
+ androidTestImplementation(libs.androidx.espresso.core)
+}
\ No newline at end of file
diff --git a/Heather/Memo/app/proguard-rules.pro b/Heather/Memo/app/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/Heather/Memo/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/Heather/Memo/app/src/androidTest/java/com/example/memo/ExampleInstrumentedTest.kt b/Heather/Memo/app/src/androidTest/java/com/example/memo/ExampleInstrumentedTest.kt
new file mode 100644
index 00000000..4a350841
--- /dev/null
+++ b/Heather/Memo/app/src/androidTest/java/com/example/memo/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.example.memo
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.example.memo", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/AndroidManifest.xml b/Heather/Memo/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..1b54a193
--- /dev/null
+++ b/Heather/Memo/app/src/main/AndroidManifest.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/java/com/example/memo/DetailActivity.kt b/Heather/Memo/app/src/main/java/com/example/memo/DetailActivity.kt
new file mode 100644
index 00000000..67734baa
--- /dev/null
+++ b/Heather/Memo/app/src/main/java/com/example/memo/DetailActivity.kt
@@ -0,0 +1,37 @@
+package com.example.memo
+
+import android.os.Bundle
+import android.view.MenuItem
+import androidx.appcompat.app.AppCompatActivity
+import com.example.memo.databinding.ActivityDetailBinding
+
+class DetailActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityDetailBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ binding = ActivityDetailBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ // ActionBar에 뒤로가기 버튼 추가
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ supportActionBar?.title = "메모장"
+
+ // 전달받은 메모 내용을 TextView에 표시
+ val memo = intent.getStringExtra("memo") ?: ""
+ binding.textMemo.text = memo
+
+ }
+
+ // 뒤로가기 버튼 클릭 처리
+ override fun onOptionsItemSelected(item: MenuItem): Boolean {
+ when (item.itemId) {
+ android.R.id.home -> {
+ finish()
+ return true
+ }
+ }
+ return super.onOptionsItemSelected(item)
+ }
+}
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/java/com/example/memo/MainActivity.kt b/Heather/Memo/app/src/main/java/com/example/memo/MainActivity.kt
new file mode 100644
index 00000000..33bf3905
--- /dev/null
+++ b/Heather/Memo/app/src/main/java/com/example/memo/MainActivity.kt
@@ -0,0 +1,57 @@
+package com.example.memo
+
+import android.app.AlertDialog
+import android.content.Intent
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import com.example.memo.databinding.ActivityMainBinding
+
+class MainActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityMainBinding
+ private var savedMemo: String = ""
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ // 버튼 클릭 리스너 설정
+ binding.btnSave.setOnClickListener {
+ val intent = Intent(this, DetailActivity::class.java)
+ intent.putExtra("memo", binding.editMemo.text.toString())
+ startActivity(intent)
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ // 저장된 메모가 있으면 EditText에 설정
+ if (savedMemo.isNotEmpty()) {
+ binding.editMemo.setText(savedMemo)
+ }
+ }
+
+ override fun onPause() {
+ super.onPause()
+ // 현재 작성 중인 메모 내용 저장
+ savedMemo = binding.editMemo.text.toString()
+ }
+
+ override fun onRestart() {
+ super.onRestart()
+ AlertDialog.Builder(this)
+ .setTitle("메모")
+ .setMessage("메모를 다시 작성하시겠습니까?")
+ .setPositiveButton("예") { _, _ ->
+ // 다시 작성하기를 선택하면 입력값이랑 저장값 모두 지움
+ binding.editMemo.setText("")
+ savedMemo = ""
+ }
+ .setNegativeButton("아니오") { _, _ ->
+ // 다시 작성하지 않으면 이전에 작성된 내용 유지
+ binding.editMemo.setText(savedMemo)
+ }
+ .show()
+ }
+}
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/drawable/ic_launcher_background.xml b/Heather/Memo/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..07d5da9c
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Heather/Memo/app/src/main/res/drawable/ic_launcher_foreground.xml b/Heather/Memo/app/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 00000000..2b068d11
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/layout/activity_detail.xml b/Heather/Memo/app/src/main/res/layout/activity_detail.xml
new file mode 100644
index 00000000..4f47d704
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/layout/activity_detail.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/layout/activity_main.xml b/Heather/Memo/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..477bd71e
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/Heather/Memo/app/src/main/res/mipmap-anydpi/ic_launcher.xml
new file mode 100644
index 00000000..6f3b755b
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/mipmap-anydpi/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/Heather/Memo/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
new file mode 100644
index 00000000..6f3b755b
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/Heather/Memo/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 00000000..c209e78e
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/Heather/Memo/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/Heather/Memo/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..b2dfe3d1
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/Heather/Memo/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/Heather/Memo/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 00000000..4f0f1d64
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/Heather/Memo/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/Heather/Memo/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..62b611da
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/Heather/Memo/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/Heather/Memo/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 00000000..948a3070
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/Heather/Memo/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/Heather/Memo/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..1b9a6956
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/Heather/Memo/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/Heather/Memo/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..28d4b77f
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/Heather/Memo/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/Heather/Memo/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9287f508
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/Heather/Memo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/Heather/Memo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..aa7d6427
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/Heather/Memo/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/Heather/Memo/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9126ae37
Binary files /dev/null and b/Heather/Memo/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/Heather/Memo/app/src/main/res/values-night/themes.xml b/Heather/Memo/app/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..5fcc9b3c
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/values/colors.xml b/Heather/Memo/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..c8524cd9
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/values/colors.xml
@@ -0,0 +1,5 @@
+
+
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/values/strings.xml b/Heather/Memo/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..249597d6
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ Memo
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/values/themes.xml b/Heather/Memo/app/src/main/res/values/themes.xml
new file mode 100644
index 00000000..6e1e6712
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/values/themes.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/xml/backup_rules.xml b/Heather/Memo/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 00000000..fa0f996d
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/main/res/xml/data_extraction_rules.xml b/Heather/Memo/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 00000000..9ee9997b
--- /dev/null
+++ b/Heather/Memo/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/Memo/app/src/test/java/com/example/memo/ExampleUnitTest.kt b/Heather/Memo/app/src/test/java/com/example/memo/ExampleUnitTest.kt
new file mode 100644
index 00000000..f75a0f5d
--- /dev/null
+++ b/Heather/Memo/app/src/test/java/com/example/memo/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.example.memo
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/Heather/Memo/build.gradle.kts b/Heather/Memo/build.gradle.kts
new file mode 100644
index 00000000..922f5511
--- /dev/null
+++ b/Heather/Memo/build.gradle.kts
@@ -0,0 +1,5 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.kotlin.android) apply false
+}
\ No newline at end of file
diff --git a/Heather/Memo/gradle.properties b/Heather/Memo/gradle.properties
new file mode 100644
index 00000000..20e2a015
--- /dev/null
+++ b/Heather/Memo/gradle.properties
@@ -0,0 +1,23 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. For more details, visit
+# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/Heather/Memo/gradle/libs.versions.toml b/Heather/Memo/gradle/libs.versions.toml
new file mode 100644
index 00000000..04e14fbc
--- /dev/null
+++ b/Heather/Memo/gradle/libs.versions.toml
@@ -0,0 +1,26 @@
+[versions]
+agp = "8.6.0"
+kotlin = "1.9.0"
+coreKtx = "1.15.0"
+junit = "4.13.2"
+junitVersion = "1.2.1"
+espressoCore = "3.6.1"
+appcompat = "1.7.0"
+material = "1.12.0"
+activity = "1.9.3"
+constraintlayout = "2.2.0"
+
+[libraries]
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
+androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
+androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
+androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+
diff --git a/Heather/Memo/gradle/wrapper/gradle-wrapper.jar b/Heather/Memo/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..e708b1c0
Binary files /dev/null and b/Heather/Memo/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/Heather/Memo/gradle/wrapper/gradle-wrapper.properties b/Heather/Memo/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..2206971b
--- /dev/null
+++ b/Heather/Memo/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sun Nov 10 20:26:27 KST 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/Heather/Memo/gradlew b/Heather/Memo/gradlew
new file mode 100755
index 00000000..4f906e0c
--- /dev/null
+++ b/Heather/Memo/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/Heather/Memo/gradlew.bat b/Heather/Memo/gradlew.bat
new file mode 100644
index 00000000..ac1b06f9
--- /dev/null
+++ b/Heather/Memo/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/Heather/Memo/settings.gradle.kts b/Heather/Memo/settings.gradle.kts
new file mode 100644
index 00000000..ac0f3468
--- /dev/null
+++ b/Heather/Memo/settings.gradle.kts
@@ -0,0 +1,23 @@
+pluginManagement {
+ repositories {
+ google {
+ content {
+ includeGroupByRegex("com\\.android.*")
+ includeGroupByRegex("com\\.google.*")
+ includeGroupByRegex("androidx.*")
+ }
+ }
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.name = "Memo"
+include(":app")
diff --git a/Heather/PokedexClone/.gitignore b/Heather/PokedexClone/.gitignore
new file mode 100644
index 00000000..aa724b77
--- /dev/null
+++ b/Heather/PokedexClone/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/Heather/PokedexClone/.idea/.gitignore b/Heather/PokedexClone/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/Heather/PokedexClone/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/Heather/PokedexClone/.idea/appInsightsSettings.xml b/Heather/PokedexClone/.idea/appInsightsSettings.xml
new file mode 100644
index 00000000..371f2e29
--- /dev/null
+++ b/Heather/PokedexClone/.idea/appInsightsSettings.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/.idea/compiler.xml b/Heather/PokedexClone/.idea/compiler.xml
new file mode 100644
index 00000000..b589d56e
--- /dev/null
+++ b/Heather/PokedexClone/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/.idea/deploymentTargetSelector.xml b/Heather/PokedexClone/.idea/deploymentTargetSelector.xml
new file mode 100644
index 00000000..b268ef36
--- /dev/null
+++ b/Heather/PokedexClone/.idea/deploymentTargetSelector.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/.idea/gradle.xml b/Heather/PokedexClone/.idea/gradle.xml
new file mode 100644
index 00000000..0897082f
--- /dev/null
+++ b/Heather/PokedexClone/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/.idea/kotlinc.xml b/Heather/PokedexClone/.idea/kotlinc.xml
new file mode 100644
index 00000000..fdf8d994
--- /dev/null
+++ b/Heather/PokedexClone/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/.idea/migrations.xml b/Heather/PokedexClone/.idea/migrations.xml
new file mode 100644
index 00000000..f8051a6f
--- /dev/null
+++ b/Heather/PokedexClone/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/.idea/misc.xml b/Heather/PokedexClone/.idea/misc.xml
new file mode 100644
index 00000000..8978d23d
--- /dev/null
+++ b/Heather/PokedexClone/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/.idea/vcs.xml b/Heather/PokedexClone/.idea/vcs.xml
new file mode 100644
index 00000000..b2bdec2d
--- /dev/null
+++ b/Heather/PokedexClone/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/.gitignore b/Heather/PokedexClone/app/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/Heather/PokedexClone/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/build.gradle.kts b/Heather/PokedexClone/app/build.gradle.kts
new file mode 100644
index 00000000..a47459b2
--- /dev/null
+++ b/Heather/PokedexClone/app/build.gradle.kts
@@ -0,0 +1,51 @@
+plugins {
+ alias(libs.plugins.android.application)
+ alias(libs.plugins.kotlin.android)
+}
+
+android {
+ namespace = "com.example.pokedexclone"
+ compileSdk = 35
+
+ defaultConfig {
+ applicationId = "com.example.pokedexclone"
+ minSdk = 34
+ targetSdk = 34
+ versionCode = 1
+ versionName = "1.0"
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+ buildFeatures {
+ viewBinding = true
+ }
+}
+
+dependencies {
+
+ implementation(libs.androidx.core.ktx)
+ implementation(libs.androidx.appcompat)
+ implementation(libs.material)
+ implementation(libs.androidx.activity)
+ implementation(libs.androidx.constraintlayout)
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.androidx.junit)
+ androidTestImplementation(libs.androidx.espresso.core)
+}
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/proguard-rules.pro b/Heather/PokedexClone/app/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/Heather/PokedexClone/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/androidTest/java/com/example/pokedexclone/ExampleInstrumentedTest.kt b/Heather/PokedexClone/app/src/androidTest/java/com/example/pokedexclone/ExampleInstrumentedTest.kt
new file mode 100644
index 00000000..96df3f06
--- /dev/null
+++ b/Heather/PokedexClone/app/src/androidTest/java/com/example/pokedexclone/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.example.pokedexclone
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.example.pokedexclone", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/AndroidManifest.xml b/Heather/PokedexClone/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..4dc0d7db
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/AndroidManifest.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/MainActivity.kt b/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/MainActivity.kt
new file mode 100644
index 00000000..c418dad5
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/MainActivity.kt
@@ -0,0 +1,106 @@
+package com.example.pokedexclone
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
+import androidx.recyclerview.widget.GridLayoutManager
+import com.example.pokedexclone.databinding.ActivityMainBinding
+
+class MainActivity : AppCompatActivity() {
+ lateinit var binding: ActivityMainBinding
+ private var pokemonDatas = ArrayList()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ // 더미데이터 추가
+ initPokemonList()
+
+ val pokemonRVAdapter = PokemonRVAdapter(pokemonDatas)
+ binding.mainPokemonRv.adapter = pokemonRVAdapter
+ binding.mainPokemonRv.layoutManager = GridLayoutManager(this, 3) // 포켓몬 한 줄에 3개
+ }
+
+ private fun initPokemonList() {
+ pokemonDatas.apply {
+ add(Pokemon("0001", "이상해씨",
+ R.drawable.img_bulbasaur,
+ ContextCompat.getColor(this@MainActivity, R.color.grass_background),
+ PokemonType.GRASS,
+ PokemonType.POISON))
+ add(Pokemon("0002", "이상해풀",
+ R.drawable.img_ivysaur,
+ ContextCompat.getColor(this@MainActivity, R.color.grass_background),
+ PokemonType.GRASS,
+ PokemonType.POISON))
+ add(Pokemon("0003", "이상해꽃",
+ R.drawable.img_venusaur,
+ ContextCompat.getColor(this@MainActivity, R.color.grass_background),
+ PokemonType.GRASS,
+ PokemonType.POISON))
+ add(Pokemon("0004", "파이리",
+ R.drawable.img_charmander,
+ ContextCompat.getColor(this@MainActivity, R.color.fire_background),
+ PokemonType.FIRE,
+ null))
+ add(Pokemon("0005", "리자드",
+ R.drawable.img_charmeleon,
+ ContextCompat.getColor(this@MainActivity, R.color.fire_background),
+ PokemonType.FIRE,
+ null))
+ add(Pokemon("0006", "리자몽",
+ R.drawable.img_charizard,
+ ContextCompat.getColor(this@MainActivity, R.color.fire_background),
+ PokemonType.FIRE,
+ PokemonType.FLYING))
+ add(Pokemon("0007", "꼬부기",
+ R.drawable.img_squirtle,
+ ContextCompat.getColor(this@MainActivity, R.color.water_background),
+ PokemonType.WATER,
+ null))
+ add(Pokemon("0008", "어니부기",
+ R.drawable.img_wartortle,
+ ContextCompat.getColor(this@MainActivity, R.color.water_background),
+ PokemonType.WATER,
+ null))
+ add(Pokemon("0009", "거북왕",
+ R.drawable.img_blastoise,
+ ContextCompat.getColor(this@MainActivity, R.color.water_background),
+ PokemonType.WATER,
+ null))
+ add(Pokemon("0010", "캐터피",
+ R.drawable.img_caterpie,
+ ContextCompat.getColor(this@MainActivity, R.color.bug_background),
+ PokemonType.BUG,
+ null))
+ add(Pokemon("0011", "단데기",
+ R.drawable.img_metapod,
+ ContextCompat.getColor(this@MainActivity, R.color.bug_background),
+ PokemonType.BUG,
+ null))
+ add(Pokemon("0012", "버터플",
+ R.drawable.img_butterfree,
+ ContextCompat.getColor(this@MainActivity, R.color.bug_background),
+ PokemonType.BUG,
+ PokemonType.FLYING))
+ add(Pokemon("0013", "뿔충이",
+ R.drawable.img_weedle,
+ ContextCompat.getColor(this@MainActivity, R.color.bug_background),
+ PokemonType.BUG,
+ PokemonType.POISON))
+ add(Pokemon("0014", "딱충이",
+ R.drawable.img_kakuna,
+ ContextCompat.getColor(this@MainActivity, R.color.bug_background),
+ PokemonType.BUG,
+ PokemonType.POISON))
+ add(Pokemon("0015", "독침봉",
+ R.drawable.img_beedrill,
+ ContextCompat.getColor(this@MainActivity, R.color.bug_background),
+ PokemonType.BUG,
+ PokemonType.POISON))
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/Pokemon.kt b/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/Pokemon.kt
new file mode 100644
index 00000000..202090fa
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/Pokemon.kt
@@ -0,0 +1,11 @@
+package com.example.pokedexclone
+
+data class Pokemon(
+ val id: String,
+ val name: String,
+ val image: Int,
+ val backgroundColor: Int,
+ val primaryType: PokemonType,
+ val secondaryType: PokemonType?,
+ var isCaught: Boolean = false
+)
diff --git a/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/PokemonRVAdapter.kt b/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/PokemonRVAdapter.kt
new file mode 100644
index 00000000..cafc3545
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/PokemonRVAdapter.kt
@@ -0,0 +1,75 @@
+package com.example.pokedexclone
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.content.ContextCompat
+import androidx.recyclerview.widget.RecyclerView
+import com.example.pokedexclone.databinding.ItemPokemonBinding
+
+class PokemonRVAdapter(private val pokemons: ArrayList) :
+ RecyclerView.Adapter() {
+
+ interface MyItemClickListener {
+ fun onTypeClick(position: Int)
+ }
+
+ private lateinit var mItemClickListener: MyItemClickListener
+
+ fun setMyItemClickListener(itemClickListener: MyItemClickListener) {
+ mItemClickListener = itemClickListener
+ }
+
+ inner class ViewHolder(private val binding: ItemPokemonBinding) :
+ RecyclerView.ViewHolder(binding.root) {
+
+ fun bind(pokemon: Pokemon) {
+ binding.itemPokemonIdTv.text = pokemon.id
+ binding.itemPokemonNameTv.text = pokemon.name
+ binding.itemPokemonImageIv.setImageResource(pokemon.image)
+ binding.itemPokemonCv.setCardBackgroundColor(pokemon.backgroundColor)
+
+ // 속성 버튼 설정
+ if (pokemon.secondaryType != null) {
+ binding.itemPokemonDualTypeLayout.visibility = View.VISIBLE
+ binding.itemPokemonSingleTypeBtn.visibility = View.GONE
+
+ binding.itemPokemonPrimaryTypeBtn.apply {
+ text = pokemon.primaryType.typeName
+ setBackgroundColor(ContextCompat.getColor(context, pokemon.primaryType.backgroundColor))
+ }
+
+ binding.itemPokemonSecondaryTypeBtn.apply {
+ text = pokemon.secondaryType.typeName
+ setBackgroundColor(ContextCompat.getColor(context, pokemon.secondaryType.backgroundColor))
+ visibility = View.VISIBLE
+ }
+
+ } else {
+ // 단일 속성일 경우
+ binding.itemPokemonDualTypeLayout.visibility = View.GONE
+ binding.itemPokemonSingleTypeBtn.visibility = View.VISIBLE
+
+ binding.itemPokemonSingleTypeBtn.apply {
+ text = pokemon.primaryType.typeName
+ setBackgroundColor(ContextCompat.getColor(context, pokemon.primaryType.backgroundColor))
+ }
+ }
+ }
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val binding: ItemPokemonBinding = ItemPokemonBinding.inflate(
+ LayoutInflater.from(parent.context),
+ parent,
+ false
+ )
+ return ViewHolder(binding)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(pokemons[position])
+ }
+
+ override fun getItemCount(): Int = pokemons.size
+}
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/PokemonType.kt b/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/PokemonType.kt
new file mode 100644
index 00000000..e2e354a7
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/java/com/example/pokedexclone/PokemonType.kt
@@ -0,0 +1,11 @@
+package com.example.pokedexclone
+
+enum class PokemonType(val typeName: String, val backgroundColor: Int) {
+ GRASS("풀", R.color.grass_type),
+ POISON("독", R.color.poison_type),
+ FIRE("불꽃", R.color.fire_type),
+ FLYING("비행", R.color.flying_type),
+ WATER("물", R.color.water_type),
+ BUG("벌레", R.color.bug_type),
+ NORMAL("노말", R.color.normal_type)
+}
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/ic_launcher_background.xml b/Heather/PokedexClone/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..07d5da9c
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/ic_launcher_foreground.xml b/Heather/PokedexClone/app/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 00000000..2b068d11
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/ic_pokeball.png b/Heather/PokedexClone/app/src/main/res/drawable/ic_pokeball.png
new file mode 100644
index 00000000..608fd96b
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/ic_pokeball.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_beedrill.png b/Heather/PokedexClone/app/src/main/res/drawable/img_beedrill.png
new file mode 100644
index 00000000..c37bd2e6
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_beedrill.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_blastoise.png b/Heather/PokedexClone/app/src/main/res/drawable/img_blastoise.png
new file mode 100644
index 00000000..7af9de87
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_blastoise.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_bulbasaur.png b/Heather/PokedexClone/app/src/main/res/drawable/img_bulbasaur.png
new file mode 100644
index 00000000..ff6d4166
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_bulbasaur.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_butterfree.png b/Heather/PokedexClone/app/src/main/res/drawable/img_butterfree.png
new file mode 100644
index 00000000..ea0dfeaf
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_butterfree.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_caterpie.png b/Heather/PokedexClone/app/src/main/res/drawable/img_caterpie.png
new file mode 100644
index 00000000..b9a9b71d
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_caterpie.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_charizard.png b/Heather/PokedexClone/app/src/main/res/drawable/img_charizard.png
new file mode 100644
index 00000000..4c4fb917
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_charizard.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_charmander.png b/Heather/PokedexClone/app/src/main/res/drawable/img_charmander.png
new file mode 100644
index 00000000..6b91d79a
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_charmander.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_charmeleon.png b/Heather/PokedexClone/app/src/main/res/drawable/img_charmeleon.png
new file mode 100644
index 00000000..8bf51519
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_charmeleon.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_ivysaur.png b/Heather/PokedexClone/app/src/main/res/drawable/img_ivysaur.png
new file mode 100644
index 00000000..bab075ed
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_ivysaur.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_kakuna.png b/Heather/PokedexClone/app/src/main/res/drawable/img_kakuna.png
new file mode 100644
index 00000000..97d03048
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_kakuna.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_metapod.png b/Heather/PokedexClone/app/src/main/res/drawable/img_metapod.png
new file mode 100644
index 00000000..22941938
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_metapod.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_squirtle.png b/Heather/PokedexClone/app/src/main/res/drawable/img_squirtle.png
new file mode 100644
index 00000000..299b74d9
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_squirtle.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_venusaur.png b/Heather/PokedexClone/app/src/main/res/drawable/img_venusaur.png
new file mode 100644
index 00000000..969dae82
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_venusaur.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_wartortle.png b/Heather/PokedexClone/app/src/main/res/drawable/img_wartortle.png
new file mode 100644
index 00000000..88d620ce
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_wartortle.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/drawable/img_weedle.png b/Heather/PokedexClone/app/src/main/res/drawable/img_weedle.png
new file mode 100644
index 00000000..b3ffa323
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/drawable/img_weedle.png differ
diff --git a/Heather/PokedexClone/app/src/main/res/layout/activity_main.xml b/Heather/PokedexClone/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..e28cf92c
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/layout/item_pokemon.xml b/Heather/PokedexClone/app/src/main/res/layout/item_pokemon.xml
new file mode 100644
index 00000000..536b9650
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/layout/item_pokemon.xml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-anydpi/ic_launcher.xml b/Heather/PokedexClone/app/src/main/res/mipmap-anydpi/ic_launcher.xml
new file mode 100644
index 00000000..6f3b755b
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/mipmap-anydpi/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/Heather/PokedexClone/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
new file mode 100644
index 00000000..6f3b755b
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/mipmap-anydpi/ic_launcher_round.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/Heather/PokedexClone/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 00000000..c209e78e
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/Heather/PokedexClone/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..b2dfe3d1
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/Heather/PokedexClone/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 00000000..4f0f1d64
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/Heather/PokedexClone/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..62b611da
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/Heather/PokedexClone/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 00000000..948a3070
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/Heather/PokedexClone/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..1b9a6956
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/Heather/PokedexClone/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..28d4b77f
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/Heather/PokedexClone/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9287f508
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/Heather/PokedexClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..aa7d6427
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/Heather/PokedexClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9126ae37
Binary files /dev/null and b/Heather/PokedexClone/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/Heather/PokedexClone/app/src/main/res/values-night/themes.xml b/Heather/PokedexClone/app/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..1b3affa8
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/values/colors.xml b/Heather/PokedexClone/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..a2cbadaf
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/values/colors.xml
@@ -0,0 +1,18 @@
+
+
+ #FF000000
+ #FFFFFFFF
+
+ #DEEDD9
+ #FFE6E6
+ #D9F1FF
+ #F2ECE3
+
+ #82C274
+ #B884DD
+ #EF7374
+ #ADD2F5
+ #74ACF5
+ #B8C26A
+ #C1C2C1
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/values/strings.xml b/Heather/PokedexClone/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..4361aabd
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ PokedexClone
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/values/themes.xml b/Heather/PokedexClone/app/src/main/res/values/themes.xml
new file mode 100644
index 00000000..991d12f3
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/values/themes.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/xml/backup_rules.xml b/Heather/PokedexClone/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 00000000..fa0f996d
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/main/res/xml/data_extraction_rules.xml b/Heather/PokedexClone/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 00000000..9ee9997b
--- /dev/null
+++ b/Heather/PokedexClone/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/PokedexClone/app/src/test/java/com/example/pokedexclone/ExampleUnitTest.kt b/Heather/PokedexClone/app/src/test/java/com/example/pokedexclone/ExampleUnitTest.kt
new file mode 100644
index 00000000..4372d6f2
--- /dev/null
+++ b/Heather/PokedexClone/app/src/test/java/com/example/pokedexclone/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package com.example.pokedexclone
+
+import org.junit.Test
+
+import org.junit.Assert.*
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
\ No newline at end of file
diff --git a/Heather/PokedexClone/build.gradle.kts b/Heather/PokedexClone/build.gradle.kts
new file mode 100644
index 00000000..922f5511
--- /dev/null
+++ b/Heather/PokedexClone/build.gradle.kts
@@ -0,0 +1,5 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ alias(libs.plugins.android.application) apply false
+ alias(libs.plugins.kotlin.android) apply false
+}
\ No newline at end of file
diff --git a/Heather/PokedexClone/gradle.properties b/Heather/PokedexClone/gradle.properties
new file mode 100644
index 00000000..20e2a015
--- /dev/null
+++ b/Heather/PokedexClone/gradle.properties
@@ -0,0 +1,23 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. For more details, visit
+# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/Heather/PokedexClone/gradle/libs.versions.toml b/Heather/PokedexClone/gradle/libs.versions.toml
new file mode 100644
index 00000000..04e14fbc
--- /dev/null
+++ b/Heather/PokedexClone/gradle/libs.versions.toml
@@ -0,0 +1,26 @@
+[versions]
+agp = "8.6.0"
+kotlin = "1.9.0"
+coreKtx = "1.15.0"
+junit = "4.13.2"
+junitVersion = "1.2.1"
+espressoCore = "3.6.1"
+appcompat = "1.7.0"
+material = "1.12.0"
+activity = "1.9.3"
+constraintlayout = "2.2.0"
+
+[libraries]
+androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
+androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
+androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
+androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
+
diff --git a/Heather/PokedexClone/gradle/wrapper/gradle-wrapper.jar b/Heather/PokedexClone/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..e708b1c0
Binary files /dev/null and b/Heather/PokedexClone/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/Heather/PokedexClone/gradle/wrapper/gradle-wrapper.properties b/Heather/PokedexClone/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..9801543f
--- /dev/null
+++ b/Heather/PokedexClone/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Sun Nov 17 22:40:59 KST 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/Heather/PokedexClone/gradlew b/Heather/PokedexClone/gradlew
new file mode 100755
index 00000000..4f906e0c
--- /dev/null
+++ b/Heather/PokedexClone/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/Heather/PokedexClone/gradlew.bat b/Heather/PokedexClone/gradlew.bat
new file mode 100644
index 00000000..ac1b06f9
--- /dev/null
+++ b/Heather/PokedexClone/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/Heather/PokedexClone/settings.gradle.kts b/Heather/PokedexClone/settings.gradle.kts
new file mode 100644
index 00000000..54b3721a
--- /dev/null
+++ b/Heather/PokedexClone/settings.gradle.kts
@@ -0,0 +1,23 @@
+pluginManagement {
+ repositories {
+ google {
+ content {
+ includeGroupByRegex("com\\.android.*")
+ includeGroupByRegex("com\\.google.*")
+ includeGroupByRegex("androidx.*")
+ }
+ }
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.name = "PokedexClone"
+include(":app")
diff --git a/Heather/UMCStudy/app/build.gradle.kts b/Heather/UMCStudy/app/build.gradle.kts
index aa79c32c..9e9c4ef6 100644
--- a/Heather/UMCStudy/app/build.gradle.kts
+++ b/Heather/UMCStudy/app/build.gradle.kts
@@ -49,7 +49,16 @@ dependencies {
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
+// implementation(libs.androidx.lifecycle.runtime.android)
+// implementation(libs.androidx.lifecycle.runtime.desktop)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
+
+ implementation("androidx.core:core-splashscreen:1.0.0")
+ implementation("androidx.activity:activity-ktx:1.9.2")
+ implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.5")
+ implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.5")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
+
}
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/AndroidManifest.xml b/Heather/UMCStudy/app/src/main/AndroidManifest.xml
index 5a08d87c..a90c2a3b 100644
--- a/Heather/UMCStudy/app/src/main/AndroidManifest.xml
+++ b/Heather/UMCStudy/app/src/main/AndroidManifest.xml
@@ -13,10 +13,16 @@
android:theme="@style/Theme.UMCStudy"
tools:targetApi="31">
+
+
diff --git a/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/BoardFragment.kt b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/BoardFragment.kt
new file mode 100644
index 00000000..466f9083
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/BoardFragment.kt
@@ -0,0 +1,59 @@
+package com.example.umcstudy
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [BoardFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class BoardFragment : Fragment() {
+ // TODO: Rename and change types of parameters
+ private var param1: String? = null
+ private var param2: String? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ param1 = it.getString(ARG_PARAM1)
+ param2 = it.getString(ARG_PARAM2)
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_board, container, false)
+ }
+
+ companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @param param1 Parameter 1.
+ * @param param2 Parameter 2.
+ * @return A new instance of fragment BoardFragment.
+ */
+ // TODO: Rename and change types and number of parameters
+ @JvmStatic
+ fun newInstance(param1: String, param2: String) =
+ BoardFragment().apply {
+ arguments = Bundle().apply {
+ putString(ARG_PARAM1, param1)
+ putString(ARG_PARAM2, param2)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/CalendarFragment.kt b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/CalendarFragment.kt
new file mode 100644
index 00000000..5acfab4a
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/CalendarFragment.kt
@@ -0,0 +1,59 @@
+package com.example.umcstudy
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [CalendarFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class CalendarFragment : Fragment() {
+ // TODO: Rename and change types of parameters
+ private var param1: String? = null
+ private var param2: String? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ param1 = it.getString(ARG_PARAM1)
+ param2 = it.getString(ARG_PARAM2)
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_calendar, container, false)
+ }
+
+ companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @param param1 Parameter 1.
+ * @param param2 Parameter 2.
+ * @return A new instance of fragment CalendarFragment.
+ */
+ // TODO: Rename and change types and number of parameters
+ @JvmStatic
+ fun newInstance(param1: String, param2: String) =
+ CalendarFragment().apply {
+ arguments = Bundle().apply {
+ putString(ARG_PARAM1, param1)
+ putString(ARG_PARAM2, param2)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/HomeFragment.kt b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/HomeFragment.kt
new file mode 100644
index 00000000..0a7fbdd1
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/HomeFragment.kt
@@ -0,0 +1,59 @@
+package com.example.umcstudy
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [HomeFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class HomeFragment : Fragment() {
+ // TODO: Rename and change types of parameters
+ private var param1: String? = null
+ private var param2: String? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ param1 = it.getString(ARG_PARAM1)
+ param2 = it.getString(ARG_PARAM2)
+ }
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.fragment_home, container, false)
+ }
+
+ companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @param param1 Parameter 1.
+ * @param param2 Parameter 2.
+ * @return A new instance of fragment HomeFragment.
+ */
+ // TODO: Rename and change types and number of parameters
+ @JvmStatic
+ fun newInstance(param1: String, param2: String) =
+ HomeFragment().apply {
+ arguments = Bundle().apply {
+ putString(ARG_PARAM1, param1)
+ putString(ARG_PARAM2, param2)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/MainActivity.kt b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/MainActivity.kt
index 673b8339..eb3c4d10 100644
--- a/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/MainActivity.kt
+++ b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/MainActivity.kt
@@ -2,19 +2,27 @@ package com.example.umcstudy
import android.content.Intent
import android.os.Bundle
+import android.view.View
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
+import androidx.fragment.app.Fragment
import com.example.umcstudy.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
+ // 현재 위치(index)를 추적하는 변수, 애니메이션 방향 설정에 필요함
+ private var currentFragment: Int = 0
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ installSplashScreen()
+
// ViewBinding 사용
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
@@ -49,6 +57,39 @@ class MainActivity : AppCompatActivity() {
// binding.btnBack.setOnClickListener {
// finish()
// }
+
+ // BottomNavigationView 이벤트 추가
+ binding.bottomNavigation.setOnItemSelectedListener { item ->
+ val targetFragment = when (item.itemId) {
+ R.id.nav_home -> 0
+ R.id.nav_board -> 1
+ R.id.nav_calendar -> 2
+ R.id.nav_user -> 3
+ else -> 0
+ }
+ when (item.itemId) {
+ R.id.nav_home -> { // 홈 선택 시 FragmentContainerView 숨기기
+ binding.mainContainer.visibility = View.VISIBLE
+ binding.fragmentContainer.visibility = View.GONE
+ currentFragment = targetFragment
+ return@setOnItemSelectedListener true
+ }
+ R.id.nav_board -> {
+ loadFragment(BoardFragment(), targetFragment)
+ return@setOnItemSelectedListener true
+ }
+ R.id.nav_calendar -> {
+ loadFragment(CalendarFragment(), targetFragment)
+ return@setOnItemSelectedListener true
+ }
+ R.id.nav_user -> {
+ loadFragment(UserFragment(), targetFragment)
+ return@setOnItemSelectedListener true
+ }
+ }
+ false
+ }
+
}
// SecondActivity로 감정 값 전달
@@ -58,4 +99,36 @@ class MainActivity : AppCompatActivity() {
startActivity(intent)
}
+ // Fragment 로드
+ private fun loadFragment(fragment: Fragment, targetFragment: Int) {
+ // Fragment 전환될 때 메인 화면(감정 우표 선택 창) 숨기기
+ binding.mainContainer.visibility = View.GONE
+ // FragmentContainerView 보이게 하기
+ binding.fragmentContainer.visibility = View.VISIBLE
+
+ val transaction = supportFragmentManager.beginTransaction()
+
+ // 현재 프래그먼트 위치에 따른 애니메이션 설정
+ // Home -> Board -> Calendar -> User
+ if (currentFragment < targetFragment) {
+ // 왼쪽에서 오른쪽으로 이동
+ transaction.setCustomAnimations(
+ R.anim.slide_in_right,
+ R.anim.slide_out_left
+ )
+ } else if (currentFragment > targetFragment) {
+ // 오른쪽에서 왼쪽으로 이동
+ transaction.setCustomAnimations(
+ R.anim.slide_in_left,
+ R.anim.slide_out_right
+ )
+ }
+
+ transaction.replace(R.id.fragment_container, fragment)
+ .addToBackStack(null)
+ .commit()
+
+ currentFragment = targetFragment // 현재 위치 업데이트
+ }
+
}
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/SplashActivity.kt b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/SplashActivity.kt
new file mode 100644
index 00000000..6f78e36c
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/SplashActivity.kt
@@ -0,0 +1,25 @@
+package com.example.umcstudy
+
+import android.content.Intent
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+
+class SplashActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ setContentView(R.layout.activity_splash)
+
+ Handler(Looper.getMainLooper()).postDelayed({
+
+ val intent = Intent(this, MainActivity::class.java)
+ startActivity(intent)
+
+ finish()
+
+ }, 2000)
+ }
+}
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/StopwatchActivity.kt b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/StopwatchActivity.kt
new file mode 100644
index 00000000..01ad68ad
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/StopwatchActivity.kt
@@ -0,0 +1,109 @@
+package com.example.umcstudy
+
+import android.os.Bundle
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import com.example.umcstudy.databinding.ActivityStopwatchBinding
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.cancelChildren
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.isActive
+import kotlinx.coroutines.launch
+
+class StopwatchActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityStopwatchBinding
+ private var currentTimeMillis = 0L
+ private var isRunning = false
+ private var coroutineScope = CoroutineScope(Dispatchers.Main + Job())
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ binding = ActivityStopwatchBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
+ val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
+ insets
+ }
+
+ setupUI()
+ }
+
+ private fun setupUI() {
+ binding.startPauseBtn.setOnClickListener {
+ if (isRunning) {
+ pause()
+ } else {
+ start()
+ }
+ updateStartPauseButton()
+ }
+
+ binding.clearBtn.setOnClickListener {
+ clear()
+ }
+ }
+
+ // 스톱워치 시작 함수
+ private fun start() {
+ if (isRunning) return
+
+ isRunning = true
+ coroutineScope.launch {
+ val startTime = System.currentTimeMillis()
+ while (isActive) { // 코루틴이 활성화되어 있는 동안 반복
+ currentTimeMillis = System.currentTimeMillis() - startTime
+ binding.stopwatchTv.text = formatTime(currentTimeMillis)
+ delay(10) // 10ms 마다 업데이트(성능 최적화)
+ }
+ }
+ }
+
+ // 스톱워치 일시 정지 함수
+ private fun pause() {
+ isRunning = false
+ coroutineScope.coroutineContext.cancelChildren() // 실행 중인 코루틴 취소
+ updateStartPauseButton()
+ }
+
+ // 스톱워치 초기화 함수
+ private fun clear() {
+ coroutineScope.coroutineContext.cancelChildren()
+ currentTimeMillis = 0L // 시간 초기화
+ binding.stopwatchTv.text = "00:00,00"
+
+ if (isRunning) {
+ // 실행 중이면 0부터 다시 시작
+ start()
+ } else {
+ // 정지 상태면 초기화만 수행
+ isRunning = false
+ updateStartPauseButton()
+ }
+ }
+
+ private fun updateStartPauseButton() {
+ binding.startPauseBtn.text = if (isRunning) "Pause" else "Start"
+ }
+
+ private fun formatTime(timeMillis: Long): String {
+ val minutes = (timeMillis / (1000 * 60)).toInt()
+ val seconds = (timeMillis % (1000 * 60) / 1000).toInt()
+ val centiseconds = (timeMillis % 1000 / 10).toInt()
+
+ return String.format("%02d:%02d,%02d", minutes, seconds, centiseconds)
+ }
+
+ // 액티비티가 종료될 떄 코루틴 정리
+ override fun onDestroy() {
+ super.onDestroy()
+ coroutineScope.cancel()
+ }
+}
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/UserFragment.kt b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/UserFragment.kt
new file mode 100644
index 00000000..e33f824d
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/java/com/example/umcstudy/UserFragment.kt
@@ -0,0 +1,38 @@
+package com.example.umcstudy
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.example.umcstudy.databinding.FragmentUserBinding
+
+class UserFragment : Fragment() {
+ private var _binding: FragmentUserBinding? = null
+ private val binding get() = _binding!!
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View {
+ _binding = FragmentUserBinding.inflate(inflater, container, false)
+ return binding.root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ binding.btnStopwatch.setOnClickListener {
+ val intent = Intent(requireContext(), StopwatchActivity::class.java)
+ startActivity(intent)
+ }
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ _binding = null
+ }
+
+}
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/anim/slide_in_left.xml b/Heather/UMCStudy/app/src/main/res/anim/slide_in_left.xml
new file mode 100644
index 00000000..d9a5ca34
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/anim/slide_in_left.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/anim/slide_in_right.xml b/Heather/UMCStudy/app/src/main/res/anim/slide_in_right.xml
new file mode 100644
index 00000000..6b2badf2
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/anim/slide_in_right.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/anim/slide_out_left.xml b/Heather/UMCStudy/app/src/main/res/anim/slide_out_left.xml
new file mode 100644
index 00000000..45d53878
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/anim/slide_out_left.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/anim/slide_out_right.xml b/Heather/UMCStudy/app/src/main/res/anim/slide_out_right.xml
new file mode 100644
index 00000000..9d87b562
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/anim/slide_out_right.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/drawable/color_selector.xml b/Heather/UMCStudy/app/src/main/res/drawable/color_selector.xml
new file mode 100644
index 00000000..b270d171
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/drawable/color_selector.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_board.xml b/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_board.xml
new file mode 100644
index 00000000..15423819
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_board.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_calendar.xml b/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_calendar.xml
new file mode 100644
index 00000000..d3c9af15
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_calendar.xml
@@ -0,0 +1,13 @@
+
+
+
diff --git a/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_home.xml b/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_home.xml
new file mode 100644
index 00000000..95665993
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_home.xml
@@ -0,0 +1,18 @@
+
+
+
+
diff --git a/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_user.xml b/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_user.xml
new file mode 100644
index 00000000..808fa82e
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/drawable/ic_nav_user.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/Heather/UMCStudy/app/src/main/res/drawable/img_postbox.xml b/Heather/UMCStudy/app/src/main/res/drawable/img_postbox.xml
new file mode 100644
index 00000000..42f6d012
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/drawable/img_postbox.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Heather/UMCStudy/app/src/main/res/drawable/rounded_button_bg.xml b/Heather/UMCStudy/app/src/main/res/drawable/rounded_button_bg.xml
new file mode 100644
index 00000000..057c41a4
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/drawable/rounded_button_bg.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/layout/activity_main.xml b/Heather/UMCStudy/app/src/main/res/layout/activity_main.xml
index 2418face..f49c8052 100644
--- a/Heather/UMCStudy/app/src/main/res/layout/activity_main.xml
+++ b/Heather/UMCStudy/app/src/main/res/layout/activity_main.xml
@@ -8,173 +8,204 @@
android:background="@drawable/bg_paper"
tools:context=".MainActivity">
-
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ app:layout_constraintEnd_toEndOf="parent" />
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/layout/activity_splash.xml b/Heather/UMCStudy/app/src/main/res/layout/activity_splash.xml
new file mode 100644
index 00000000..63d11b08
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/layout/activity_splash.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/layout/activity_stopwatch.xml b/Heather/UMCStudy/app/src/main/res/layout/activity_stopwatch.xml
new file mode 100644
index 00000000..30983fb4
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/layout/activity_stopwatch.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/layout/fragment_board.xml b/Heather/UMCStudy/app/src/main/res/layout/fragment_board.xml
new file mode 100644
index 00000000..3a954de0
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/layout/fragment_board.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/layout/fragment_calendar.xml b/Heather/UMCStudy/app/src/main/res/layout/fragment_calendar.xml
new file mode 100644
index 00000000..f801317f
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/layout/fragment_calendar.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/layout/fragment_home.xml b/Heather/UMCStudy/app/src/main/res/layout/fragment_home.xml
new file mode 100644
index 00000000..6b787adc
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/layout/fragment_home.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/layout/fragment_user.xml b/Heather/UMCStudy/app/src/main/res/layout/fragment_user.xml
new file mode 100644
index 00000000..ccca6090
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/layout/fragment_user.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/menu/bottom_nav_menu.xml b/Heather/UMCStudy/app/src/main/res/menu/bottom_nav_menu.xml
new file mode 100644
index 00000000..3fb8dad5
--- /dev/null
+++ b/Heather/UMCStudy/app/src/main/res/menu/bottom_nav_menu.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/values/strings.xml b/Heather/UMCStudy/app/src/main/res/values/strings.xml
index 4a2088c9..439d3635 100644
--- a/Heather/UMCStudy/app/src/main/res/values/strings.xml
+++ b/Heather/UMCStudy/app/src/main/res/values/strings.xml
@@ -1,3 +1,5 @@
UMCStudy
+
+ Hello blank fragment
\ No newline at end of file
diff --git a/Heather/UMCStudy/app/src/main/res/values/themes.xml b/Heather/UMCStudy/app/src/main/res/values/themes.xml
index dc9f2818..506d0d1e 100644
--- a/Heather/UMCStudy/app/src/main/res/values/themes.xml
+++ b/Heather/UMCStudy/app/src/main/res/values/themes.xml
@@ -4,5 +4,11 @@
+
+
\ No newline at end of file
diff --git a/Heather/UMCStudy/gradle/libs.versions.toml b/Heather/UMCStudy/gradle/libs.versions.toml
index 4679d4c8..1e8e2634 100644
--- a/Heather/UMCStudy/gradle/libs.versions.toml
+++ b/Heather/UMCStudy/gradle/libs.versions.toml
@@ -9,6 +9,8 @@ appcompat = "1.6.1"
material = "1.10.0"
activity = "1.8.0"
constraintlayout = "2.1.4"
+lifecycleRuntimeAndroid = "2.8.7"
+lifecycleRuntimeDesktop = "2.8.7"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -19,6 +21,8 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
androidx-activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+androidx-lifecycle-runtime-android = { group = "androidx.lifecycle", name = "lifecycle-runtime-android", version.ref = "lifecycleRuntimeAndroid" }
+androidx-lifecycle-runtime-desktop = { group = "androidx.lifecycle", name = "lifecycle-runtime-desktop", version.ref = "lifecycleRuntimeDesktop" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }