1. Android 앱개발 심화 개인과제
어제는 드디어 Retrofit을 연결하여 API를 불러오는 데에 성공했다.
오늘은 이제 남은 기능인 좋아요 기능과 SharedPreference를 완성하여 필수 구현 항목들을 전부 완성시키는 것이 목표다.
좋아요 기능
우선 이 좋아요 기능을 자세하게 설명하자면
- 리스트에서 특정 이미지를 선택하면 특별한 표시를 보여주도록 구현(좋아요/별표/하트 등)
- 선택된 이미지는 MainActivity의 ‘선택된 이미지 리스트 변수’에 저장
- MainActivity의 ‘선택된 이미지 리스트 변수’에서 데이터를 받아오도록 구현
- 내보관함에 보관된 이미지를 선택하면 보관함에서 제거할 수 있도록 구현
즉, 다시 말해서 검색 Fragment에서 이미지를 선택하면 좋아요 표시를 껐다 킬 수 있고, 좋아요 표시가 된 이미지들만 따로 MyPage Fragment에 따로 표시되게 만들어야하며, MyPage Frament에 있는 이미지들을 클릭하면 목록에서 삭제시킬 수 있어야 한다.
그렇다면 이제 좋아요 기능을 한 번 만들어보자.
우선, 좋아요 기능을 사용하려면 Boolean 자료형의 변수가 추가되어야 한다.
하지만, 그렇다고 현재 API에서 JSON 형태로 받아오는 data class에 변수를 추가해서는 안 된다. 그러면 JSON을 제대로 받지 못 하기 때문.
그렇기 때문에, 또다른 data class를 만들어서 거기에 Boolean 자료형 변수를 추가해야 한다.
data class SearchItem (var title: String, var dateTime: String, var url: String, var isLike: Boolean = false)
여기서 true일 때 이벤트를 발생시켜야 하므로, 기본값에 false를 집어넣는다.
그 다음, Adapter에도 이 추가된 자료형을 집어넣어서 만들어야 한다.
holder.itemLike.visibility = if(items[position].isLike) View.VISIBLE else View.INVISIBLE
기본적으로 좋아요 표시가 안 보이게 만들어야 하므로 true이면 VISIBLE, false이면 INVISIBLE로 설정한다.
init {
itemLike.visibility = View.GONE
itemImage.setOnClickListener(this)
clItem.setOnClickListener(this)
}
초기 설정을 설정하는 부분이다.
override fun onClick(v: View?) {
val position = adapterPosition.takeIf { it != RecyclerView.NO_POSITION } ?: return
val item = items[position]
item.isLike = !item.isLike
if (item.isLike) {
(mContext as MainActivity).addLikedItems(item)
} else {
(mContext as MainActivity).removeLikedItems(item)
}
notifyItemChanged(position)
}
이미지를 클릭했을 때 발생하는 이벤트를 나타내는 함수다.
우선, 이미지를 클릭하면 isLike 변수를 반전시킨다. true면 false로, 그 반대도 마찬가지.
그리고 그 isLike가 true면 MainActivity에 있는 addLikedItems 메소드를 실행시키고, false면 removeLikedItems를 실행시킨다.
그러면 저 안에 있는 addLikedItems와 removeLikedItems는 어떤 식일까?
저 함수가 있는 MainActivity로 넘어가보자.
MainActivity.kt
var likedItems: ArrayList<SearchItem> = ArrayList()
우선, 좋아요한 이미지의 데이터들을 보관하는 리스트를 하나 만든다.
fun addLikedItems (item: SearchItem) {
if (!likedItems.contains(item)) likedItems.add(item)
}
fun removeLikedItems (item: SearchItem) {
likedItems.remove(item)
}
그리고 addLikedItems는 저 likedItems 안에 같은 것이 없으면 리스트에 추가하는 메소드이고, removeLikedItems는 반대로 likedItems에 있는 리스트를 제거하는 메소드이다.
마지막으로, 좋아요가 찍힌 이미지를 받아오는 MyPage 작업을 진행해보자.
일단 recyclerView는 SearchFragment와 MyPageFragment가 같이 공유하므로 따로 더 만들 필요는 없다.
우리가 필요로 하는 건 Adapter와 Fragment.
MyPageAdapter.kt
class MyPageAdapter(var mContext: Context) : RecyclerView.Adapter<MyPageAdapter.Holder>() {
var items = ArrayList<SearchItem>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val binding = ItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
override fun onBindViewHolder(holder: MyPageAdapter.Holder, position: Int) {
//Glide를 통한 Image URI 형식 받기
Glide.with(mContext)
.load(items[position].url)
.into(holder.itemImage)
holder.itemTitle.text = items[position].title
// 시간 포맷 설정
holder.itemDate.text = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(
OffsetDateTime.parse(items[position].dateTime))
holder.itemLike.visibility = View.GONE
}
override fun getItemCount(): Int {
return items.size
}
inner class Holder (binding: ItemBinding) : RecyclerView.ViewHolder(binding.root) {
val itemImage = binding.searchImage
val itemTitle = binding.searchTitle
val itemDate = binding.searchDate
val itemLike = binding.searchLike
val clItem: ConstraintLayout = binding.constRecyclerview
init {
itemLike.visibility = View.GONE
clItem.setOnClickListener {
val position = adapterPosition
if (position != RecyclerView.NO_POSITION) {
items.removeAt(position)
notifyItemRemoved(position)
}
}
}
}
}
Adapter 역시 SearchAdapter와 크게 차이는 없다.
차이점은 이미지를 클릭하면 제거하는 기능만 있는 것뿐.
MyPageFragment.kt
class MyPageFragment : Fragment() {
private var binding: FragmentMyPageBinding? = null
private lateinit var mContext: Context
private lateinit var adapter: MyPageAdapter
private var likedItems: List<SearchItem> = listOf()
override fun onAttach(context: Context) {
super.onAttach(context)
mContext = context
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val mainActivity = activity as MainActivity
likedItems = mainActivity.likedItems
adapter = MyPageAdapter(mContext).apply {
items = likedItems.toMutableList() as ArrayList<SearchItem>
}
binding = FragmentMyPageBinding.inflate(inflater, container, false).apply {
myrecyclerview.layoutManager = GridLayoutManager(context, 2)
myrecyclerview.adapter = adapter
}
return binding?.root
}
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
}
MainActivity에서 저장된 likedItems를 불러와서 보여준다.
그리고 Adapter 역시 불러와서 이미지를 클릭하면 삭제해주는 기능까지 추가되었다.
그리고 이것이 바로 좋아요 기능을 포함한 모든 기능을 완성시킨 앱 동영상이다.
'[TIL][내일배움캠프]' 카테고리의 다른 글
[내일배움캠프][TIL] 24.02.05 (월) - 팀 프로젝트(심화) : 프로젝트 논의 (0) | 2024.02.05 |
---|---|
[내일배움캠프][TIL] 24.02.02 (금) - MVVM (0) | 2024.02.02 |
[내일배움캠프][TIL] 24.01.31 (수) - Android 앱개발 심화 개인과제 : Retrofit 3트, 그 결과 (1) | 2024.01.31 |
[내일배움캠프][TIL] 24.01.30 (화) - Android 앱개발 심화 개인과제 : 문제해결 (1) | 2024.01.30 |
[내일배움캠프][TIL] 24.01.29 (월) - Android 앱개발 심화 개인과제 : Retrofit (1) | 2024.01.29 |