- [Android] 개발공부 36일차 TIL - adapter 중복 생성 실수, DecimalFormat 실수, Floating Button(플로팅 버튼, 최상단 이동)2024년 01월 10일 16시 17분 29초에 업로드 된 글입니다.작성자: 짧은 코딩끈
일자 : 2024.01.10
금일 공부 목록
- 혼공컴운 강의 수강
- 숙련개인과제 필수과제 완료
- 숙련개인과제 선택 (플로팅버튼) 시도
다음 공부 목록
- 혼공컴운 강의 수강
- 숙련 개인과제 제출
- 해설강의 영상 시청 후 재도전
📝TIL 정리
💬adapter 중복 생성 실수
개인 숙련과제 필수과제 중에서
리사이클러뷰 뷰홀더 하나를 클릭했을 때
MainActivity에서 SecondActivity의 화면을 요청하는 인텐트 이벤트를 발생시키려고 코드를 작성했었다.
처음에는 아래와 같이
별도 공간에 작성하였는데 클릭을 하여도 아무런 반응이 없었다.
로그를 찍으니 만들어놓은 어댑터에서는 로그가 찍히는데
메인액티비티에서는 전혀 반응이 없었다.
알고보니 기존에 만든 리사이클러뷰의 어댑터에 연결한 데이터 리스트에서 바로 클릭이벤트 코드를 연결해서 작성해야했는데 따로 하다보니 기존에 만든 어댑터와 다른 어댑터로 인식하여서 클릭 이벤트가 발생하지 않았다.
혼자 코드가 잘못된줄 알고 이리저리 고치다가 튜터님께 여쭤보니 매우 간단한 이유였다
연결된 어댑터가 이미 생성되어있기에 그것과 바로 연결되도록 했어야 했다..
앞으로도 유의하자..!!
아래 두 코드중 1번째가 잘못된 케이스
2번째가 제대로 된 케이스 이다.
with(binding) { ivMainAlarm.setOnClickListener { // 알람 발생 notification() } rvMainList.layoutManager = LinearLayoutManager(this@MainActivity, LinearLayoutManager.VERTICAL, false) rvMainList.setHasFixedSize(true) // RecyclerView 에게 고정된 사이즈라고 알려주기 (생성시 일일히 전체 레이아웃 사이즈 체크 필요없음) rvMainList.adapter = MerchandiseAdapter(list) } MerchandiseAdapter(list).itemClick = object : MerchandiseAdapter.ItemClick { override fun onClick(view: View, position: Int) { Log.d("Click", "MainActivity : $position") val item = list.get(position) val intent = Intent(this@MainActivity, SecondActivity::class.java) intent.putExtra("data", item) startActivity(intent) } }
with(binding) { ivMainAlarm.setOnClickListener { // 알람 발생 notification() } rvMainList.layoutManager = LinearLayoutManager(this@MainActivity, LinearLayoutManager.VERTICAL, false) rvMainList.setHasFixedSize(true) // RecyclerView 에게 고정된 사이즈라고 알려주기 (생성시 일일히 전체 레이아웃 사이즈 체크 필요없음) rvMainList.adapter = MerchandiseAdapter(list).apply { itemClick = object : MerchandiseAdapter.ItemClick { override fun onClick(view: View, position: Int) { Log.d("Click", "MainActivity : $position") val item = list.get(position) val intent = Intent(this@MainActivity, SecondActivity::class.java) intent.putExtra("data", item) startActivity(intent) } // Adapter에 리스트 전달 } } }
💬DecimalFormat 실수(타입)
DecimalFormat을 활용하여
받은 숫자데이터(Int, Long)를 표시할 때 숫자 사이에 천원단위로 콤마를 넣고자 했다.
처음에는 text에 할당하는 데이터라서 뒤에 toString으로 형변환을 해줬는데 오류가 났었다
이미 포맷상에서는 String 문자열("#,###원")로 정했기에 DecimalFormat을 적용할 시에는 굳이 String 형변환을 해줄 필요가 없었다.
tvItemPrice.text = priceFormat.format(intent.getParcelableExtra<Merchandise>("data")!!.price.toString()) // toString 형변환으로 인한 오류
with(binding) { ivItemBackbtn.bringToFront() // 이미지 최상단 불러오기 // 뒤로가기 클릭시 화면 종료 및 메인 페이지 ivItemBackbtn.setOnClickListener { if(!isFinishing) finish() } val priceFormat = DecimalFormat("#,###원") // 가격 숫자 콤마 추가 ivItem.setImageResource(intent.getParcelableExtra<Merchandise>("data")!!.photo) tvItemSeller.setText(intent.getParcelableExtra<Merchandise>("data")!!.seller) tvItemLocation.setText(intent.getParcelableExtra<Merchandise>("data")!!.address) tvItemTitle.setText(intent.getParcelableExtra<Merchandise>("data")!!.title) tvItemInfo.setText(intent.getParcelableExtra<Merchandise>("data")!!.intro) tvItemPrice.text = priceFormat.format(intent.getParcelableExtra<Merchandise>("data")!!.price) // toString을 안해줘도 되었다. }
📌Floating Button(플로팅 버튼)
플로팅 버튼을 만들고
그 버튼을 눌렀을 때, 가장 최상단으로 올라가는 기능을 구현하고자 했다.
그리고 최상단 및 스크롤을 하지 않은 상태일때는 플로팅 버튼의 visibility 상태를 GONE으로 하여 아예 누를 수 없도록 하고, 조금이라도 아래로 스크롤이 되었을 때에 플로팅 버튼의 visibility 상태를 VISIBLE로 하도록 했다.
fade in과 fade out 애니메이션 효과도 적용하였으니 아래 코드를 확인해보자
구현 영상
app:shapeAppearance="@style/FloatingButtonTheme” ← 원형이 아니던 FAB를 스타일 지정해서 원형으로 만듬(기본 약간 동글 사각형)
android:backgroundTint="@color/selector_fab_click” ← 배경 색 지정(기본 회색)
android:outlineSpotShadowColor="@color/white” ← 그림자 색 지정(기본 검은색)
app:backgroundTint="@color/grey” ← 테두리 색 지정(기본 연보라색)
app:borderWidth="1dp” ← 테두리 두께 지정(기본 0dp)
app:tint="@color/black” ← 아이콘 색 지정(기본 보라색)
app:maxImageSize="20dp” ← 이미지 최대 크기 지정
app:fabCustomSize="45dp" ← FAB 크기 지정메인XML
<androidx.recyclerview.widget.RecyclerView android:id="@+id/rv_main_list" android:layout_width="0dp" android:layout_height="0dp" android:layoutAnimation="@anim/layout_animation_fall_down" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/cv_main_top" /> <com.google.android.material.floatingactionbutton.FloatingActionButton android:id="@+id/btn_floating" android:layout_width="wrap_content" android:layout_height="wrap_content" app:backgroundTint="@color/btn_selector_color" android:src="@drawable/gotop_arrow" app:tint ="@color/btn_selector_icon" app:fabSize="mini" android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.9" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.95" /> </androidx.constraintlayout.widget.ConstraintLayout>
메인 코드
if문에서 최상단인지 확인할수 있도록 아래 코드를 조건을 넣으면서 !(부정)을 붙였다 (true가 되도록)
- canScrollVertically(-1) : 최상단일 경우 false 값 return
- canScrollVertically(1) : 최하단일 경우 false 값 return
그리고, 동시에 현재 아무런 스크롤을 하지 않을 상태도 같이 조건에 들어가도록
newState가 IDLE 상태인지도 같이 체크하도록 하였다.
with(binding) { val fadeIn = AlphaAnimation(0f,1f).apply { duration = 500 } // 서서히 나오기, f는 투명도 val fadeOut = AlphaAnimation(1f,0f).apply { duration = 500 } // 서서히 사라지기, f는 투명도 var isTop = true // 플로팅 버튼에 기능 할당, RecyclerView의 위치 확인 rvMainList.addOnScrollListener(object : RecyclerView.OnScrollListener(){ override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { super.onScrollStateChanged(recyclerView, newState) if(!rvMainList.canScrollVertically(-1)&& newState==RecyclerView.SCROLL_STATE_IDLE){ // 스크롤이 최상단인 상태면서 스크롤을 하지 않은 상태일때 btnFloating.startAnimation(fadeOut) // 애니메이션 적용 btnFloating.visibility = View.GONE isTop=true } else if(isTop) { btnFloating.visibility = View.VISIBLE btnFloating.startAnimation(fadeIn) // 애니메이션 적용 isTop=false } } }) btnFloating.setOnClickListener { rvMainList.smoothScrollToPosition(0) // 버튼을 눌렀을 때 최상단(position : 0)으로 이동 } }
참고한 사이트 : https://notepad96.tistory.com/190
금일 회고
상태:😀
회고:
어제 밤에 개인사정으로 조금 늦게 자서 그런지
오늘 아침에는 거의 헤롱헤롱하였다
운영체제 공부를 1시간30분만하고,, 나머지 오전 시간은... 결국 졸아버렸다 ㅠㅠ
그래도 자고 나니깐 개운해서 이후 오후시간에는 쭉 숙련 필수과제 완성과 플로팅버튼 선택과제에 집중할 수 있었다.
확실히 플로팅버튼 기능 자체는 안어려웠지만,
fade in 과 fade out 애니메이션 효과를 넣는것과
눌렸을 때 버튼 색상이 변경되도록 하는 부분에서 애를 먹었다
애니메이션은 아직 이해를 제대로 못하고 있는 부분이 많고
버튼의 색상 변경은 selector 를 이용하여 눌렸을때와 아닐때를 구분하여 색상만 다르도록 하면 되는데
그게 적용이 잘 되지 않는다
테마 에서 Material3를 APPCOMPAT으로 변경했었는데도 뭔가 버튼의 색상이 고정되어있다
backgroundTIlt를 건들여야 하는걸로 들었는데 결국 그렇게 해야하나보다.. ㅠㅠ
여튼 오늘도 시간이 매우 빠르게 지나갔다
오늘 공부한것도 머리에 잘 남아서 , 후에도 동일한 상황일때 잘 써먹을 수 있으면 좋겠다..
'개발공부 > 일지' 카테고리의 다른 글
다음글이 없습니다.이전글이 없습니다.댓글