diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e5cbb64..0000000 --- a/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -# Gradle files -.gradle/ -build/ - -# Local configuration file (sdk path, etc) -local.properties - -# Log/OS Files -*.log - -# Android Studio generated files and folders -captures/ -.externalNativeBuild/ -.cxx/ -*.aab -*.apk -output-metadata.json - -# IntelliJ -*.iml -.idea/ -misc.xml -deploymentTargetDropDown.xml -render.experimental.xml - -# Keystore files -*.jks -*.keystore - -# Google Services (e.g. APIs or Firebase) -google-services.json - -# Android Profiling -*.hprof diff --git a/README.md b/README.md deleted file mode 100644 index 904e458..0000000 --- a/README.md +++ /dev/null @@ -1,49 +0,0 @@ -# πŸ’š Android A πŸ’š - -DGU-UMC 9κΈ° Android μŠ€ν„°λ”” Aμ‘° - -## πŸ’» Member - -| λ°•λ°•μ§€ν˜„ | λ°•λ°•μ§€ν˜„ | λ°•λ°•μ§€ν˜„ | λ°•λ°•μ§€ν˜„ | -| :-----------------------------------: | :-----------------------------------: | :-----------------------------------: | :-----------------------------------: | -| [λ°•μ§€ν˜„](https://github.com/wlgusqkr) | [λ°•μ§€ν˜„](https://github.com/wlgusqkr) | [λ°•μ§€ν˜„](https://github.com/wlgusqkr) | [λ°•μ§€ν˜„](https://github.com/wlgusqkr) | - -## 🌳 branch κ·œμΉ™ - -```bash -β”œβ”€main - β”œβ”€Ean/main - β”‚ └─Ean/#1 -``` - -1. `λ‹‰λ„€μž„/main 브랜치`κ°€ κΈ°λ³Έ 브랜치둜 pr 보낼 λ•Œ main λΈŒλžœμΉ˜κ°€ μ•„λ‹Œ λ‹‰λ„€μž„/main 브랜치둜 μ˜¬λ¦½λ‹ˆλ‹€. -2. λ§€μ£Ό μ‹€μŠ΅, λ―Έμ…˜μ€ 각자의 λ‹‰λ„€μž„/main 브랜치λ₯Ό base 브랜치둜 μ‚Όμ•„ `λ‹‰λ„€μž„/이슈번호 브랜치`λ₯Ό μƒμ„±ν•˜μ—¬ κ΄€λ ¨ νŒŒμΌμ„ μ—…λ‘œλ“œν•©λ‹ˆλ‹€. -3. λͺ¨λ“  νŒ€μ›λ“€μ˜ approveλ₯Ό λ°›μœΌλ©΄, pr을 λ¨Έμ§€ν•©λ‹ˆλ‹€. approve와 mergeλŠ” μŠ€ν„°λ”” μ§„ν–‰ 쀑에 μ΄λ£¨μ–΄μ§‘λ‹ˆλ‹€. - -## πŸ“‚ 디렉터리 κ·œμΉ™ - -```bash -β”œβ”€λ‹‰λ„€μž„ - β”œβ”€λ―Έμ…˜μ΄λ¦„ (예: week1, flo_clone) - β”‚ β””β”€ν”„λ‘œμ νŠΈλͺ… - β”œβ”€λ―Έμ…˜μ΄λ¦„ - β”‚ β””β”€ν”„λ‘œμ νŠΈλͺ… -``` - -## πŸ”– 컀밋 μ»¨λ²€μ…˜ - -1. 컀밋에 ν•΄λ‹Ήν•˜λŠ” 컀밋 λ©”μ‹œμ§€ μ“°κΈ° (예: [parkparkjihyeon/#1] mission {λ‚΄μš©} ) - -| Message | μ„€λͺ… | -| :------: | :-------------------- | -| mission | λ―Έμ…˜ μˆ˜ν–‰ | -| practice | μ‹€μŠ΅ μˆ˜ν–‰ | -| keyword | ν‚€μ›Œλ“œ 정리 | -| workbook | μ›Œν¬λΆ 정리 | -| fix | 버그 μˆ˜μ • | -| docs | λ¬Έμ„œ μˆ˜μ • | -| comment | 주석 μΆ”κ°€ 및 λ³€κ²½ | -| test | ν…ŒμŠ€νŠΈ μ½”λ“œ μΆ”κ°€ | -| rename | 파일 ν˜Ήμ€ 폴더λͺ… μˆ˜μ • | -| remove | 파일 ν˜Ήμ€ 폴더 μ‚­μ œ | -| chore | 기타 변경사항 | diff --git a/backy/test.txt b/backy/test.txt deleted file mode 100644 index e69de29..0000000 diff --git a/bongbak/week2/.idea/studiobot.xml b/bongbak/week2/.idea/studiobot.xml new file mode 100644 index 0000000..539e3b8 --- /dev/null +++ b/bongbak/week2/.idea/studiobot.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/bongbak/week2/.kotlin/errors/errors-1762774619558.log b/bongbak/week2/.kotlin/errors/errors-1762774619558.log new file mode 100644 index 0000000..1219b50 --- /dev/null +++ b/bongbak/week2/.kotlin/errors/errors-1762774619558.log @@ -0,0 +1,4 @@ +kotlin version: 2.0.21 +error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output: + 1. Kotlin compile daemon is ready + diff --git a/bongbak/week2/.kotlin/errors/errors-1762851684314.log b/bongbak/week2/.kotlin/errors/errors-1762851684314.log new file mode 100644 index 0000000..1219b50 --- /dev/null +++ b/bongbak/week2/.kotlin/errors/errors-1762851684314.log @@ -0,0 +1,4 @@ +kotlin version: 2.0.21 +error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output: + 1. Kotlin compile daemon is ready + diff --git a/bongbak/week2/app/build.gradle.kts b/bongbak/week2/app/build.gradle.kts index 1c955a1..0acb416 100644 --- a/bongbak/week2/app/build.gradle.kts +++ b/bongbak/week2/app/build.gradle.kts @@ -1,8 +1,8 @@ -import org.jetbrains.kotlin.storage.CacheResetOnProcessCanceled.enabled plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.android) + kotlin("kapt") } @@ -45,6 +45,7 @@ android { } dependencies { + implementation("com.google.code.gson:gson:2.10.1") implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.material) @@ -54,4 +55,16 @@ dependencies { testImplementation(libs.junit) androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.espresso.core) + implementation("androidx.core:core-splashscreen:1.0.1") + implementation("me.relex:circleindicator:2.1.6") + implementation("androidx.room:room-ktx:2.6.1") + implementation("androidx.room:room-runtime:2.6.1") + kapt("androidx.room:room-compiler:2.6.1") + implementation("com.squareup.retrofit2:retrofit:2.9.0") + implementation("com.squareup.retrofit2:converter-gson:2.9.0") + implementation("com.squareup.retrofit2:adapter-rxjava2:2.9.0") + implementation("com.squareup.okhttp3:okhttp:4.12.0") + implementation("com.squareup.okhttp3:logging-interceptor:4.12.0") + implementation("com.github.bumptech.glide:glide:4.16.0") + kapt("com.github.bumptech.glide:compiler:4.16.0") } \ No newline at end of file diff --git a/bongbak/week2/app/src/main/AndroidManifest.xml b/bongbak/week2/app/src/main/AndroidManifest.xml index a9b0652..2858e63 100644 --- a/bongbak/week2/app/src/main/AndroidManifest.xml +++ b/bongbak/week2/app/src/main/AndroidManifest.xml @@ -1,11 +1,9 @@ - + + + + android:theme="@style/SplashTheme"> - - + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/Album.kt b/bongbak/week2/app/src/main/java/com/example/mission2/Album.kt new file mode 100644 index 0000000..4d3189f --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/Album.kt @@ -0,0 +1,13 @@ +package com.example.mission2 + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName="AlbumTable") +data class Album( + @PrimaryKey(autoGenerate = false) var id:Int=0, + var title:String?="", + var singer:String?="", + var coverImg : Int? =null, + var isLike: Boolean = false, +) diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/AlbumDao.kt b/bongbak/week2/app/src/main/java/com/example/mission2/AlbumDao.kt new file mode 100644 index 0000000..de44320 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/AlbumDao.kt @@ -0,0 +1,28 @@ +package com.example.mission2 + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query + +@Dao +interface AlbumDao { + + @Insert + fun insert(albume:Album) + + @Query("SELECT*FROM AlbumTable") + fun getAlbums():List + + @Insert + fun likeAlbum(like: Like) + + @Query("SELECT id FROM LikeTable WHERE userId=:userId AND albumId=:albumId") + fun isLikedAlbum(userId:Int, albumId:Int) : Int? + + @Query("DELETE FROM LikeTable WHERE userId=:userId AND albumId=:albumId") + fun disLikedAlbum(userId:Int, albumId:Int) : Int? + + @Query("SELECT AT .* FROM LikeTable as LT LEFT JOIN AlbumTable as AT ON LT.albumId=AT.id WHERE LT.userId= :userId") + fun getLikedAlbums(userId:Int) : List + +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/AlbumFragment.kt b/bongbak/week2/app/src/main/java/com/example/mission2/AlbumFragment.kt index 5f2eaed..f107a8c 100644 --- a/bongbak/week2/app/src/main/java/com/example/mission2/AlbumFragment.kt +++ b/bongbak/week2/app/src/main/java/com/example/mission2/AlbumFragment.kt @@ -4,16 +4,21 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import com.example.mission2.databinding.FragmentAlbumBinding import com.example.mission2.databinding.FragmentSongBinding import com.google.android.material.tabs.TabLayoutMediator +import com.google.gson.Gson class AlbumFragment : Fragment() { private val information=arrayListOf("수둝곑","상세정보","μ˜μƒ") lateinit var binding : FragmentAlbumBinding + private var gson: Gson =Gson() + + private var isLiked:Boolean=false override fun onCreateView( inflater : LayoutInflater, @@ -30,6 +35,15 @@ class AlbumFragment : Fragment() { .replace(R.id.main_frm, HomeFragment()).commitAllowingStateLoss() } + + + val albumJson=arguments?.getString("album") + val album=gson.fromJson(albumJson,Album::class.java) + isLiked=isLikedAlbum(album.id) + + setInit(album) + setOnClickListeners(album) + val albumAdapter = AlbumVPAdapter(this,titleFromTextView,composerFromTextView) binding.albumContentVp.adapter=albumAdapter TabLayoutMediator(binding.albumContentTb, binding.albumContentVp) { tab, position -> @@ -38,4 +52,55 @@ class AlbumFragment : Fragment() { 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() + if(isLiked){ + binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_on) + } + else{ + binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_off) + } + } + private fun getJwt(): Int { + val spf = activity?.getSharedPreferences("auth", AppCompatActivity.MODE_PRIVATE) + return spf!!.getInt("jwt", 0) + } + private fun likeAlbum(userId:Int,albumId:Int){ + val songDB=SongDatabase.getInstance(requireContext())!! + val like=Like(userId,albumId) + + songDB.AlbumDao().likeAlbum(like) + } + + private fun isLikedAlbum(albumId:Int):Boolean{ + val songDB= SongDatabase.getInstance(requireContext())!! + val userId=getJwt() + + val likeId : Int? =songDB.AlbumDao().isLikedAlbum(userId,albumId) + + return likeId!=null + } + + private fun disLikedAlbum(albumId:Int){ + val songDB= SongDatabase.getInstance(requireContext())!! + val userId=getJwt() + + val likeId : Int? =songDB.AlbumDao().disLikedAlbum(userId,albumId) + } + + private fun setOnClickListeners(album:Album){ + val userId=getJwt() + binding.albumLikeIv.setOnClickListener { + if(isLiked){ + binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_off) + disLikedAlbum(album.id) + } + else{ + binding.albumLikeIv.setImageResource(R.drawable.ic_my_like_on) + likeAlbum(userId, album.id) + } + } + } } diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/AlbumRVAdapter.kt b/bongbak/week2/app/src/main/java/com/example/mission2/AlbumRVAdapter.kt new file mode 100644 index 0000000..0ba4a07 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/AlbumRVAdapter.kt @@ -0,0 +1,60 @@ +package com.example.mission2 + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.example.mission2.databinding.ItemAlbumBinding + +class AlbumRVAdapter(private val albumList:ArrayList): RecyclerView.Adapter(){ + + interface MyItemClickListener{ + fun onItemClick(album: Album) + fun onRemoveAlbum(position:Int) + fun onPlayClick(album: Album) + } + + private lateinit var myItemClickListener: MyItemClickListener + fun setMyItemClickListener(itemClickListener: MyItemClickListener){ + myItemClickListener=itemClickListener + } + + fun addItem(album:Album){ + albumList.add(album) + notifyDataSetChanged() + } + fun removeItem(position:Int){ + albumList.removeAt(position) + notifyDataSetChanged() + } + + override fun onCreateViewHolder( + viewGroup: ViewGroup, + viewType: Int + ): AlbumRVAdapter.ViewHolder { + + val binding: ItemAlbumBinding=ItemAlbumBinding.inflate(LayoutInflater.from(viewGroup.context),viewGroup,false) + + return ViewHolder(binding) + } + + override fun onBindViewHolder(holder: AlbumRVAdapter.ViewHolder, position: Int) { + holder.bind(albumList[position]) + holder.itemView.setOnClickListener { myItemClickListener.onItemClick(albumList[position])} +// holder.binding.itemAlbumTitleTv.setOnClickListener { myItemClickListener.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.itemAlbumSingerNameTv.text=album.singer + binding.itemAlbumCoverImgIv.setImageResource(album.coverImg!!) + + binding.itemAlbumPlayImgIv.setOnClickListener { + myItemClickListener.onPlayClick(album) + } + + } + } +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/HomeFragment.kt b/bongbak/week2/app/src/main/java/com/example/mission2/HomeFragment.kt index c716999..2ee62ef 100644 --- a/bongbak/week2/app/src/main/java/com/example/mission2/HomeFragment.kt +++ b/bongbak/week2/app/src/main/java/com/example/mission2/HomeFragment.kt @@ -1,15 +1,41 @@ package com.example.mission2 +import android.content.Context import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.core.view.doOnAttach import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager import androidx.viewpager2.widget.ViewPager2 import com.example.mission2.databinding.FragmentHomeBinding +import com.google.gson.Gson +import me.relex.circleindicator.CircleIndicator3 + class HomeFragment : Fragment() { lateinit var binding: FragmentHomeBinding + private val albumDatas = ArrayList() + private val handler = Handler(Looper.getMainLooper()) + private lateinit var songDB : SongDatabase + private lateinit var sliderRunnable: Runnable + override fun onAttach(context: Context) { + super.onAttach(context) + if (context is OnSongPlayListener) { + songPlayListener = context + } else { + throw RuntimeException("$context must implement OnSongPlayListener") + } + } + + interface OnSongPlayListener { + fun onSongPlayed(title: String?, singer: String?) + } + + private lateinit var songPlayListener: OnSongPlayListener override fun onCreateView( inflater: LayoutInflater, @@ -18,26 +44,74 @@ class HomeFragment : Fragment() { ): View { binding = FragmentHomeBinding.inflate(inflater, container, false) - binding.homeAlbumImgIv1.setOnClickListener { - (context as MainActivity).supportFragmentManager.beginTransaction() - .replace(R.id.main_frm , AlbumFragment()) - .commitAllowingStateLoss() - } +// binding.homeAlbumImgIv1.setOnClickListener { +// (context as MainActivity).supportFragmentManager.beginTransaction() +// .replace(R.id.main_frm , AlbumFragment()) +// .commitAllowingStateLoss() +// } + // 데이터 리슀트 생성 더미 데이터 + songDB=SongDatabase.getInstance(requireContext())!! + albumDatas.addAll(songDB.AlbumDao().getAlbums()) + + 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) + } - val bannerAdapter= BannerVPAdapter(this) + override fun onPlayClick(album: Album) { + songPlayListener.onSongPlayed(album.title, album.singer) + } + }) + + + 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 + binding.homeBannerVp.adapter = bannerAdapter + binding.homeBannerVp.orientation = ViewPager2.ORIENTATION_HORIZONTAL + - val homePannelAdapter= HomePannelVPAdapter(this) + val homePannelAdapter = HomePannelVPAdapter(this) homePannelAdapter.addFragment(HomePannelFragment(R.drawable.img_first_album_default)) homePannelAdapter.addFragment(HomePannelFragment(R.drawable.img_second_album)) - homePannelAdapter.addFragment(HomePannelFragment(R.drawable.img_third_album)) - binding.homePannelBackgroundVp.adapter=homePannelAdapter - binding.homePannelBackgroundVp.orientation=ViewPager2.ORIENTATION_HORIZONTAL + binding.homePannelBackgroundVp.adapter = homePannelAdapter + binding.homePannelBackgroundVp.orientation = ViewPager2.ORIENTATION_HORIZONTAL + binding.homePannelCi.setViewPager(binding.homePannelBackgroundVp) + + startAutoSlider(homePannelAdapter.itemCount) return binding.root } -} \ No newline at end of file + 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() + } + + private fun startAutoSlider(size: Int) { + sliderRunnable = Runnable { + val viewPager = binding.homePannelBackgroundVp + viewPager.currentItem = (viewPager.currentItem + 1) % size + handler.postDelayed(sliderRunnable, 3000) + } + handler.postDelayed(sliderRunnable, 3000) + } + +} + diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/Included.kt b/bongbak/week2/app/src/main/java/com/example/mission2/Included.kt new file mode 100644 index 0000000..3373434 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/Included.kt @@ -0,0 +1,6 @@ +package com.example.mission2 + +data class Included( + var title:String?="", + var singer:String?="" +) diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/Like.kt b/bongbak/week2/app/src/main/java/com/example/mission2/Like.kt new file mode 100644 index 0000000..a890fba --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/Like.kt @@ -0,0 +1,12 @@ +package com.example.mission2 + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName="LikeTable") +data class Like( + val userId:Int, + val albumId: Int +){ + @PrimaryKey(autoGenerate = true) var id:Int=0 +} diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/LockerFragment.kt b/bongbak/week2/app/src/main/java/com/example/mission2/LockerFragment.kt index 2a60cc8..45aa9c1 100644 --- a/bongbak/week2/app/src/main/java/com/example/mission2/LockerFragment.kt +++ b/bongbak/week2/app/src/main/java/com/example/mission2/LockerFragment.kt @@ -1,18 +1,20 @@ package com.example.mission2 +import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import com.example.mission2.databinding.FragmentLockerBinding import com.google.android.material.tabs.TabLayoutMediator -class LockerFragment : Fragment(){ - - private val information=arrayListOf("μ €μž₯ν•œ 곑","μŒμ•…νŒŒμΌ","μ €μž₯앨범") +class LockerFragment : Fragment() { lateinit var binding: FragmentLockerBinding + lateinit var songDB: SongDatabase + private val information = arrayListOf("μ €μž₯ν•œ 곑", "μŒμ•…νŒŒμΌ", "μ €μž₯앨범") override fun onCreateView( inflater: LayoutInflater, @@ -21,20 +23,54 @@ class LockerFragment : Fragment(){ ): View? { binding = FragmentLockerBinding.inflate(inflater, container, false) - binding.lockerPlayAllImgIv.setOnClickListener { - (context as MainActivity).supportFragmentManager.beginTransaction().replace( - R.id.main_frm, - HomeFragment() - ).commitAllowingStateLoss() - } val lockerAdapter = LockerVPAdapter(this) - binding.vpLockerLockerFragment.adapter=lockerAdapter + binding.vpLockerLockerFragment.adapter = lockerAdapter - TabLayoutMediator(binding.lockerContentTb, binding.vpLockerLockerFragment) { tab, position -> + TabLayoutMediator( + binding.lockerContentTb, + binding.vpLockerLockerFragment + ) { tab, position -> tab.text = information[position] - }.attach() + binding.lockerLoginTv.setOnClickListener { + startActivity(Intent(activity, LoginActivity::class.java)) + } + return binding.root } -} \ No newline at end of file + + override fun onStart() { + super.onStart() + initViews() + } + + private fun getJwt(): Int { + val spf = activity?.getSharedPreferences("auth", AppCompatActivity.MODE_PRIVATE) + return spf!!.getInt("jwt", 0) + } + + private fun initViews() { + val jwt: Int = getJwt() + if (jwt == 0) { + binding.lockerLoginTv.text = "둜그인" + binding.lockerLoginTv.setOnClickListener { + startActivity(Intent(activity, LoginActivity::class.java)) + } + } else { + binding.lockerLoginTv.text = "λ‘œκ·Έμ•„μ›ƒ" + binding.lockerLoginTv.setOnClickListener { + // λ‘œκ·Έμ•„μ›ƒ μ§„ν–‰ + logout() + startActivity(Intent(activity, LoginActivity::class.java)) + } + } + } + + private fun logout() { + val spf = activity?.getSharedPreferences("auth", AppCompatActivity.MODE_PRIVATE) + val editor = spf!!.edit() + editor.remove("jwt") + editor.apply() + } +} diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/LockerRVAapter.kt b/bongbak/week2/app/src/main/java/com/example/mission2/LockerRVAapter.kt new file mode 100644 index 0000000..ad40590 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/LockerRVAapter.kt @@ -0,0 +1,61 @@ +package com.example.flo + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.example.mission2.Song +import com.example.mission2.databinding.ItemSavedBinding + + +class LockerRVAapter() : + RecyclerView.Adapter() { + private val songs = ArrayList() + interface MyItemClickListener{ + fun onRemoveSong(songId: Int) + } + private lateinit var mItemClickListener : MyItemClickListener + + fun setMyItemClickListener(itemClickListener: MyItemClickListener){ + mItemClickListener = itemClickListener + } + + + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int): LockerRVAapter.ViewHolder { + val binding: ItemSavedBinding = ItemSavedBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) + + return ViewHolder(binding) + } + + override fun onBindViewHolder(holder: LockerRVAapter.ViewHolder, position: Int) { + holder.bind(songs[position]) + holder.binding.itemSavedMore01Iv.setOnClickListener { + mItemClickListener.onRemoveSong(songs[position].id) + removeSong(position) + } + } + + override fun getItemCount(): Int = songs.size + + @SuppressLint("NotifyDataSetChanged") + fun addSongs(songs: ArrayList) { + this.songs.clear() + this.songs.addAll(songs) + + notifyDataSetChanged() + } + + @SuppressLint("NotifyDataSetChanged") + private fun removeSong(position: Int){ + songs.removeAt(position) + notifyDataSetChanged() + } + + inner class ViewHolder(val binding: ItemSavedBinding) : RecyclerView.ViewHolder(binding.root){ + fun bind(song: Song){ + binding.itemSavedCoverIv.setImageResource(song.coverImg!!) + binding.itemSavedMusicTitle01Tv.text = song.title + binding.itemSavedSingerName01Tv.text = song.singer + } + } +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/LockerVPAdapter.kt b/bongbak/week2/app/src/main/java/com/example/mission2/LockerVPAdapter.kt index 940e106..8623541 100644 --- a/bongbak/week2/app/src/main/java/com/example/mission2/LockerVPAdapter.kt +++ b/bongbak/week2/app/src/main/java/com/example/mission2/LockerVPAdapter.kt @@ -3,17 +3,16 @@ package com.example.mission2 import androidx.fragment.app.Fragment; import androidx.viewpager2.adapter.FragmentStateAdapter; -import java.util.ArrayList; class LockerVPAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) { - private val fragmentlist:ArrayList = ArrayList(); - override fun getItemCount(): Int = fragmentlist.size + override fun getItemCount(): Int = 3 - override fun createFragment(position: Int): Fragment = fragmentlist[position] - - fun addFragment(fragment: Fragment){ - fragmentlist.add(fragment) - notifyItemInserted(fragmentlist.size-1) + override fun createFragment(position: Int): Fragment { + return when (position) { + 0 -> SavedFragment() + 1 -> Fragment() + else -> SalbumFragment() + } } } \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/LoginActivity.kt b/bongbak/week2/app/src/main/java/com/example/mission2/LoginActivity.kt new file mode 100644 index 0000000..22fb807 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/LoginActivity.kt @@ -0,0 +1,67 @@ +package com.example.mission2 + +import android.content.Intent +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.example.mission2.databinding.ActivityLoginBinding + +class LoginActivity : AppCompatActivity() { + lateinit var binding: ActivityLoginBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityLoginBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.loginSignUpTv.setOnClickListener { + startActivity(Intent(this, SignUpActivity::class.java)) + } + binding.loginSignInBtn.setOnClickListener { + login() + } + } + + private fun login() { + if (binding.loginIdEt.text.toString() + .isEmpty() || binding.loginDirectInputEt.text.toString().isEmpty() + ) { + Toast.makeText(this, "이메일을 μž…λ ₯ν•΄μ£Όμ„Έμš”.", Toast.LENGTH_SHORT).show() + return + } + + if (binding.loginPasswordEt.text.toString().isEmpty()) { + Toast.makeText(this, "λΉ„λ°€λ²ˆν˜Έλ₯Ό μž…λ ₯ν•΄μ£Όμ„Έμš”.", Toast.LENGTH_SHORT).show() + return + } + + val email: String=binding.loginIdEt.text.toString() + "@"+binding.loginDirectInputEt.text.toString() + val pwd:String=binding.loginPasswordEt.text.toString() + + val songDB=SongDatabase.getInstance(this)!! + val user=songDB.UserDao().getUser(email,pwd) + + user?.let{ + Log.d("LOGIN_ACT/GET_USER","userId : ${user.id},$user") + saveJwt(user.id) + startMainActivity() + return + } + + Toast.makeText(this,"직원 정보가 μ‘΄μž¬ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€", Toast.LENGTH_SHORT).show() + } + + private fun saveJwt(jwt:Int){ + val spf=getSharedPreferences("auth",MODE_PRIVATE) + val editor=spf.edit() + + editor.putInt("jwt",jwt) + editor.apply() + } + + private fun startMainActivity(){ + val intent=Intent(this, MainActivity::class.java) + startActivity(intent) + } +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/MainActivity.kt b/bongbak/week2/app/src/main/java/com/example/mission2/MainActivity.kt index dd613a1..d825414 100644 --- a/bongbak/week2/app/src/main/java/com/example/mission2/MainActivity.kt +++ b/bongbak/week2/app/src/main/java/com/example/mission2/MainActivity.kt @@ -3,33 +3,80 @@ package com.example.mission2 import android.content.Intent import androidx.appcompat.app.AppCompatActivity import android.os.Bundle +import android.util.Log +import android.widget.Toast import com.example.mission2.databinding.ActivityMainBinding -class MainActivity : AppCompatActivity() { +import com.google.gson.Gson + +class MainActivity : AppCompatActivity(),HomeFragment.OnSongPlayListener { lateinit var binding: ActivityMainBinding + private var song:Song = Song() + private var gson:Gson= Gson() + + val songs=arrayListOf() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) + inputDummySongs() + inputDummyAlbums() initBottomNavigation() - val song = Song(binding.mainMiniplayerTitleTv.text.toString(), binding.mainMiniplayerSingerTv.text.toString()) - binding.mainPlayerCl.setOnClickListener { - val intent = Intent(this, SongActivity::class.java) - } + val editor=getSharedPreferences("song",MODE_PRIVATE).edit() + editor.putInt("songId",song.id) + editor.apply() - binding.mainPlayerCl.setOnClickListener { - val intent = Intent(this,SongActivity::class.java) - intent.putExtra("title", song.title) - intent.putExtra("singer",song.singer) + val intent=Intent(this, SongActivity::class.java) startActivity(intent) + + } + binding.mainNextIv.setOnClickListener { + moveSong(+1) } + binding.mainPreviousIv.setOnClickListener { + moveSong(-1) + } + + } + override fun onSongPlayed(title: String?, singer: String?){ + binding.mainMiniplayerTitleTv.text = title + binding.mainMiniplayerSingerTv.text = singer + binding.mainMiniplayerTitleTv.text = title + binding.mainMiniplayerSingerTv.text = singer + } + private fun moveSong(direct: Int) { + val spf = getSharedPreferences("song", MODE_PRIVATE) + val songId = spf.getInt("songId", 0) + + val nowPos = getPlayingSongPosition(songId) + + val nextPos = nowPos + direct + + val newSong = songs[nextPos] + + val editor = spf.edit() + editor.putInt("songId", newSong.id) + editor.apply() + + setMiniPlayer(newSong) + + this.song = newSong } + + private fun getPlayingSongPosition(songId:Int): Int{ + for(i in 0 until songs.size){ + if(songs[i].id==songId){ + return i + } + } + return 0 + } private fun initBottomNavigation(){ supportFragmentManager.beginTransaction() @@ -68,5 +115,164 @@ class MainActivity : AppCompatActivity() { false } } + private fun setMiniPlayer(song: Song){ + binding.mainMiniplayerTitleTv.text=song.title + binding.mainMiniplayerSingerTv.text=song.singer + binding.mainMiniplayerProgressSb.progress=(song.second*100000)/song.playTime + } + + override fun onStart() { + super.onStart() + + val spf=getSharedPreferences("song",MODE_PRIVATE) + val songId=spf.getInt("songId",0) + + val songDB=SongDatabase.getInstance(this)!! + + song=if(songId==0) { + songDB.songDao().getSong(1) + } + else{ + songDB.songDao().getSong(songId) + } + Log.d("song ID",song.id.toString()) // 데이터 λ Œλ”λ§ + + setMiniPlayer(song) + } + + private fun inputDummySongs(){ + val songDB = SongDatabase.getInstance(this)!! + val allSongs = songDB.songDao().getSongs() + + if (allSongs.isNotEmpty()) { + return + } + songDB.songDao().insert( + Song( + "Lilac", + "μ•„μ΄μœ  (IU)", + 0, + 200, + false, + "music_lilac", + R.drawable.img_album_exp2, + false, + ) + ) + + songDB.songDao().insert( + Song( + "Flu", + "μ•„μ΄μœ  (IU)", + 0, + 200, + false, + "music_flu", + R.drawable.img_album_exp2, + false, + ) + ) + + songDB.songDao().insert( + Song( + "Boy with Luv", + "λ°©νƒ„μ†Œλ…„λ‹¨ (BTS)", + 0, + 230, + false, + "music_boy", + R.drawable.img_album_exp4, + false + ) + ) + + songDB.songDao().insert( + Song( + "Next Level", + "μ—μŠ€νŒŒ (AESPA)", + 0, + 210, + false, + "music_next", + R.drawable.img_album_exp3, + false, + ) + ) + + + songDB.songDao().insert( + Song( + "Boy with Luv", + "music_boy", + 0, + 230, + false, + "music_lilac", + R.drawable.img_album_exp4, + false, + ) + ) + + + songDB.songDao().insert( + Song( + "BBoom BBoom", + "λͺ¨λͺ¨λžœλ“œ (MOMOLAND)", + 0, + 240, + false, + "music_bboom", + R.drawable.img_album_exp5, + false, + ) + ) + + val _songs = songDB.songDao().getSongs() + Log.d("DB data", _songs.toString()) + } + + private fun inputDummyAlbums(){ + val songDB = SongDatabase.getInstance(this)!! + val albums = songDB.AlbumDao().getAlbums() + + if (albums.isNotEmpty()) { + return + } + songDB.AlbumDao().insert( + Album( + 0, + "IU 5th Album 'LILAC'", "μ•„μ΄μœ  (IU)", R.drawable.img_album_exp2 + ) + ) + + songDB.AlbumDao().insert( + Album( + 1, + "Butter", "λ°©νƒ„μ†Œλ…„λ‹¨ (BTS)", R.drawable.img_album_exp + ) + ) + + songDB.AlbumDao().insert( + Album( + 2, + "iScreaM Vol.10 : Next Level Remixes", "μ—μŠ€νŒŒ (AESPA)", R.drawable.img_album_exp3 + ) + ) + + songDB.AlbumDao().insert( + Album( + 3, + "MAP OF THE SOUL : PERSONA", "λ°©νƒ„μ†Œλ…„λ‹¨ (BTS)", R.drawable.img_album_exp4 + ) + ) + + songDB.AlbumDao().insert( + Album( + 4, + "GREAT!", "λͺ¨λͺ¨λžœλ“œ (MOMOLAND)", R.drawable.img_album_exp5 + ) + ) + + } } \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/Salbum.kt b/bongbak/week2/app/src/main/java/com/example/mission2/Salbum.kt new file mode 100644 index 0000000..3ac5011 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/Salbum.kt @@ -0,0 +1,8 @@ +package com.example.mission2 + +data class Salbum( + var title:String?="", + var info:String?="", + var coverImg:Int?=null, + var isPlaying: Boolean = false +) diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SalbumFragment.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SalbumFragment.kt new file mode 100644 index 0000000..4f6bcfe --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SalbumFragment.kt @@ -0,0 +1,58 @@ +package com.example.mission2 + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import com.example.mission2.databinding.FragmentSalbumBinding + +class SalbumFragment : Fragment() { + lateinit var binding: FragmentSalbumBinding + lateinit var albumDB: SongDatabase + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = FragmentSalbumBinding.inflate(inflater, container, false) + + albumDB = SongDatabase.getInstance(requireContext())!! + + return binding.root + } + + override fun onStart() { + super.onStart() + initRecyclerview() + } + + private fun initRecyclerview(){ + binding.lockerSalbumRv.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + + val albumRVAdapter = SalbumRVAdapter() + //λ¦¬μŠ€λ„ˆ 객체 생성 및 전달 + + albumRVAdapter.setMyItemClickListener(object : SalbumRVAdapter.MyItemClickListener{ + override fun onRemoveSong(songId: Int) { + albumDB.AlbumDao().getLikedAlbums(getJwt()) + } + }) + + binding.lockerSalbumRv.adapter = albumRVAdapter + + albumRVAdapter.addAlbums(albumDB.AlbumDao().getLikedAlbums(getJwt()) as ArrayList) + } + + private fun getJwt() : Int { + val spf = activity?.getSharedPreferences("auth" , AppCompatActivity.MODE_PRIVATE) + val jwt = spf!!.getInt("jwt", 0) + Log.d("MAIN_ACT/GET_JWT", "jwt_token: $jwt") + + return jwt + } +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SalbumRVAdapter.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SalbumRVAdapter.kt new file mode 100644 index 0000000..142f2e3 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SalbumRVAdapter.kt @@ -0,0 +1,59 @@ +package com.example.mission2 + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.example.mission2.databinding.ItemSalbumBinding + +class SalbumRVAdapter (): RecyclerView.Adapter() { + private val albums = ArrayList() + + interface MyItemClickListener{ + fun onRemoveSong(songId: Int) + } + + private lateinit var mItemClickListener: MyItemClickListener + + fun setMyItemClickListener(itemClickListener: MyItemClickListener){ + mItemClickListener = itemClickListener + } + + override fun onCreateViewHolder(viewGroup: ViewGroup, viewType: Int):SalbumRVAdapter.ViewHolder { + val binding: ItemSalbumBinding = ItemSalbumBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) + + return ViewHolder(binding) + } + + override fun onBindViewHolder(holder: SalbumRVAdapter.ViewHolder, position: Int) { + holder.bind(albums[position]) + holder.binding.itemSalbumMoreIv.setOnClickListener { + mItemClickListener.onRemoveSong(albums[position].id) + removeSong(position) + } + } + + override fun getItemCount(): Int = albums.size + + @SuppressLint("NotifyDataSetChanged") + fun addAlbums(albums: ArrayList) { + this.albums.clear() + this.albums.addAll(albums) + + notifyDataSetChanged() + } + + fun removeSong(position: Int){ + albums.removeAt(position) + notifyDataSetChanged() + } + + inner class ViewHolder(val binding: ItemSalbumBinding) : RecyclerView.ViewHolder(binding.root){ + fun bind(album: Album){ + binding.itemSalbumCoverIv.setImageResource(album.coverImg!!) + binding.itemSalbumTitleTv.text = album.title + binding.itemSalbumNameTv.text = album.singer + } + } + +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/Saved.kt b/bongbak/week2/app/src/main/java/com/example/mission2/Saved.kt new file mode 100644 index 0000000..2c729fc --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/Saved.kt @@ -0,0 +1,7 @@ +package com.example.mission2 + +data class Saved( + var title:String?="", + var singer:String?="", + var coverImg : Int? =null, +) diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SavedFragment.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SavedFragment.kt new file mode 100644 index 0000000..d66cb8e --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SavedFragment.kt @@ -0,0 +1,51 @@ +package com.example.mission2 + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import com.example.flo.LockerRVAapter // (이전 파일의 LockerRVAapterλ₯Ό μ‚¬μš©ν•œλ‹€κ³  κ°€μ •) +import com.example.mission2.databinding.FragmentSavedBinding + +class SavedFragment : Fragment() { + + lateinit var binding: FragmentSavedBinding + + lateinit var songDB: SongDatabase + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + binding = FragmentSavedBinding.inflate(inflater, container, false) // 바인딩 클래슀 λ³€κ²½ + + songDB = SongDatabase.getInstance(requireContext())!! + + return binding.root + } + + override fun onStart() { + super.onStart() + initRecyclerview() + } + + private fun initRecyclerview(){ + binding.lockerSavedRv.layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false) + + val lockerRVAapter = LockerRVAapter() + + lockerRVAapter.setMyItemClickListener(object : LockerRVAapter.MyItemClickListener{ + override fun onRemoveSong(songId: Int) { + songDB.songDao().updateIsLikeById(false,songId) + } + }) + + binding.lockerSavedRv.adapter = lockerRVAapter + lockerRVAapter.addSongs(songDB.songDao().getLikedSongs(true) as ArrayList) + } + +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SignUpActivity.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SignUpActivity.kt new file mode 100644 index 0000000..0dd74ba --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SignUpActivity.kt @@ -0,0 +1,47 @@ +package com.example.mission2 + +import android.os.Bundle +import android.util.Log +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.example.mission2.databinding.ActivitySignupBinding + + +class SignUpActivity: AppCompatActivity(){ + lateinit var binding: ActivitySignupBinding + + override fun onCreate(savedInstanceState: Bundle?){ + super.onCreate(savedInstanceState) + binding= ActivitySignupBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.signUpSignUpBtn.setOnClickListener { + signUp() + finish() + } + } + + private fun getUser(): User{ + val email: String=binding.signUpIdEt.text.toString() + "@"+binding.signUpDirectInputEt.text.toString() + val pwd:String=binding.signUpPasswordEt.text.toString() + + return User(email,pwd) + } + + private fun signUp(){ + if(binding.signUpIdEt.text.toString().isEmpty()||binding.signUpDirectInputEt.text.toString().isEmpty()){ + Toast.makeText(this,"이메일 ν˜•μ‹μ΄ 잘λͺ»λ˜μ—ˆμŠ΅λ‹ˆλ‹€",Toast.LENGTH_SHORT).show() + return + } + if(binding.signUpPasswordEt.text.toString()!=binding.signUpPasswordEt.text.toString()){ + Toast.makeText(this,"λΉ„λ°€λ²ˆν˜Έκ°€ μΌμΉ˜ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€",Toast.LENGTH_SHORT).show() + return + } + val userDB=SongDatabase.getInstance(this)!! + userDB.UserDao().insert(getUser()) + + val users = userDB.UserDao().getUsers() + + Log.d("SIGNUPACT", users.toString()) + } +} diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/Song.kt b/bongbak/week2/app/src/main/java/com/example/mission2/Song.kt index f1b44b1..229e034 100644 --- a/bongbak/week2/app/src/main/java/com/example/mission2/Song.kt +++ b/bongbak/week2/app/src/main/java/com/example/mission2/Song.kt @@ -1,6 +1,21 @@ package com.example.mission2 +import androidx.room.Entity +import androidx.room.PrimaryKey + + +@Entity(tableName = "SongTable") data class Song( var title: String = "", var singer: String = "", -) \ No newline at end of file + var second: Int=0, + val playTime:Int=0, + var isPlaying: Boolean=false, + var music: String="", + var coverImg:Int?=null, + var isLike:Boolean=false + + // μ–΄λ–€ μŒμ•…μ΄ μž¬μƒλ˜κ³  μžˆμ—ˆλŠ”μ§€λ₯Ό 확인 +){ + @PrimaryKey(autoGenerate=true)var id:Int=0 +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SongActivity.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SongActivity.kt index 0676579..4cccd65 100644 --- a/bongbak/week2/app/src/main/java/com/example/mission2/SongActivity.kt +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SongActivity.kt @@ -1,78 +1,257 @@ package com.example.mission2 +import android.media.MediaPlayer import android.os.Bundle +import android.util.Log import android.view.View +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import com.example.mission2.databinding.ActivitySongBinding +import com.google.gson.Gson class SongActivity : AppCompatActivity() { - lateinit var binding : ActivitySongBinding + lateinit var binding: ActivitySongBinding + + //week5. song data μ΄ˆκΈ°ν™” ν•¨μˆ˜ 생성 + lateinit var timer: Timer + private var mediaPlayer: MediaPlayer? = null + private var gson: Gson=Gson() + + val songs=arrayListOf() + lateinit var songDB:SongDatabase + var nowPos=0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - binding= ActivitySongBinding.inflate(layoutInflater) + binding = ActivitySongBinding.inflate(layoutInflater) setContentView(binding.root) - binding.songDownIb.setOnClickListener{ + + // week5. Song 데이터 μ΄ˆκΈ°ν™” 및 UI μ„€μ • + + initPlayList() + initSong() + initClickListener() + + } + + // week5. Song 객체λ₯Ό μ΄ˆκΈ°ν™”ν•˜λŠ” ν•¨μˆ˜ + + private fun initClickListener(){ + binding.songDownIb.setOnClickListener { finish() } - binding.songMiniplayerIv.setOnClickListener{ - setPlayerStatus(false) - } - binding.songPauseIv.setOnClickListener{ + + binding.songMiniplayerIv.setOnClickListener { setPlayerStatus(true) } - binding.songRepeatIv.setOnClickListener { - setRepeatStatus(false) - } - binding.songSelectRepeatIv.setOnClickListener{ - setRepeatStatus(true) + + binding.songPauseIv.setOnClickListener { + setPlayerStatus(false) } - binding.songRandomIv.setOnClickListener{ - setRandomStatus(false) + + binding.songNextIv.setOnClickListener { + moveSong(+1) } - binding.songSelectRandomIv.setOnClickListener{ - setRandomStatus(true) + + binding.songPreviousIv.setOnClickListener { + moveSong(-1) } - if (intent.hasExtra("title")&&intent.hasExtra("singer")){ - binding.songMusicTitleTv.text=intent.getStringExtra("title") - binding.songSingerNameTv.text=intent.getStringExtra("singer") + binding.songLikeIv.setOnClickListener{ + setLike(songs[nowPos].isLike) } + } + private fun initSong() { + val spf=getSharedPreferences("song",MODE_PRIVATE) + val songId=spf.getInt("songId",0) + nowPos=getPlayingSongPosition(songId) + + Log.d("now Song Id", songs[nowPos].id.toString()) + startTimer() + setPlayer(songs[nowPos]) } - fun setPlayerStatus(isPlaying : Boolean){ - if(isPlaying){ - binding.songMiniplayerIv.visibility= View.VISIBLE - binding.songPauseIv.visibility=View.GONE + + private fun setLike(isLike: Boolean){ + songs[nowPos].isLike=!isLike + songDB.songDao().updateIsLikeById(!isLike,songs[nowPos].id) + + if(!isLike){ + binding.songLikeIv.setImageResource(R.drawable.ic_my_like_on) } else{ - binding.songMiniplayerIv.visibility= View.GONE - binding.songPauseIv.visibility=View.VISIBLE + binding.songLikeIv.setImageResource(R.drawable.ic_my_like_off) } } - fun setRepeatStatus(isRepeat: Boolean){ - if(isRepeat){ - binding.songRepeatIv.visibility=View.VISIBLE - binding.songSelectRepeatIv.visibility=View.GONE + + private fun moveSong(direct: Int){ + if(nowPos+direct<0){ + Toast.makeText(this,"first song",Toast.LENGTH_SHORT).show() + return } - else{ - binding.songRepeatIv.visibility=View.GONE - binding.songSelectRepeatIv.visibility=View.VISIBLE + if(nowPos+direct>=songs.size){ + Toast.makeText(this,"Last song", Toast.LENGTH_SHORT).show() + return + } + nowPos+=direct + timer.interrupt() + startTimer() + + mediaPlayer?.release() + mediaPlayer=null + + setPlayer(songs[nowPos]) + + } + + private fun getPlayingSongPosition(songId:Int): Int{ + for(i in 0 until songs.size){ + if(songs[i].id==songId){ + return i + } } + return 0 } - fun setRandomStatus(isRandom: Boolean){ - if(isRandom){ - binding.songRandomIv.visibility=View.VISIBLE - binding.songSelectRandomIv.visibility=View.GONE + + //week5. UI에 λ…Έλž˜ 정보λ₯Ό λ°˜μ˜ν•˜λŠ” ν•¨μˆ˜ + private fun setPlayer(song: Song) { + binding.songMusicTitleTv.text = song.title + binding.songSingerNameTv.text = song.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 + ) + binding.songAlbumIv.setImageResource(song.coverImg!!) + binding.songProgressSb.progress = (song.second*100*1000/song.playTime) + Log.d("song","second=${song.second}") + + val music=resources.getIdentifier(song.music,"raw",this.packageName) + + if (song.isLike){ + binding.songLikeIv.setImageResource(R.drawable.ic_my_like_on) } else{ - binding.songRandomIv.visibility=View.GONE - binding.songSelectRandomIv.visibility=View.VISIBLE + binding.songLikeIv.setImageResource(R.drawable.ic_my_like_off) + } + + setPlayerStatus(song.isPlaying) + } + + private fun setPlayerStatus(isPlaying: Boolean) { + songs[nowPos].isPlaying = isPlaying + timer.isPlaying = isPlaying + if (isPlaying) { + binding.songMiniplayerIv.visibility = View.GONE + binding.songPauseIv.visibility = View.VISIBLE + mediaPlayer?.start() + } else { + binding.songMiniplayerIv.visibility = View.VISIBLE + binding.songPauseIv.visibility = View.GONE + if (mediaPlayer?.isPlaying == true) { // μŒμ•…μ΄ μž¬μƒ μ€‘μΌλ•Œλ§Œ pauseλ₯Ό 해야함. + mediaPlayer?.pause() + } } } + private fun startTimer() { + timer = Timer(songs[nowPos].playTime, songs[nowPos].isPlaying) + timer.start() + } + + // 바인딩 λ³€μˆ˜λ₯Ό μ΄μš©ν•΄μ•Όν•΄μ„œ inner class 둜 생성 + inner class Timer(private val playTime: Int, var isPlaying: Boolean = true) : Thread() { + private var second: Int = 0 + private var mills: Float = songs[nowPos].second*1000F + override fun run() { + super.run() + try { + + + while (true) { + + if (second >= playTime) { + break + } + + if (isPlaying) { + sleep(50) + mills += 50 + + runOnUiThread { + binding.songProgressSb.progress = ((mills / playTime) * 100).toInt() + // seekbar κ΅¬ν˜„ + } + if (mills % 1000 == 0f) { + runOnUiThread { + binding.songStartTimeTv.text = + String.format("%02d:%02d", songs[nowPos].second / 60, songs[nowPos].second % 60) + } + songs[nowPos].second++ + } + } + } + } catch (e: InterruptedException) { + Log.d("Song", "μ“°λ ˆλ“œκ°€ μ’…λ£Œλ˜μ—ˆμŠ΅λ‹ˆλ‹€.") + } + } + } + + // μ‚¬μš©μžκ°€ 포컀슀λ₯Ό μžƒμ—ˆμ„ λ•Œ μŒμ•…μ΄ 쀑지 + override fun onPause() { + super.onPause() + setPlayerStatus(false) + songs[nowPos].second=((binding.songProgressSb.progress*songs[nowPos].playTime)/100)/1000 + songs[nowPos].isPlaying = false + setPlayerStatus(false) + + val sharedPreferences = getSharedPreferences("song", MODE_PRIVATE) + val editor = sharedPreferences.edit() // 에디터 + + editor.putInt("songId",songs[nowPos].id) + + editor.apply() + } + + override fun onDestroy() { + super.onDestroy() // μ“°λ ˆλ“œ μ’…λ£Œ + timer.interrupt() + mediaPlayer?.release() // λ―Έλ””μ–΄ν”Œλ ˆμ΄μ–΄κ°€ κ°–κ³  있던 λ¦¬μ†ŒμŠ€ ν•΄μ œ + mediaPlayer=null //λ―Έλ””μ–΄ ν”Œλ ˆμ΄μ–΄ ν•΄μ œ + } + + private fun initPlayList(){ + songDB= SongDatabase.getInstance(this)!! + songs.addAll(songDB.songDao().getSongs()) + } + + + /* + private fun setRepeatStatus(isRepeat: Boolean) { + if (isRepeat) { + binding.songRepeatIv.visibility = View.GONE + binding.songSelectRepeatIv.visibility = View.VISIBLE + } else { + binding.songRepeatIv.visibility = View.VISIBLE + binding.songSelectRepeatIv.visibility = View.GONE + } + } + + private fun setRandomStatus(isRandom: Boolean) { + if (isRandom) { + binding.songRandomIv.visibility = View.GONE + binding.songSelectRandomIv.visibility = View.VISIBLE + } else { + binding.songRandomIv.visibility = View.VISIBLE + binding.songSelectRandomIv.visibility = View.GONE + } + } + */ } \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SongDao.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SongDao.kt new file mode 100644 index 0000000..1d7bbb7 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SongDao.kt @@ -0,0 +1,28 @@ +package com.example.mission2 + +import androidx.room.* + +@Dao +interface SongDao { + + @Insert + fun insert(song:Song) + + @Update + fun update(song:Song) + + @Delete + fun delete(song:Song) + + @Query("SELECT * FROM SongTable") + fun getSongs(): List + + @Query("SELECT * FROM SongTable WHERE id = :id") + fun getSong(id: Int): Song + + @Query("UPDATE SongTable SET isLike=:isLike WHERE id = :id") + fun updateIsLikeById(isLike:Boolean,id:Int) + + @Query("SELECT*FROM SongTable WHERE isLike=:isLike") + fun getLikedSongs(isLike:Boolean):List +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SongDatabase.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SongDatabase.kt new file mode 100644 index 0000000..c6d2f10 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SongDatabase.kt @@ -0,0 +1,33 @@ +package com.example.mission2 + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase + +@Database(entities=[Song::class,User::class,Like::class,Album::class],version=1) +abstract class SongDatabase :RoomDatabase(){ + abstract fun songDao(): SongDao + abstract fun UserDao(): UserDao + abstract fun AlbumDao(): AlbumDao + + companion object{ + private var instance:SongDatabase?=null + + @Synchronized + fun getInstance(context: Context):SongDatabase?{ + if(instance==null){ + synchronized(SongDatabase::class){ + instance= Room.databaseBuilder( + context.applicationContext, + SongDatabase::class.java, + "song-database" // λ‹€λ₯Έ 데이터 λ² μ΄μŠ€λž‘ 이름 겹치면 κΌ¬μž„ + ).allowMainThreadQueries().build() + } + } + return instance + } + + } + +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SongFragment.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SongFragment.kt index 09e24e5..e269836 100644 --- a/bongbak/week2/app/src/main/java/com/example/mission2/SongFragment.kt +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SongFragment.kt @@ -5,19 +5,33 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager import com.example.mission2.databinding.FragmentSongBinding class SongFragment : Fragment() { + + + lateinit var binding: FragmentSongBinding + private val includedDatas=ArrayList() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { binding = FragmentSongBinding.inflate(inflater, container, false) - + includedDatas.apply{ + add(Included("Butter","λ°©νƒ„μ†Œλ…„λ‹¨(BTS)")) + add(Included("Permission to Dance","λ°©νƒ„μ†Œλ…„λ‹¨(BTS)")) + add(Included("Butter(instrumental)","λ°©νƒ„μ†Œλ…„λ‹¨(BTS)")) + add(Included("Permission to Dance(instrumental)","λ°©νƒ„μ†Œλ…„λ‹¨(BTS)")) + } + val songRVAdapter = SongRVAdapter(includedDatas) + binding.albumAlbumContentRv.adapter = songRVAdapter + binding.albumAlbumContentRv.layoutManager = LinearLayoutManager(context) binding.songMixoffTg.setOnClickListener { diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SongRVAdapter.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SongRVAdapter.kt new file mode 100644 index 0000000..d8494db --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SongRVAdapter.kt @@ -0,0 +1,36 @@ +package com.example.mission2 + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.example.mission2.databinding.ItemSongBinding + +class SongRVAdapter(private val includedList:ArrayList): RecyclerView.Adapter() { + + override fun onCreateViewHolder( + parent: ViewGroup, + viewType: Int + ): ViewHolder { + + val binding: ItemSongBinding = + ItemSongBinding.inflate(LayoutInflater.from(parent.context), parent, false) + + return ViewHolder(binding) + } + + override fun onBindViewHolder(holder: SongRVAdapter.ViewHolder, position: Int) { + + holder.bind(includedList[position]) + } + + override fun getItemCount(): Int=includedList.size + + inner class ViewHolder(val binding: ItemSongBinding) : RecyclerView.ViewHolder(binding.root) { + fun bind(included: Included) { + val orderText=String.format("%02d",adapterPosition+1) + binding.itemSongListOrder01Tv.text=orderText + binding.itemSongMusicTitle01Tv.text = included.title + binding.itemSongSingerName01Tv.text = included.singer + } + } +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/SplashActivity.kt b/bongbak/week2/app/src/main/java/com/example/mission2/SplashActivity.kt new file mode 100644 index 0000000..64ccc9c --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/SplashActivity.kt @@ -0,0 +1,26 @@ +package com.example.mission2 + +import android.content.Intent +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import androidx.appcompat.app.AppCompatActivity +import androidx.core.os.postDelayed +import com.example.mission2.databinding.ActivitySplashBinding + +class SplashActivity: AppCompatActivity() { + lateinit var binding: ActivitySplashBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = ActivitySplashBinding.inflate(layoutInflater) + setContentView(binding.root) + val handler = Handler(Looper.getMainLooper()) + handler.postDelayed({ + val intent = Intent(this@SplashActivity, MainActivity::class.java) + startActivity(intent) + finish() + }, 1000) + } +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/User.kt b/bongbak/week2/app/src/main/java/com/example/mission2/User.kt new file mode 100644 index 0000000..fe7acbe --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/User.kt @@ -0,0 +1,12 @@ +package com.example.mission2 + +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity(tableName="UserTable") +data class User( + var email : String, + var password:String +){ + @PrimaryKey(autoGenerate=true) var id:Int=0 +} diff --git a/bongbak/week2/app/src/main/java/com/example/mission2/UserDao.kt b/bongbak/week2/app/src/main/java/com/example/mission2/UserDao.kt new file mode 100644 index 0000000..37d3bb3 --- /dev/null +++ b/bongbak/week2/app/src/main/java/com/example/mission2/UserDao.kt @@ -0,0 +1,17 @@ +package com.example.mission2 + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query + +@Dao +interface UserDao { + @Insert + fun insert(user:User) + + @Query("SELECT*FROM UserTable") + fun getUsers():List + + @Query("SELECT*FROM UserTable WHERE email=:email AND password= :password") + fun getUser(email:String, password:String) : User? +} \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/drawable/ic_flo_logo.png b/bongbak/week2/app/src/main/res/drawable/ic_flo_logo.png new file mode 100644 index 0000000..643224d Binary files /dev/null and b/bongbak/week2/app/src/main/res/drawable/ic_flo_logo.png differ diff --git a/bongbak/week2/app/src/main/res/drawable/ic_launcher_background.xml b/bongbak/week2/app/src/main/res/drawable/ic_launcher_background.xml index ca3826a..07d5da9 100644 --- a/bongbak/week2/app/src/main/res/drawable/ic_launcher_background.xml +++ b/bongbak/week2/app/src/main/res/drawable/ic_launcher_background.xml @@ -1,74 +1,170 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:viewportHeight="108"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bongbak/week2/app/src/main/res/drawable/indicator_dot_selected.xml b/bongbak/week2/app/src/main/res/drawable/indicator_dot_selected.xml new file mode 100644 index 0000000..c1779e8 --- /dev/null +++ b/bongbak/week2/app/src/main/res/drawable/indicator_dot_selected.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/drawable/indicator_dot_unselected.xml b/bongbak/week2/app/src/main/res/drawable/indicator_dot_unselected.xml new file mode 100644 index 0000000..e4ccccc --- /dev/null +++ b/bongbak/week2/app/src/main/res/drawable/indicator_dot_unselected.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/drawable/splash.xml b/bongbak/week2/app/src/main/res/drawable/splash.xml new file mode 100644 index 0000000..ace8a7d --- /dev/null +++ b/bongbak/week2/app/src/main/res/drawable/splash.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/drawable/textview_background_radius.xml b/bongbak/week2/app/src/main/res/drawable/textview_background_radius.xml index d250c1e..53beead 100644 --- a/bongbak/week2/app/src/main/res/drawable/textview_background_radius.xml +++ b/bongbak/week2/app/src/main/res/drawable/textview_background_radius.xml @@ -11,4 +11,5 @@ android:width="1dp" android:color="#f9f9f9"/> - \ No newline at end of file + + diff --git a/bongbak/week2/app/src/main/res/drawable/textview_background_select_color_radius.xml b/bongbak/week2/app/src/main/res/drawable/textview_background_select_color_radius.xml index 8aaca4c..ea8dc88 100644 --- a/bongbak/week2/app/src/main/res/drawable/textview_background_select_color_radius.xml +++ b/bongbak/week2/app/src/main/res/drawable/textview_background_select_color_radius.xml @@ -10,4 +10,4 @@ - \ No newline at end of file + diff --git a/bongbak/week2/app/src/main/res/layout/activity_login.xml b/bongbak/week2/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..7a3b16f --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/activity_main.xml b/bongbak/week2/app/src/main/res/layout/activity_main.xml index ea4cb30..44f8398 100644 --- a/bongbak/week2/app/src/main/res/layout/activity_main.xml +++ b/bongbak/week2/app/src/main/res/layout/activity_main.xml @@ -76,6 +76,7 @@ app:layout_constraintTop_toTopOf="parent"> @@ -95,6 +96,7 @@ diff --git a/bongbak/week2/app/src/main/res/layout/activity_signup.xml b/bongbak/week2/app/src/main/res/layout/activity_signup.xml new file mode 100644 index 0000000..778975a --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/activity_signup.xml @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/activity_song.xml b/bongbak/week2/app/src/main/res/layout/activity_song.xml index 209615d..69964f4 100644 --- a/bongbak/week2/app/src/main/res/layout/activity_song.xml +++ b/bongbak/week2/app/src/main/res/layout/activity_song.xml @@ -150,45 +150,64 @@ - - - - + app:layout_constraintTop_toBottomOf="@+id/song_like_iv_layout" + /> + + + + + + + + + + + + + + + + + + + + + + - + android:text="00:00" + android:textColor="@color/select_color" + app:layout_constraintStart_toStartOf="@+id/song_progress_sb" + app:layout_constraintTop_toBottomOf="@+id/song_progress_sb"/> + android:textColor="@color/gray_color" + app:layout_constraintEnd_toEndOf="@+id/song_progress_sb" + app:layout_constraintTop_toBottomOf="@+id/song_progress_sb" /> + app:layout_constraintTop_toBottomOf="@+id/song_progress_sb"> + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/acvitity_login.xml b/bongbak/week2/app/src/main/res/layout/acvitity_login.xml new file mode 100644 index 0000000..7a3b16f --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/acvitity_login.xml @@ -0,0 +1,284 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/fragment_home.xml b/bongbak/week2/app/src/main/res/layout/fragment_home.xml index 7f7dbf9..2f4f8d9 100644 --- a/bongbak/week2/app/src/main/res/layout/fragment_home.xml +++ b/bongbak/week2/app/src/main/res/layout/fragment_home.xml @@ -14,13 +14,26 @@ android:id="@+id/home_pannel_background_vp" android:layout_width="match_parent" android:layout_height="430dp" - android:scaleType="centerCrop" - android:src="@drawable/img_first_album_default" + android:layout_marginTop="8dp" app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintHorizontal_bias="1.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> + + + app:layout_constraintTop_toBottomOf="@id/home_pannel_ci" /> + app:layout_constraintTop_toBottomOf="@id/home_pannel_ci" /> + app:layout_constraintTop_toBottomOf="@id/home_pannel_ci" /> + app:layout_constraintTop_toBottomOf="@id/home_pannel_ci" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + app:layout_constraintTop_toBottomOf="@id/home_today_music_total_tv"/> + + + app:layout_constraintTop_toBottomOf="@id/home_banner_ci" /> - - + app:layout_constraintTop_toBottomOf="@id/home_video_music_hs" /> + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools"> - - - - - - - - - - - - - - - - - - - - - - + app:layout_constraintEnd_toEndOf="parent" /> - + app:layout_constraintTop_toBottomOf="@id/locker_content_tb" /> \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/fragment_locker_savedsong.xml b/bongbak/week2/app/src/main/res/layout/fragment_locker_savedsong.xml new file mode 100644 index 0000000..cc9cb1c --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/fragment_locker_savedsong.xml @@ -0,0 +1,17 @@ + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/fragment_look.xml b/bongbak/week2/app/src/main/res/layout/fragment_look.xml index 59d1359..ef7871a 100644 --- a/bongbak/week2/app/src/main/res/layout/fragment_look.xml +++ b/bongbak/week2/app/src/main/res/layout/fragment_look.xml @@ -1,16 +1,152 @@ - + android:background="@android:color/white"> + + + app:layout_constraintEnd_toEndOf="parent"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/fragment_salbum.xml b/bongbak/week2/app/src/main/res/layout/fragment_salbum.xml new file mode 100644 index 0000000..d176998 --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/fragment_salbum.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/fragment_saved.xml b/bongbak/week2/app/src/main/res/layout/fragment_saved.xml new file mode 100644 index 0000000..de84053 --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/fragment_saved.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/fragment_song.xml b/bongbak/week2/app/src/main/res/layout/fragment_song.xml index ac83fdf..be51648 100644 --- a/bongbak/week2/app/src/main/res/layout/fragment_song.xml +++ b/bongbak/week2/app/src/main/res/layout/fragment_song.xml @@ -2,7 +2,8 @@ + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_height="wrap_content" + tools:listitem="@layout/item_song" + android:orientation="vertical" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + app:layout_constraintTop_toBottomOf="@id/song_music_list_layout"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/item_album.xml b/bongbak/week2/app/src/main/res/layout/item_album.xml new file mode 100644 index 0000000..5f97168 --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/item_album.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/layout/item_salbum.xml b/bongbak/week2/app/src/main/res/layout/item_salbum.xml new file mode 100644 index 0000000..17628b1 --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/item_salbum.xml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bongbak/week2/app/src/main/res/layout/item_saved.xml b/bongbak/week2/app/src/main/res/layout/item_saved.xml new file mode 100644 index 0000000..5733b5a --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/item_saved.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/bongbak/week2/app/src/main/res/layout/item_song.xml b/bongbak/week2/app/src/main/res/layout/item_song.xml new file mode 100644 index 0000000..ee9d5e7 --- /dev/null +++ b/bongbak/week2/app/src/main/res/layout/item_song.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + diff --git a/bongbak/week2/app/src/main/res/raw/unavailable.mp3 b/bongbak/week2/app/src/main/res/raw/unavailable.mp3 new file mode 100644 index 0000000..378d7ac Binary files /dev/null and b/bongbak/week2/app/src/main/res/raw/unavailable.mp3 differ diff --git a/bongbak/week2/app/src/main/res/values-v23/themes.xml b/bongbak/week2/app/src/main/res/values-v23/themes.xml index 99615b5..427cc51 100644 --- a/bongbak/week2/app/src/main/res/values-v23/themes.xml +++ b/bongbak/week2/app/src/main/res/values-v23/themes.xml @@ -1,9 +1,15 @@ - + + + \ No newline at end of file diff --git a/bongbak/week2/app/src/main/res/values/themes.xml b/bongbak/week2/app/src/main/res/values/themes.xml deleted file mode 100644 index e6e56e0..0000000 --- a/bongbak/week2/app/src/main/res/values/themes.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - -