首先,按设计Snackbar
不应该在点击动作后停留在那里,这就是为什么它是不可配置的参数。
深入研究代码,我可以找到足够的接缝,以便通过反射来做到这一点。
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);
}
这是经过测试并与支持库版本一起使用的25.3.1
。
用法
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();
}
结果
请注意,这不是您应该坚持使用的解决方案,只要 API 可能会因版本而异。您最好考虑实现您的自定义Snackbar
相似视图。但作为一种快速解决方法,您可以考虑使用此反射版本。