스낵바가 자동으로 종료되었을 때 어떻게 알림을받을 수 있습니까?


82

com.android.support:design:22.2.0도서관 에서 스낵바를 사용하고 있습니다. 삭제를 취소하는 데 사용하고 있습니다. 내 삶을 더 쉽게 만들기 위해 UI를 실제로 데이터 소스에서 삭제 된 것처럼 보이게 만들고 스낵바의 실행 취소 버튼을 누르지 않으면 실제로 데이터 소스에서 삭제를 수행합니다. 따라서 Snackbar가 더 이상 표시되지 않는시기를 알고 싶으므로 항목을 삭제하는 것이 안전합니다.

Snackbar에서 getView ()를 호출 할 수 있지만 어떤 리스너를 사용해야하는지 잘 모르겠습니다. 시도 setOnSystemUiVisibilityChangeListener()했지만 작동하지 않았습니다. 시스템 상태 표시 줄에만 해당한다고 생각합니다.

또한 Snackbar에는 개인 생성자가 있으므로 확장 할 수 없습니다.


1
이 기능은 지원 설계 라이브러리의 다음 릴리스 될 것입니다
타일러 파프

답변:


179

Google 디자인 라이브러리는 버전 23에서 Snackbar 콜백을 지원합니다. Snackbar 문서콜백 문서를 참조하세요 . 그러면 Snackbar가 닫힐 때 (및 표시 될 때) 알림을 받게되며, 이것이 유용한 경우 닫힘 유형도 알려줍니다.

snackbar.addCallback(new Snackbar.Callback() {

    @Override
    public void onDismissed(Snackbar snackbar, int event) {
      //see Snackbar.Callback docs for event details
      ...  
    }

    @Override
    public void onShown(Snackbar snackbar) {
       ...
    }
  });

13
setCallback ()은 이제 더 이상 사용되지 않습니다. 대신 사용하여 다음 addCallBack ()
jds17

41
snackbar.addCallback(new Snackbar.Callback() {

    @Override
    public void onDismissed(Snackbar snackbar, int event) {
        if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
            // Snackbar closed on its own
        }
    }

    @Override
    public void onShown(Snackbar snackbar) {
        ...
    }
});

4
actionText 클릭 할 때 onDismissed도 호출되기 때문에 좋은는, 이벤트를 언급
암로 elaswar

2
대부분의 경우 if (event != Snackbar.Callback.DISMISS_EVENT_ACTION)대신 확인하는 것이 가장 좋습니다. 그렇지 않으면 사용자가 수동으로 닫거나 스낵바가 다른 스낵바에 의해 닫히면 닫기 로직이 실행되지 않습니다.
shyamal

이 라인 주셔서 감사합니다event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT
Pratik Butani

18

Kotlin의 Snackbar.addCallback

val snackBar = Snackbar
                .make(view, "Text Snackbar", Snackbar.LENGTH_LONG)
                .addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
                    override fun onShown(transientBottomBar: Snackbar?) {
                        super.onShown(transientBottomBar)
                    }

                    override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
                        super.onDismissed(transientBottomBar, event)
                    }
                })

        val snackBarView = snackBar.view
        snackBarView.setBackgroundColor(Color.RED)
        snackBar.show()

16

최근에 스크롤하고 Snackback을 표시 할 때이 문제를 직접 발견했습니다. 첫 번째 항목이 사라지기도 전에 너무 많이 표시되었습니다. 앱이 스낵바를 설치해야하는지 알 수있는 방법을 찾아야했습니다.

개인적으로이 해결책을 찾았습니다.

사실 Snackbar 자체는 상태 / 가시성에 대한 리스너를 제공하지 않지만 Snackbar (getView ();)에서 View Object를 가져올 수 있습니다. View Object에서 다양한 메서드를 사용하여 리스너를 추가 할 수 있습니다.

이를 구현하려면 리스너를 추가하면 void를 반환하므로 일반적인 "일체형"Toast / Snackbar 사용에서 벗어나야합니다 .

개인적으로 OnAttachStateChangeListener를 찾았습니다.

유용 할 경우를 대비하여 내 코드와 함께 스니퍼를 떨어 뜨립니다.

Snackbar snack = Snackbar.make(getView(), "My Placeholder Text", Snackbar.LENGTH_LONG);

snack.getView().addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
    @Override
        public void onViewAttachedToWindow(View v) {
            canDisplaySnackbar = false;
        }

    @Override
    public void onViewDetachedFromWindow(View v) {

        Handler h = new Handler();
        h.postDelayed(new Runnable() {
            @Override
            public void run() {
                canDisplaySnackbar = true;

                }
        }, 1000);
    }
});
snack.show();

이것은 내 문제에 대한 내 구현 일뿐입니다. postDelayed Runnable이있는 Handler는 귀하의 경우에도 적합하지 않을 수 있습니다. 내가 이미 소유 한 스 니펫을 사용하여 제안한 구현에 대한 일반적인 아이디어를 제공하기위한 것입니다.


4
and_dev의 andswer가 이제 더 나은 대답입니다.
Islam A. Hassan

12

스낵바가 표시되거나 닫 혔을 때 알림을 받으려면 setCallback (Callback)을 통해 Snackbar.Callback을 제공 할 수 있습니다.


setCallBack은 이제 더 이상 사용되지 않습니다. 대신 addCallBack을 사용하십시오.
mjn42

5

onDismissed는 액션 텍스트가 클릭 될 때도 호출됩니다.

event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT

이제 새 코드는 다음과 같습니다.

final Snackbar snackBar = Snackbar.make(findViewById(R.id.root_layout), result, Snackbar.LENGTH_LONG);

snackbar.addCallback(new Snackbar.Callback() {

@Override
public void onDismissed(Snackbar snackbar, int event) {
 if (event == Snackbar.Callback.DISMISS_EVENT_TIMEOUT) {
        // Snackbar closed on its own
    }  
}

@Override
public void onShown(Snackbar snackbar) {
...
}
});
snackBar.show();

코드 전용 답변은 미래의 독자들에게 많은 정보를 제공하지
않기 때문에 권장되지 않습니다.

대부분의 경우 if (event != Snackbar.Callback.DISMISS_EVENT_ACTION)대신 확인하는 것이 가장 좋습니다. 그렇지 않으면 사용자가 수동으로 닫거나 스낵바가 다른 스낵바에 의해 닫히면 닫기 로직이 실행되지 않습니다.
shyamal


3

현재 스낵바 표시가 완료되면 알림을받을 수있는 방법이 없습니다.

이 스레드에서는 스낵바 표시 기간 동안의 타이머를 기반으로 한 해결 방법에 대해 설명합니다. 지원 라이브러리의 스낵바에 OnDismissListener ()가 포함되어 있지 않습니까?

이 해결 방법에서 고려해야 할 한 가지 문제는 스낵바 기간이 다시 시작될 수 있다는 것입니다. Snackbar머티리얼 디자인 사양에 따르면 관련없는 대화 상자 또는 팝업이 표시 될 경우 이런 일이 발생합니다.


1

현재 당신은 그것을 달성 할 수 없습니다.

스낵바가 닫힐 때 호출되는 청취자가 없습니다.

이를 수행하는 가장 쉬운 방법은 레코드를 다른 곳에 (지역 변수 포함) 임시로 저장 한 다음 실행 취소 버튼을 눌렀을 경우 다시 삽입하는 것입니다.


1
    snackbar.addCallback(new Snackbar.Callback() {
        public void onShown(Snackbar snackbar) {
           //  on show  
        }
 public void onDismissed(Snackbar snackbar, int event) {
          //  on dismiss  
        }
      });

코드 스 니펫과 함께 설명 / 설명을 제공하세요.
Janis F

1

나는 당신과 똑같은 문제가 있습니다. 내 해결책은 ...

              final Snackbar povrati_obrisani_unos = Snackbar.make (coordinatorLayout, "Ponisti brisanje", Snackbar.LENGTH_INDEFINITE)
                    .addCallback (new Snackbar.Callback (){
                        @Override
                        public void onDismissed(Snackbar transientBottomBar, int event) {
                            super.onDismissed (transientBottomBar, event);
                            if(event==DISMISS_EVENT_SWIPE){//here we detect if snackbar is swipped away and not cliked (which is undo in my case)
                                Uri uriDelete = Uri.parse (obrisano.getImageuri ());
                                ContentResolver contentResolver = getContentResolver();
                                contentResolver.delete (uriDelete, null, null);
                                Toast.makeText (MainActivity.this,
                                        "Ocitavanje i slika su trajno obrisani", Toast.LENGTH_SHORT).show ();
                            }

그게 다입니다. 실행 취소 인 snackbar.action을 복사하여 붙여넣고 싶지 않습니다. 내가 여기서 가능한 한 명확하게하고 싶다.

감사합니다 Nenad


0

Kotlin의 @SergeyMilakov 덕분에 다음 과 같습니다.

@SuppressLint("WrongConstant") // Suppress an error when set duration.
private fun showSnackbar() {
    val DURATION = 5000

    Snackbar.make(view!!, "Remove item?"), DURATION).apply {
        setAction("Undo") {
            // Your action when a button is clicked.
        }
        addCallback(object : BaseTransientBottomBar.BaseCallback<Snackbar>() {
            /* override fun onShown(transientBottomBar: Snackbar?) {
                super.onShown(transientBottomBar)
                Timber.d("*** onShown")
            }*/

            override fun onDismissed(transientBottomBar: Snackbar?, event: Int) {
                super.onDismissed(transientBottomBar, event)
                if (event != Snackbar.Callback.DISMISS_EVENT_ACTION) {
                    // Your action when the Snackbar is closed and the button was not clicked.
                }

            }
        })
        view.setBackgroundColor(ContextCompat.getColor(context, R.color.black))
        setActionTextColor(ContextCompat.getColor(context, R.color.yellow))
        show()
    }
}

참고 Snackbar당신이 (다시, 예를 들어) 다른 화면으로 이동하는 경우에도 보여줍니다. 따라서 올바른 화면에서 작업을 수행하는지 확인하는 것을 잊지 마십시오.

또한 Snackbar화면 회전 후 복원되지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.