Skip to content

Commit

Permalink
[Nunu/#28] feat: 6주차 구현
Browse files Browse the repository at this point in the history
* [nunu/#28] feat: 6주차 구현1

- item_album.xml 구현

* [nunu/#28] feat: 6주차 구현2

- 리사이클러뷰를 사용해서 화면 만들기
- 리사이클러뷰 클릭 이벤트

* [nunu/#28] feat: 6주차 구현3

- Play 버튼 클릭시 MiniPlayer에 동기화
- SongActivity intent 관련 문제 해결

* [nunu/#28] 6주차 구현4

- RecyclerView 문제점 해결
(SparseBooleanArray 사용)
Ssamssamukja authored May 21, 2024
1 parent 16d995a commit a4cb646
Showing 26 changed files with 626 additions and 215 deletions.
156 changes: 17 additions & 139 deletions .idea/workspace.xml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions UMC_6th/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -67,6 +67,7 @@ dependencies {
implementation("androidx.compose.material3:material3")
implementation("androidx.viewpager2:viewpager2:1.0.0")
implementation ("me.relex:circleindicator:2.1.6")
implementation ("com.google.code.gson:gson:2.9.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
8 changes: 8 additions & 0 deletions UMC_6th/app/src/main/java/com/example/umc_6th/Album.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.example.umc_6th

data class Album(
var title : String? = "",
var artist : String? = "",
var coverImage : Int? = null,
var songs: ArrayList<Song>? = null
)
16 changes: 16 additions & 0 deletions UMC_6th/app/src/main/java/com/example/umc_6th/HomeFragment.kt
Original file line number Diff line number Diff line change
@@ -14,10 +14,14 @@ import com.example.umc_6th.adapter.ViewPagerAdapter
import com.example.umc_6th.databinding.FragmentHomeBinding
import me.relex.circleindicator.CircleIndicator3
import android.os.Looper
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider


class HomeFragment : Fragment() {
// 여기에 Fragment의 구현 내용을 작성합니다.
private lateinit var viewModel: SharedViewModel
private var _binding: FragmentHomeBinding? = null
private val binding get() = _binding!!
private lateinit var handler: Handler
@@ -27,6 +31,7 @@ class HomeFragment : Fragment() {
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
viewModel = ViewModelProvider(requireActivity()).get(SharedViewModel::class.java)
_binding = FragmentHomeBinding.inflate(inflater, container, false)

return binding.root
@@ -62,8 +67,19 @@ class HomeFragment : Fragment() {
}
}
startAutoSlide()

binding.imgSecondAlbumPlay1.setOnClickListener(){
viewModel.selectedTitle.value = binding.txSecondTitle1.getText().toString()
viewModel.selectedArtist.value = binding.txSecondArtist1.getText().toString()
}
}

class SharedViewModel : ViewModel() {
val selectedTitle = MutableLiveData<String>()
val selectedArtist = MutableLiveData<String>()
}


private fun startAutoSlide() {
handler.postDelayed(runnable, 3000) // 3초에 한번씩 페이지 이동
}
28 changes: 23 additions & 5 deletions UMC_6th/app/src/main/java/com/example/umc_6th/LockerFragment.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,39 @@
package com.example.umc_6th

import android.os.Bundle
import android.os.Handler
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.umc_6th.adapter.LockerPagerAdapter
import com.example.umc_6th.databinding.FragmentHomeBinding
import com.example.umc_6th.databinding.FragmentLockerBinding
import com.google.android.material.tabs.TabLayoutMediator

class LockerFragment : Fragment() {
// 여기에 Fragment의 구현 내용을 작성합니다.
private var _binding: FragmentLockerBinding? = null
private val binding get() = _binding!!
private val information = arrayListOf("저장한곡", "음악파일")

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// 여기에서 Fragment의 레이아웃을 인플레이트합니다.
return inflater.inflate(R.layout.fragment_locker, container, false)
): View {
_binding = FragmentLockerBinding.inflate(inflater, container, false)

val lockerAdapter = LockerPagerAdapter(this)
binding.vpLocker.adapter = lockerAdapter
TabLayoutMediator(binding.tbLocker, binding.vpLocker) { tab, position ->
tab.text = information[position]
}.attach()

return binding.root
}

// 필요한 경우 다른 Fragment 생명주기 메소드를 오버라이드합니다.
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.example.umc_6th

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

class LockerMusicFileFragment : Fragment() {
// 여기에 Fragment의 구현 내용을 작성합니다.
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// 여기에서 Fragment의 레이아웃을 인플레이트합니다.
return inflater.inflate(R.layout.fragment_locker_music_file, container, false)
}

// 필요한 경우 다른 Fragment 생명주기 메소드를 오버라이드합니다.
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.example.umc_6th

import android.os.Bundle
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.umc_6th.adapter.LockerAlbumRecyclerAdapter
import com.example.umc_6th.databinding.FragmentLockerSavedSongBinding
import com.google.gson.Gson

class LockerSavedSongFragment : Fragment() {
private var albumDatas = ArrayList<Album>()
lateinit var binding : FragmentLockerSavedSongBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentLockerSavedSongBinding.inflate(inflater, container, false)

albumDatas.apply {
add(Album("Love wins all", "아이유 (IU)", R.drawable.img_album_lovewinsall))
add(Album("해야 (HEYA)", "IVE", R.drawable.img_album_heya))
add(Album("Supernova", "에스파 (aespa)", R.drawable.img_album_supernova))
add(Album("Lilac", "아이유 (IU)", R.drawable.img_album_exp2))
add(Album("Drama", "에스파 (aespa)", R.drawable.img_album_drama))
add(Album("Weekend", "태연 (Tae Yeon)", R.drawable.img_album_exp6))
add(Album("Love wins all", "아이유 (IU)", R.drawable.img_album_lovewinsall))
add(Album("해야 (HEYA)", "IVE", R.drawable.img_album_heya))
add(Album("Supernova", "에스파 (aespa)", R.drawable.img_album_supernova))
add(Album("Lilac", "아이유 (IU)", R.drawable.img_album_exp2))
add(Album("Drama", "에스파 (aespa)", R.drawable.img_album_drama))
add(Album("Weekend", "태연 (Tae Yeon)", R.drawable.img_album_exp6))
add(Album("Love wins all", "아이유 (IU)", R.drawable.img_album_lovewinsall))
add(Album("해야 (HEYA)", "IVE", R.drawable.img_album_heya))
add(Album("Supernova", "에스파 (aespa)", R.drawable.img_album_supernova))
add(Album("Lilac", "아이유 (IU)", R.drawable.img_album_exp2))
add(Album("Drama", "에스파 (aespa)", R.drawable.img_album_drama))
add(Album("Weekend", "태연 (Tae Yeon)", R.drawable.img_album_exp6))
}
val lockerAlbumRecyclerAdapter = LockerAlbumRecyclerAdapter(albumDatas)
binding.rvLockerSavedSong.adapter = lockerAlbumRecyclerAdapter
binding.rvLockerSavedSong.layoutManager = LinearLayoutManager(requireActivity())

lockerAlbumRecyclerAdapter.setItemClickListener(object : LockerAlbumRecyclerAdapter.OnItemClickListener {
override fun onRemoveAlbum(position: Int) {
lockerAlbumRecyclerAdapter.removeItem(position)
}

override fun onItemClick(album: Album) {
changeAlbumFragment(album)
}
})

return binding.root
}

private fun changeAlbumFragment(album: Album) {
(context as MainActivity).supportFragmentManager.beginTransaction()
.replace(R.id.main_container, AlbumFragment().apply {
arguments = Bundle().apply {
val gson = Gson()
val albumToJson = gson.toJson(album)
putString("album", albumToJson)
}
})
.commitAllowingStateLoss()
}

}
23 changes: 13 additions & 10 deletions UMC_6th/app/src/main/java/com/example/umc_6th/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -7,12 +7,14 @@ import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import com.example.umc_6th.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var resultLauncher: ActivityResultLauncher<Intent>

private lateinit var viewModel: HomeFragment.SharedViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -24,8 +26,6 @@ class MainActivity : AppCompatActivity() {
ActivityResultContracts.StartActivityForResult()
) { result ->
if (result.resultCode == Activity.RESULT_OK) {
val albumTitle = result.data?.getStringExtra("albumTitle") ?: "No Title Provided"
Toast.makeText(this, albumTitle, Toast.LENGTH_LONG).show()
val elapsedSeconds = result.data?.getIntExtra("elapsedSeconds", 0) ?: 0
updateSeekBar(elapsedSeconds)
}
@@ -39,12 +39,20 @@ class MainActivity : AppCompatActivity() {

binding.layoutPlayContainer.setOnClickListener(){
val intent = Intent(this, SongActivity::class.java)
intent.putExtra("songTitle", binding.txPlayTitle.text)
intent.putExtra("songArtist", binding.txPlayArtist.text)
intent.putExtra("songTitle", binding.txPlayTitle.text.toString())
intent.putExtra("songArtist", binding.txPlayArtist.text.toString())
resultLauncher.launch(intent)
}

setupButtonListeners()
viewModel = ViewModelProvider(this).get(HomeFragment.SharedViewModel::class.java)
viewModel.selectedTitle.observe(this, Observer {
binding.txPlayTitle.text = it
})

viewModel.selectedArtist.observe(this, Observer {
binding.txPlayArtist.text = it
})
}

private fun setupButtonListeners() {
@@ -55,11 +63,6 @@ class MainActivity : AppCompatActivity() {
binding.mainSeekBar.isEnabled = true
}
}

binding.layoutPlayContainer.setOnClickListener {
val intent = Intent(this, SongActivity::class.java)
resultLauncher.launch(intent)
}
}

private fun updateSeekBar(elapsedSeconds: Int) {
7 changes: 7 additions & 0 deletions UMC_6th/app/src/main/java/com/example/umc_6th/Song.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.example.umc_6th

data class Song(
var title : String? = "",
var artist : String? = "",
var coverImage : Int? = null,
)
3 changes: 3 additions & 0 deletions UMC_6th/app/src/main/java/com/example/umc_6th/SongActivity.kt
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ import android.content.Intent
import android.graphics.PorterDuff
import android.os.Bundle
import android.os.PersistableBundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.ui.graphics.Color
@@ -30,6 +31,8 @@ class SongActivity : AppCompatActivity() {
val songTitle = intent.getStringExtra("songTitle")
val songArtist = intent.getStringExtra("songArtist")

Log.d("SongActivity", "Received title: $songTitle, artist: $songArtist")

binding.txSongTitle.text = songTitle
binding.txSongArtist.text = songArtist

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package com.example.umc_6th.adapter

class AlbumRecyclerAdapter {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.example.umc_6th.adapter

import android.util.SparseBooleanArray
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.umc_6th.Album
import com.example.umc_6th.databinding.ItemLockerAlbumBinding

class LockerAlbumRecyclerAdapter(private val albumList: ArrayList<Album>) : RecyclerView.Adapter<LockerAlbumRecyclerAdapter.ViewHolder>() {

private val switchStatus = SparseBooleanArray()
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int
): LockerAlbumRecyclerAdapter.ViewHolder {
val binding: ItemLockerAlbumBinding = ItemLockerAlbumBinding
.inflate(LayoutInflater.from(parent.context), parent, false)

return ViewHolder(binding)
}

override fun onBindViewHolder(holder: LockerAlbumRecyclerAdapter.ViewHolder, position: Int) {
holder.bind(albumList[position])
holder.itemView.setOnClickListener {
itemClickListener.onItemClick(albumList[position])
}

holder.binding.imgItemLockerAlbumMore.setOnClickListener {
itemClickListener.onRemoveAlbum(position)
}

val switch = holder.binding.switchRV
switch.isChecked = switchStatus[position]
switch.setOnClickListener {
if (switch.isChecked) {
switchStatus.put(position, true)
}
else {
switchStatus.put(position, false)
}

notifyItemChanged(position)
}
}

override fun getItemCount(): Int = albumList.size

inner class ViewHolder(val binding: ItemLockerAlbumBinding): RecyclerView.ViewHolder(binding.root){

fun bind(album: Album){
binding.txItemLockerAlbumTitle.text = album.title
binding.txItemLockerAlbumArtist.text = album.artist
binding.imgItemLockerAlbumCover.setImageResource(album.coverImage!!)
}
}

interface OnItemClickListener {
fun onItemClick(album : Album)
abstract fun onRemoveAlbum(position: Int)
}

private lateinit var itemClickListener : OnItemClickListener

fun setItemClickListener(onItemClickListener: OnItemClickListener) {
this.itemClickListener = onItemClickListener
}

fun removeItem(position: Int){
albumList.removeAt(position)
notifyDataSetChanged()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.example.umc_6th.adapter

import androidx.fragment.app.Fragment
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.umc_6th.LockerMusicFileFragment
import com.example.umc_6th.LockerSavedSongFragment

class LockerPagerAdapter (fragment : Fragment) : FragmentStateAdapter(fragment) {
override fun getItemCount(): Int = 2

override fun createFragment(position: Int): Fragment {
return when(position){
0 -> LockerSavedSongFragment()
else -> LockerMusicFileFragment()
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Oops, something went wrong.

0 comments on commit a4cb646

Please sign in to comment.