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 @@ + + + + + +