First, by design Snackbar
shouldn't stay there after the action click, that's why it is non-configurable parameter.
Diving into code I could find enough seams in order to do that 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 support library version 25.3.1
.
Usage
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

BEWARE, this is not the solution you should prefer to stick with, as long as API may change from version to version. You'd better consider implementing your custom Snackbar
alike view. But as a fast workaround you can consider using this reflectioned version.