ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • JetPack Compose 에서 CustomToast 구현하기
    Android/Compose 2024. 3. 19. 10:49
    반응형

     

    JetPack Compose 에서 기본 Toast UI 는 다음과 같다.

     

    그렇다면, [ 이미지 + 텍스트 ] 로 이루어진 Toast / Snackbar 를 구현해야 하는 경우는 어떻게 구현해야 할까?

     

    사이드 프로젝트 중인 Linkzip 많관부

     

     


    1. 토스트 메시지와 스낵바 중 선택하기

    처음에는 스낵바로 구현했으나 ..... 그러면.. 가장 하단 컴포넌트는 위로 밀리는거 왜 아무도 말 안해줬는데 ... .. . . . . .

    Linkzip 에서의 피드백 메시지는 Snackbar 보다는 Toast 의 특징을 나타내기에, CustomToast 로 구현하기로 결정 !

     

    (좌) 스낵바  (우) 토스트메시지

     

     

    - (참고) Toast vs Snackbar ( https://brunch.co.kr/@leesubella/10 )

    Toast Snackbar
    피드백 메시지만 전달 피드백 메시지 전달 + 간단한 유저 액션 가능
    다양한 위치에 배치 가능 플랫폼 상관 없이, 화면 하단에만 위치
    짧은 시간에 여러개 표시 가능 한 번에 하나씩만 표시 가능

     

     

     

    2. CustomToastUtil object 구현하기

    토스트 메시지의 view 를 그리는 역할

     

    예시 코드에서는 메시지와 아이콘만 변경할 수 있도록 매개변수를 설정했지만,

    배경색, 글자색, 패딩 등의 속성도 가변성이 있다면 매개변수로 설정해주면 된다.

    object CustomToastUtil {
    
        @Composable
        fun SetView(
            messageTxt: String,
            resourceIcon: Int
        ) {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                modifier = Modifier
                    .fillMaxWidth()
                    .background(
                        color = LinkZipTheme.color.wg70,
                        shape = RoundedCornerShape(size = 12.dp)
                    )
                    .padding(12.dp)
            ) {
                Icon(
                    painter = painterResource(id = resourceIcon),
                    contentDescription = "toastIcon",
                    tint = Color.Unspecified,
                    modifier = Modifier
                        .padding(start = 14.dp, end = 7.dp)
                )
                Text(
                    text = messageTxt,
                    style = LinkZipTheme.typography.medium12.copy(
                        color = LinkZipTheme.color.white
                    )
                )
            }
        }
    }

     

     

     

    3. CustomToast class 구현하기

    Toast 를 상속받아, 토스트 메시지를 화면에 띄우는 역할

     

    ComposeView 를 가진 변수 views 에, 위에서 구현한 Custom View 를 설정해준다.

    Toast의 view 와 duration 을 설정해주고, 기존과 마찬가지로 show() 메서드로 화면에 보여준다.

    class CustomToast(context: Context) : Toast(context) {
      @Composable
      fun MakeText(
           message: String,
           icon: Int,
           duration: Int = LENGTH_SHORT,
      ) {
          val context = LocalContext.current
          val views = ComposeView(context)
    
          views.setContent {
              CustomToastUtil.SetView(
                  messageTxt = message,
                  resourceIcon = icon,
              )
          }
           
          views.setViewTreeLifecycleOwner(LocalLifecycleOwner.current)
          views.setViewTreeSavedStateRegistryOwner(LocalSavedStateRegistryOwner.current) 
          views.setViewTreeViewModelStoreOwner(LocalViewModelStoreOwner.current)
     
          this.duration = duration
          this.view = views
          this.show()
       }
    }

     

     

    - (참고) setViewTreeLifeCycleOwner, setViewTreeSavedStateRegistryOwner, setViewTreeViewModelStoreOwner ?

    https://pluu.github.io/blog/android/2020/12/21/viewtreelifecycle/ )

     

    CustomView에서 LifecycleOwner / ViewModelStoreOwner / SavedStateRegistryOwner를 얻을 수 있게 되고,
    Lifecycle / ViewModelStore / SavedStateRegistry 를 얻을 수 있다.

    Lifecycle를 사용해 View의 생명주기를 observe 가능
    LifeCycleOwner를 통해서 LifecycleCoroutineScope 사용 가능 >> CoroutineScope.launch, launchWhen* 등 사용 가능
    ViewModelStore를 사용해 ViewModelProvider를 통해 ViewModel 객체를 생성 가능
    LiveData 생성 및 observe 가능

     

     

     

    4. 사용하기

    isShowToast 변수를 선언하여, 해당 값이 true 일 때 토스트 메시지 출력

     

    var isShowToast by remember { mutableStateOf(false) }
    
    ...
    
    if(isShowToast) {
        val customToast = CustomToast(LocalContext.current)
        customToast.MakeText(message = "그룹 추가완료!", icon = R.drawable.ic_check)
        isShowToast = false
    }

     

     

     

     

     

    반응형
Designed by Tistory.