Prevent Snackbar from disabling when clicking an action

How to prevent Android Snackbar blocking on setAction onclick, thanks

Snackbar.make(rootlayout, "Hello SnackBar!", Snackbar.LENGTH_INDEFINITE) .setAction("Undo", new View.OnClickListener() { @Override public void onClick(View v) { // Snackbar should not dismiss } }) .show(); 
+5
source share
2 answers

Firstly, by design, Snackbar should not stay there after clicking an action, so it is not a custom parameter.

Immersed in the code, I was able to find enough seams to do this by reflection.

 public static void doNotHideSnackbar(Snackbar snackbar) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException { final Field sHandler = BaseTransientBottomBar.class.getDeclaredField("sHandler"); sHandler.setAccessible(true); final Method handleMessage = Handler.class.getMethod("handleMessage", Message.class); final Handler originalHandler = (Handler) sHandler.get(snackbar); Handler decoratedHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() { @Override public boolean handleMessage(Message message) { switch (message.what) { case 0: try { handleMessage.invoke(originalHandler, Message.obtain(originalHandler, 0)); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return true; } return false; } }); sHandler.set(snackbar, decoratedHandler); } 

This is tested and works with the support library version 25.3.1 .

Using

 final Snackbar snackbar = Snackbar.make(root, "Hello SnackBar!", Snackbar.LENGTH_INDEFINITE).setAction("Undo", new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(v.getContext(), "clicked", Toast.LENGTH_SHORT).show(); } }); snackbar.show(); try { doNotHideSnackbar(snackbar); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } 

Result

enter image description here

BEWARE is not the solution you prefer to stick with if the API can change from version to version. You should better consider implementing a custom Snackbar . But as a quick workaround, you can use this mirrored version.

0
source

Better late than never - here, as I did.

 private fun showSnackbar() { if(snackbar == null) { //init snackbar snackbar = Snackbar.make(mainCoordinator, R.string.snackbar_no_network, Snackbar.LENGTH_INDEFINITE) .setAction(R.string.snackbar_no_network_action) { checkConnection() } // action text on the right side .setActionTextColor(ContextCompat.getColor(context, R.color.snack_green)) //set background color snackbar!!.view.setBackgroundColor(ContextCompat.getColor(context, R.color.main_dark_gray)) } //show snackbar!!.show() } private val handler = Handler() private fun checkConnection() { handler.postDelayed(checkConnectionRunnable, 500) } private val checkConnectionRunnable = Runnable { if (!NetworkUtil.isOnline(context)){ showSnackbar() } } 
-1
source

Source: https://habr.com/ru/post/1258387/


All Articles