Material Design의 BottomNavigationView를 사용해본 적이 있다면 매우 간편하게 Badge를 업데이트 할 수 있음을 경험한 적이 있을 것이다.
금번에 뱃지를 BottomNavigationView가 아닌 별도 View(이를테면 TextView 라던지)에 달아야 하는 경우가 생겼는데,
쓸만하고 예쁘다 싶은 라이브러리가 잘 없었기에, Material의 Badge가 떠오르는 건 어쩔 수가 없었다.
그런데 다행스럽게도 구글에서 Material Components 1.1.0-alpha09 버전부터 Badge를 지원하고 있다는 반가운 소식!
기쁜 마음으로 텍스트 뷰 옆에 뱃지를 붙이고 싶어 공식 문서를 들여다 보았으나..
여타 잘 정리되지 않은 구글 문서처럼 해당 페이지만을 기반으로 적용을 하는 건 쉽지 않았다
결국 참을인 세 번에 검색 세 번을 해서 참조하기 좋은 소스를 좀 찾아낼 수 있었는데 핵심은
FrameLayout과 FrameLayout 안에 nested layout을 사용하는 것이었다. (이유에 대해선 Material Design 공식 문서를 참조)
< BadgeDrawable 일반 View에 적용하는 법 >
1. MaterialDesign dependency를 gradle에 추가한다. (20년 10월 14일자 최신 버전 : 1.2.1)
implementation "com.google.android.material:material:1.2.1"
2. BadgeDrawable을 적용하고자 하는 layout을 FrameLayout으로 감싼다.
뱃지는 FrameLayout 내부에서만 보여지기 때문에, FrameLayout을 작게 잡으면 Badge가 잘리는 현상이 생긴다.
3. BadgeDrawable을 적용하고자 하는 layout을 아래의 스니펫을 참조해 적용한다.
본인의 경우 Fragment 내에서 뱃지를 적용했기 때문에 requireContext()를 이용해 context를 넘겨주었다. color를 넘겨줄 때도 Fragment에서 사용하던 방식을 썼다.
- BadgeDrawable을 create할 때 원하는 디자인 요소와 설정을 적용한다. (테스트를 위해 별도로 변수로 지정 안했지만, 지정하게 되면 이후에 조작도 가능할 듯 하다)
- BadgeDrawable을 감싸주었던 frameLayout의 foreground에 설정한다.
- BadgeDrawable을 감싸준 frameLayout에 addOnLayoutChangeListener를 지정해, 내부에서 attatchBadgeDrawable을 수행한다.
- attatchBadgeDrawable(뱃지 Drawable, 뱃지를 달고자 하는 target, 먼저 지정해준 frameLayout)
< 추가 >
참조로 badgeGravity에는 네 개의 옵션이 있으며, 이에 따라 Badge가 달리는 지점을 설정해 줄 수 있음.
Badge는 붙이고자 하는 대상 뷰 영역에 붙기 때문에, 공간을 두고자 하는 경우 해당 뷰의 padding을 주는 등의 처리를 하면 간격 처리를 손쉽게 가능.
뱃지의 Visibility는 BadgeDrawable의 visiblity를 조정한 뒤, BadgeDrawable이 포함된 FrameLayout을 invalidate해 주어야 최종 반영되는 것을 확인했다.
BadgeDrawable.create(requireContext()).apply {
number = 5
backgroundColor = ContextCompat.getColor(requireContext(), R.color.bgColor)
badgeTextColor = ContextCompat.getColor(requireContext(), R.color.textColor)
badgeGravity = BadgeDrawable.TOP_END
}.let {
binding.frameLayout.foreground = it
binding.frameLayout.addOnLayoutChangeListener {v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom ->
BadgeUtils.attachBadgeDrawable(it, binding.target, binding.frameLayout)
}
마지막으로 Material Component들은 해당 레이아웃이 사용되는 Activity의 테마가 Material이 달린 것 중에 하나로 지정되야 하는 걸 유의하자.
그리고 혹 적용 중 ... can only be called from within the same library group 식의 오류가 발생한다면, 프로젝트 레벨의 gradle 파일에 아래 lint 옵션을 적용하자.
android {
lintOptions {
disable 'RestrictedApi'
}
}
문서는 아쉽지만 BadgeDrawable의 클래스 내부에 도큐먼트가 잘 정리되어 있으니, 사용하고 싶은 요소들, 제어하고 싶은 요소들을 찾아서 적용한다면 어렵지 않게 응용이 가능할 것이다!
< 참조 >
'ANDROID > UI - UX' 카테고리의 다른 글
[Android/UI-UX] 텍스트의 일부에 스타일 및 터치 이벤트 설정하기 (0) | 2022.02.24 |
---|---|
[Android/UI-UX] 유동적인 TextView의 사이즈를 제한하고, 정렬까지(with ConstraintLayout) (0) | 2021.03.09 |
[안드로이드] Material Design의 Chips를 사용해보자 (0) | 2020.05.16 |
[안드로이드 | 코틀린 ] 뷰가 겹치는 상황에서 터치 우선순위 관리하기 (0) | 2020.04.14 |
[안드로이드] Elevation 효과가 적용된 CardView ViewPager 구현하기 (0) | 2020.04.05 |