본문 바로가기

TIL

[TIL] Lambda를 이용해 Dialog 분리해서 제어하기, FloatingButton으로 RecyclerView 스크롤 상단으로 이동하기

[오늘 배운 내용]

-1- Lambda식 이용해서 Dialog 분리해서 제어하기

  • 기존에 Dialog를 띄우기 위해서 Dialog를 생성하고 바로 적용해보았다.
  • 앱에 다이얼로그 종류가 하나였던 경우는 못 봤던 것 같고, 현재 진행하고 있는 과제에서도 Dialog를 여러개 띄워야 하는 상황인데 Dialog가 필요할 때마다 일일이 Dialog를 만들어야 한다면 상당히 귀찮을 것 같다.
  • 일반 AlertDialog 를 베이스로 생성하고 Dialog의 버튼 선택 경우의 수가 같다면 미리 Dialog를 생성해두고, Dilog의 Title, Message, Positive버튼을 눌렀을 때의 이벤트와 Negative버튼을 눌렀을 때의 이벤트를 각각 다르게 지정할 수 있게 해주면 Dialog가 필요한 상황에서 일일이 만들 필요가 없어질 것이다.

 

ShowDialog.Class

class ShowDialog {
    fun showDialog(context: Context, setTitle: String, setMessage: String, completion: () -> Unit) {
        val builder = AlertDialog.Builder(context)
        builder.apply {
            setTitle(setTitle)
            setMessage(setMessage)
            setIcon(R.drawable.baseline_android_24)
            setPositiveButton("확인") { dialogInterface: DialogInterface, i: Int -> completion() }
            setNegativeButton("취소") { dialogInterface: DialogInterface, i: Int -> dialogInterface.dismiss() }
            show()
        }
    }
}
  • showDialog() 내부의 completion: () -> Unit 으로 별도로 함수를 선언하지 않고 곧바로 람다식 자체를 showDialog의 파라미터로 지정 해두었다.
  • 별도로 함수를 지정하지 않은 이유는, setPositivtButton을 눌렀을 때 필요한 기능들이 전부 Unit형이지 않기 때문
    • RecyclerView에서 특정 Item을 길게 눌렀을 때 Dialog창을 띄우고, PositiveButton으로 해당 ListItem을 삭제 하기 위해서 removeAt[Index] 을 해야 할 경우, removeAt[Index] 는 ItemData값이기 때문에 별도로 변환해줘야 한다 

 

Main.kt

// 뒤로가기 버튼 클릭 이벤트 : callback 인스턴스 생성
        val callback = object : OnBackPressedCallback(true) {
            override fun handleOnBackPressed() {
                ShowDialog().showDialog(this@MainActivity, "앱 종료", "앱을 종료하시겠습니까?") { finish() }
            }
        }
        
        
 // RecyclerView Item 길게 클릭 시 Item[position]의 Data 삭제하는 Dialog 출력
        myAdapter.itemLongClick = object : MyAdapter.ItemLongClick {
            val context = binding.root.context
            override fun onLongClock(view: View, position: Int) {
                Log.d("TAG", "onLongClock: ${position} 롱 클릭 ")
                val showDialog = ShowDialog()
                // ShowDialog에서 Dialog만 받아오고 positiveButton 클릭 시, ltemList.removeAt(position)
                showDialog.showDialog(context, "아이템 삭제 알림", "아이템을 삭제하시겠습니까?") {
                    itemList.removeAt(position)
                    myAdapter.notifyItemRemoved(position)
                }
            }
        }
  • ShowDialog 클래스를 통해 Dialog를 띄울 수 있게 되었다.
  • 마지막 파라미터가 람다식이면 중괄호 { } 부분을 소괄호 밖으로 뺄 수 있다

 

 

정상적으로 Dialog창 확인.

 

 

 

-2- FloatingButton으로 RecyclerView 스크롤 상단으로 이동하기

  • RecyclerView의 스크롤을 감지해서, 상단이 아니라면 FloatingButtion을 보이게하고, 상단으로 갔을 시 FloatingButton이 보여지지 않도록 Animation을 통해 설정해보자.
  • 적용코드
// floatingButton Animation 설정
        val fadeIn = AlphaAnimation(0f, 1f).apply { duration = 500 }
        val fadeOut = AlphaAnimation(1f, 0f).apply { duration = 500 }
        var isTop = true

        binding.recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                if (!binding.recyclerView.canScrollVertically(-1)
                    && newState == RecyclerView.SCROLL_STATE_IDLE
                ) {
                    binding.mainFloatBtn.startAnimation(fadeOut)
                    binding.mainFloatBtn.visibility = View.GONE
                    isTop = true
                } else if (isTop) {
                    binding.mainFloatBtn.visibility = View.VISIBLE
                    binding.mainFloatBtn.startAnimation(fadeIn)
                    isTop = false
                }
            }
        })

        // RecyclerView 스크롤 상단 이동 floationg버튼
        binding.mainFloatBtn.setOnClickListener {
            binding.recyclerView.smoothScrollToPosition(0)
        }
  • AlphaAnimation 클래스를 사용하여 500ms 동안 실행되는 Animation 생성하고, isTop 변수를 초기값 true로 설정해둔다.
  • RecyclerView의 스크롤 리스너를 익명 클래스의 형태로 RecyclerView.OnScrollListener을 상속받아 스크롤이 되지 않은 상태인 SCROLL_STATE_IDLE, 스크롤이 맨 위에 위치하고 있는 상태를 나타내는 canScrollVertically(-1) 의 조건을 충족할 경우 FloatingButton이 보여지지 않도록 fadeOut Animation이 실행되고 visibility 를 gone으로 설정.
  • 스크롤이 상단이 아닌 경우, FloatingButton이 보여지도록 else if ~ 코드 작성

 

  • 마지막으로 FloatingButton 클릭 시 recylcerView의 스크롤이 상단으로 가게끔 smoothScrollToPosition(0)으로 이동.

 

-3-

 

 

 

 


 

[오늘 복습한 내용]

1.

 

2.

 

3.

 


[오류,에러 등등]

1.

 

2.

 

3.

 


[느낀 점]

1.

 

2.

 

3.

 

 


[Reference]

 

// RecyclerView FloatingButtion

https://notepad96.tistory.com/190?category=947414

// refresh

https://todaycode.tistory.com/55

// Lambda

https://blog.yena.io/studynote/2017/11/22/Kotlin-Lambda.html