[오늘 배운 내용]
-1- Android 뒤로가기 버튼 클릭 이벤트
- 기존의 onBackPressed() 가 deprecated 되어서 OnBackPressedDIspatcher 를 통해 뒤로가기 버튼 클릭 이벤트를 생성 해야 한다.
- Fragment에서의 뒤로가기 버튼 클릭 시 콜백은 해당 Fragment가 최소한 Started일 때만 호출된다.
- 뒤로가기 버튼 클릭시 다이얼로그 통해 앱 종료되는 이벤트
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// 앱 종료 다이얼로그창 생성
fun exitShowDialog() {
val builder = AlertDialog.Builder(this)
builder.setTitle("앱 종료")
.setMessage("앱을 종료하시겠습니까?")
.setIcon(R.drawable.baseline_android_24)
.setPositiveButton("앱 종료") { dialogInterface: DialogInterface, i: Int -> finish() }
.setNegativeButton("취소") { dialogInterface: DialogInterface, i: Int ->
dialogInterface.dismiss()
}
builder.show()
}
// callback 인스턴스 생성
val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
exitShowDialog()
}
}
// 미리 생성해둔 callback 인스턴스 적용
this.onBackPressedDispatcher.addCallback(this, callback)
-2- RecyclerView에 있는 Item을 Parcelize 이용해서 데이터 옮겨 DetailPage로 이동하기.
- RecyclerView 에 있는 특정 Item 클릭 시 해당 아이템의 Data를 확인할 수 있는 DetailActivity로 이동하는 기능을 추가해보자.
먼저 activity_detail.xml 을 생성하자
Adapter.kt
- xml 파일 생성이 완료 되었으면 RecyclerView의 Adapter Class로 이동해서 Interface로 OnClick 기능을 만들어주자.
class MyAdapter (private val mItems: MutableList<ItemData>) : RecyclerView.Adapter<ViewHolder>(){
// 아이템 클릭 이벤트 인터페이스 생성
interface ItemClick {
fun onClick(view: View, position: Int)
}
var itemClick: ItemClick? = null
override fun getItemCount(): Int {
return mItems.size
}
// onBindViewHolder에 Click이벤트 적용
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.itemView.setOnClickListener {
itemClick?.onClick(it, position)
}
holder.itemImage.setImageResource(mItems[position].mItemImage)
holder.itemImage.clipToOutline=true // 이미지 크기 조정
...
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = ItemViewBinding.inflate(LayoutInflater.from(parent.context),parent, false)
return ViewHolder(binding)
}
}
class ViewHolder(binding: ItemViewBinding) : RecyclerView.ViewHolder(binding.root){
val itemImage = binding.imageviewItem
val itemName = binding.tvItemName
...
}
- Adapter에 클릭리스너를 생성하고 난 뒤, 데이터를 옮겨줄 Parcelable 을 적용하자. Parcel, Parcelable 은 -3- 에 잘 정리된 블로그 주소를 남겨놨음.
- Parcelize 적용하는 방법
- 1. build.gradle(module : app) 의 plugins {} 내부에 해당 코드 추가 후 sync now
- 2. Data.kt 에서 Parcelize 적용
build.gradle.kts
// 플러그인은 build.gradle 상단에 있다.
plugins {
...
id("kotlin-parcelize")
}
Data.kt
- data class 앞에 @Parselize 추가
- data class () 뒤에 : Parcelable 추가
@Parcelize
data class ItemData(
val mItemImage : Int,
val mItemName : String,
val mItemAddress : String,
val mItemPrice : Int,
val mItemComment : Int,
val mItemLike : Int
) : Parcelable
- Parcelize를 다 적용시켜주었다면, RecyclerView와 Adapter로 연결되어 있는 Activity 로 돌아와서 Item클릭 시 해당 아이템의 Data를 넘겨주는 로직을 작성해보자
val myAdapter = MyAdapter(itemList)
binding.recyclerView.adapter = myAdapter
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.addItemDecoration(DividerItemDecoration(this, LinearLayout.VERTICAL))
myAdapter.itemClick = object : MyAdapter.ItemClick {
val context = binding.root.context
override fun onClick(view: View, position: Int) {
val intent = Intent(context, DetailActivity::class.java)
intent.putExtra("data",itemList[position])
intent.run { context.startActivity(this) }
}
}
- Intent를 생성하려면 cotext가 필요한데, val context = binding.root.context 로 context를 가져올 수 있다.
- intent = Intent(context, DetailActivity::class.java 를 통해 DetailActivity를
- Intent.putExtra를 통해 itemList 중에 내가 선택한 position의 데이터들을 "data" Extra에 담고, DetailActivity를 실행한다.
MainActivity에서 Data를 받아오고 받아온 "data"를 DetailActivity의 binding아이템에 적용시켜주면 된다.
class DetailActivity : AppCompatActivity() {
private lateinit var binding: ActivityDetailBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityDetailBinding.inflate(layoutInflater)
setContentView(binding.root)
val data = intent.getParcelableExtra<ItemData>("data")
binding.detailImageviewItem.setImageResource(data!!.mItemImage)
binding.detailTvUserName.text = data?.mUserName
binding.detailTvItemTradingAddress.text = data?.mItemAddress
binding.detailTvItemName.text = data?.mItemName
binding.detailTvItemPrice.text = MakeComma.makeComma(data?.mItemPrice)+"원"
binding.detailTvItemDescription.text = data?.mItemDesc
}
}
숫자 1000 단위마다 콤마 ( ' , ' ) 찍는 함수MakeComma를 adapter에서도 필요하고, DetailPage에도 필요해서 Object로 만들어놨다.
object MakeComma {
fun makeComma(num:Int?):String{
val formatter = DecimalFormat("###,###")
return formatter.format(num)
}
}
완성화면
-3- Parcel
- PutExtra 를 시도하다가 Parcel이란 게 나와서 간단하게 읽어 보았는데, putExtra를 할 때 필요한 직렬화를 할 때 Container 역할을 하는 클래스라고 한다.
- 추후에 더 많은 기능 공부하며 필요성 느끼면 추가 예정
- 자세한 설명은 하단 블로그에 잘 정리되어 있어서 참조하면 좋을 것 같다
- https://kotlinworld.com/44
[오늘 복습한 내용]
1. itemList.add 코드 정리하기
- 코드창에 list.add(data("A","B"))로 일일이 추가하면 데이터의 프로퍼티가 한, 두개정도는 괜찮을 수 있어도 리스트 객체양이 많아지거나, 프로퍼티가 많으면 굉장히 코드창이 지저분하고 코드를 축약할 수 없다
- list.apply { add(data("A","B")) } 처럼 apply로 리스트객체를 추가하고 다 추가한 다음 좌측 열 번호에 있는 - , + 통해 코드 축약 해놓으면 코드창이 깔끔해진다.
[오류,에러 등등]
1. onBackPressed
- 뒤로가기 버튼 클릭 시 이벤트를 만들기 위해 구글링 해서 코드를 작성해봤다.
- 다 작성해도 override 의 빨간색 밑줄이 안없어 지길래 super.onBackPressed() 도 넣어봤으나 해결이 안된다.
- onBackPressed() 를 ctrl + 클릭해도 라이브러리가 나오지 않길래 봤더니 API 33레벨 이상부터는 onBackPressed() 를 지원하지 않는다고 한다. 대신 OnbackInvokedCallback 또는, OnBackPressedCallback을 사용해야 한다고 한다.
- 해결방법은 오늘 배운 내용에 작성.
- 오류 코드
override fun onBackPressed() {
var builder = AlertDialog.Builder(this)
builder.setTitle("앱 종료 확인")
builder.setMessage("정말로 종료하시겠습니까?")
builder.setIcon(R.drawable.baseline_android_24)
val listener = DialogInterface.OnClickListener { p0, p1 ->
when (p1) {
DialogInterface.BUTTON_POSITIVE -> finishAffinity()
DialogInterface.BUTTON_NEGATIVE -> { }
}
}
builder.setPositiveButton("종료하기",listener)
builder.setNegativeButton("취소",listener)
builder.show()
}
2. 오류까지는 아니지만... putExtra로 어떤 값을 넣어야 하는지 모르겠는데 이런 경우에는 어떤 값을 넣어야 하는지, 특정 값을 넣으면 어떻게 되는지를 알아보며 답을 직접 찾아보고 싶어서 logd 계속 해가면서 결국 찾았다.
3.
[느낀 점]
1. 오류가 생기면 logd 로 어디가 문제인지 확인하자
2. 어렵다.
3. 다양한 코드 천천히 읽어보기.
[Reference]
// 코드해석 왕
CHAT.OPENAI.COM GPT아저씨
// Parce 등등 정
// Parcelize 와 Cerializable
https://altongmon.tistory.com/1022
// putExtra확인
'TIL' 카테고리의 다른 글
[TIL] registerForActivityResult 로 Activity간의 데이터 옮기기 (0) | 2023.09.02 |
---|---|
[TIL] Lambda를 이용해 Dialog 분리해서 제어하기, FloatingButton으로 RecyclerView 스크롤 상단으로 이동하기 (0) | 2023.08.31 |
[TIL] Dialog, 알림 (Notification), Intent FLAG (0) | 2023.08.29 |
[TIL] Fragment, Bottom Navigation, System UI isn't responding (0) | 2023.08.25 |
[TIL] RecyclerView (0) | 2023.08.24 |