오늘은 58번을 풀었다..
소수 판별하는문제 옛날에 했었는데,,
거기서 좀 더,, 추가된 형식이였는데
정신이 안차려짐
흐리멍텅 멍청 짓 종내 했음~
어제 자기전에 디테일 페이지를 만들기 위한 준비준비까지 해놓고 잤음
액티비티로 되어있던 페이지들 다 프래그먼트로 바꿀애들 바꿔주고..
디테일 페이지 기본 레이아웃 틀 만들고…
오늘은 디테일 페이지를 만든다….
디테일 페이지까지 만들게 될 줄 알았으면 스포티파이 안했을텐데..
더미데이터 긁어올 양이 너무 많아버림.ㅎㅎ
플레이리스트 하나 클릭할 때마다 노래 최소 10개씩은 나와야하는데;;
노래 최소 90개를 제목, 아티스트, 앨범아트 긁어와야함ㅎㅎ 와 신난다~
interface OnItemClick{
fun onClick(position: Int)
}
인터페이스 하나 기깔나게 만들어줌
var itemClick : OnItemClick? = null
override fun onBindViewHolder(holder: HorizontalAdapter.Holder, position: Int) {
holder.itemView.setOnClickListener {
itemClick?.onClick(position)
}
adapterRecommend.itemClick = object : OnItemClick{
override fun onClick(position: Int) {
val category = "RecommendStation"
val index = position
val detailInstance = Detail.newInstance(category, index)
val transaction = parentFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, detailInstance)
transaction.addToBackStack(null)
transaction.commit()
}
OnItemClick 인터페이스를 구현하는 오브젝트 하나 만들어준다음에,
내부 함수 정의.
해당 아이템을 클릭하면 Detail Fragment로 전환하면서 데이터도 보내줘야해서
넣어줄 변수 만들어주고, Detail Fragment 의 newInstance 생성해서 넣어줌
companion object {
@JvmStatic
fun newInstance(param1: String, param2 : Int) =
Detail().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putInt(ARG_PARAM2, param2)
}
}
}
프래그먼트 만들면 맨 밑에 짱박혀있는 컴패니언 오브젝트의 new Instance 함수의 파라미터를 내가 보낸 정보에 맞게 고쳐줌
class Detail : Fragment() {
private var param1: String? = null
private var param2: Int? = null
여기도 고쳐줌
이게 진짜 미친놈임
이거하면서 진짜 처음으로 하차하고싶어짐
스탠다드반 수준별 수업 자료랑 희영튜터님이 주신 깃 허브 자료 보면서 참고해서 만들려고 했는데
생각대로 안되어버림.
사실 어려운 이유는 첫단추 잘못껴서그럼
애초에 메인에서 만들 때 데이터클래스 하나에 짬뽕으로 다 쳐넣고 처리하려고 이것저것 시도해서 어떻게든 만들어놨는데 이게 오늘도 발목잡아버림
처음에는 List Adapter랑 SealedClass써서 만들려고했는데
맘대로 안되어버림..
내가 완벽하게 이 리사이클러뷰와 리스트 어댑터뷰의 모든 함수를 꿰고있고, DiffUtil 도 꿰고있고
Enum클래스 Sealed 클래스 꿰고있고 한 상태면 상관 없었을텐데 지금 거의 말하는 감자 상태로
자료 보면서 하나하나 이해해봐야되는데 응용까지 해야되니까
선행학습 안하고 학교에서만 수학 배우는 애가 오늘 학교 수학시간에 뭐 하나 배웠는데 수학익힘책 문제도 다 안푼 상태로 갑자기 집와서 쎈 인가 그 무슨 응용문제 있는 문제집 풀려고 머리 쥐어뜯는 꼴이였음
근데 또 내일 까지 제출이니까 막 하나하나 뜯어서 볼 시간도 없는 것 같고 걍 하차해버리고싶었다.
진짜 이거는 트러블 슈팅 기록하면서 했으면 나중에 엄청 도움됐을텐데 하면서 멘탈나가서 하나도 안적고 그냥 해버림 ㅎ.ㅎ
하지만 하차 한다고 매니저님 한테 안달려간것만으로도 내 자신이 기특하다. 쏘 독해~like 르쎄라핌잊지마 내가 두고온 케리아…(코딩 공부한다고 lck 못 챙겨본다는 뜻)
결국 완벽하겐 구현 못하고 그냥 되는대로 구현했음
내가 구현하고 싶었던 건 원래
홈에서 리사이클러뷰 아이템 (플레이리스트) 한개 누르면, 해당 플레이리스트의 음악들이 쫙 나오고,
밑에 다른 리사이클러 뷰에는 다른 추천항목으로 다른 카테고리의 플레이리스트가 나오게 하고싶었는데,
내가 구현한건 아이템 누르면, 해당 플레이리스트의 음악 나오기까지는 성공했는데,
다른 추천 항목에 다른 카테고리가아니고 그냥 같은 카테고리의 플레이리스트들이 나온다^^발
일단 내 TIL은 그냥 쓰라고 해서 쓰는거고 혹시 인터넷이 지속되는 많은 기간동안 운없게도 멀티뷰 리사이클러에 대한 정보를 찾다가 이 글을 발견해서 참고해볼까? 하고 보는 사람이 없길 바람. 개 엉터리임니다
내가 이 거지같은 구현을 어떻게 했냐면.
뷰타입을 나타낼 Enum class를 만들어줌
enum class MultiViewEnum(val viewType: Int) {
SONG(0),
RECOMMEND(1)
}
SONG은 0 RECOMMEND는 1을 할당해줬다.
데이터 클래스도 하나 새로 만들어줌
data class PlaySongList(
val viewType : MultiViewEnum,
val playList : MutableList<PlayList>,
val SongList : MutableList<Song>,
val anotherPlayList : MutableList<PlayList>
)
첫번째로 1번에서 만든 EnumClass로 뷰타입을 받아주고,
나머지는 내가 사용할 데이터들을 넣어줌
Adapter 정의
class SongAdapter(private val items: PlaySongList) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
MultiViewEnum.SONG.viewType -> {
val binding =
SongHolderBinding.inflate(LayoutInflater.from(parent.context), parent, false)
SongHolder(binding)
}
MultiViewEnum.RECOMMEND.viewType -> {
val binding = RecommendHolderBinding.inflate(
LayoutInflater.from(parent.context),
parent,
false
)
RecommendHolder(binding)
}
else -> throw IllegalArgumentException("Invalid view type")
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is SongHolder -> {
holder.bind(items.SongList[position])
}
is RecommendHolder -> {
holder.bind(items.playList[position])
}
}
}
override fun getItemViewType(position: Int): Int {
return items.viewType.viewType
}
override fun getItemCount(): Int {
return if(items.viewType == MultiViewEnum.SONG){
items.SongList.size
}else{
items.playList.size
}
}
}
class SongHolder(private val binding: SongHolderBinding) : RecyclerView.ViewHolder(binding.root) {
fun bind(song: Song) {
binding.apply {
ivSongCover.setImageResource(song.cover)
tvSongName.text = song.song
tvArtistName.text = song.artist
}
}
}
class RecommendHolder(private val binding: RecommendHolderBinding) :
RecyclerView.ViewHolder(binding.root) {
fun bind(item: PlayList) {
binding.apply {
ivCoverPlayList.setImageResource(item.cover)
tvPlaylistName.text = item.playlistName
tvPlaylistDesc.text = item.desc
}
}
}
RecyclerView.Adapter를 구현하는 SongAdapter라는걸 만들어줌
지금 생각하니까 이름 DetailAdapter로 할껄잘못만든거같음
홀더도 정의해줌
마찬가지로 RecyclerView의 ViewHolder를 갖다가 구현하는데
인자로 binding 받는다고 해놓고 RecyclerView.ViewHolder()안에 binding.root 넣어주면
내가 정의해놓은 holder의 xml파일에서 binding으로 객체를 가져올 수있음
bind라는 함수를 사용해서 여기에서 사용할 데이터 타입 정해서
각 뷰에 맞춰서 적용해줌
Song Holder는 Song 타입의 데이터를 사용하고,
RecommendHolder는 PlayList 타입의 데이터를 사용함
그리고 onCreateViewHolder, onBindViewHolder, getItemViewType, getItemCount 를 구현해줌
onCreateViewHolder에서는
return when을 사용해서 EnumClass에서 정해준 viewType 에 따라서 다른 레이아웃을 뿌려주게? 만들어줌
onBindViewHolder에서는
when으로 holder에 따라서 holder가 SongHolder면 holder에 bind로 받은 item의 SongList에서 position을 참고해서 넣어주고
RecommendHolder면 playList에서 넣어줌
getItemViewType에서는 items에서 viewType을 참고해서 viewType을 반환해주면됨
21세기나 됐으면 이런건 좀 알아서해라 내가 정의안해줘도 ㅋㅋ 고철덩어리같은것.
getItemCount에서는 return if 로 item의 뷰타입이 SONG이면 SongList의 사이즈를, 아니면 playList의 사이즈를 반환하게 해줌
Detail Fragment에서 리사이클러 뷰에 어댑터 연결해주기
val playList = MyPlayListObject.recommendStation.getOrNull(index)
val songData = playList?.song ?: mutableListOf()
val songListData = PlaySongList(MultiViewEnum.SONG, MyPlayListObject.recommendStation,songData,MyPlayListObject.mixForUser)
val recommendData = PlaySongList(MultiViewEnum.RECOMMEND, MyPlayListObject.recommendStation,SongListObject.hyang,MyPlayListObject.mixForUser)
binding.rvSongList.adapter = SongAdapter(songListData)
binding.rvSongList.addItemDecoration(RecyclerDecoration(16,16,16,16))
binding.rvRecommend.adapter = SongAdapter(recommendData)
binding.rvRecommend.layoutManager = GridLayoutManager(this.context,2)
binding.rvRecommend.addItemDecoration(RecyclerDecoration(16,16,16,16))
위에서 Adapter에 PlaySongList라는 타입을 먹여주기로 약속했는데
PlaySongList는 viewType과 PlayList, Song 타입의 MutableList를 받는 애임
playList라는 변수에 Dataclass에서 정의해둔 object하나 꺼내와서 거기에 Home 에서 받아온 position을 넘김 왜 이름을 index로 지었냐면 나도 후회중임 가독성 ㅎㅌㅊ
그리고 songData라는애는 playList의 song을 넣어줌
그래서 각 rvSongList adpater에 쑤셔넣은 정보들을 넣어줌!