¿Hay alguna forma de hacer Snackbar persisten entre los cambios de actividad?
Aunque Snackbar
es hermoso, no persiste al cambiar actividades. Esto es una lástima en los escenarios donde me gustaría confirmar que un mensaje fue enviado usando una Snackbar
, antes de terminar la actividad. He considerado pausar el código antes de salir de la actividad, pero he encontrado que para ser una mala práctica.
Si lo que describo no es posible, ¿hay algún tipo de material de mensaje de brindis de diseño? O una manera de hacer un mensaje de tostada rectangular; Uno con bordes redondeados de un radio más pequeño?
- Uso de la versión 1.0.0-alpha7 de la biblioteca de restricciones, que es obsoleta
- Java.lang.NoClassDefFoundError: com.acme.R $ layout que hace referencia a la biblioteca android
- Android Studio: Error al analizar SDK puede estar faltando los complementos de directorio
- Bibliotecas de Android en Android Studio
- Android Studio nuevo proyecto no se puede ejecutar, lanzando error
- ¿Por qué mi configuración de ejecución está deshabilitada en Android Studio?
- Android Studio - Todos los nombres de archivo en el proyecto son de color rojo, pero no hay errores
- Android Studio está listo para la producción?
- com.android.build.gradle.internal.model.ApiVersionImpl no se puede transmitir a java.lang.Integer mientras migra el proyecto AS a IDEA
- ¿Cómo comprobar el idioma de un dispositivo en android?
- Permisos de geolocalización insuficientes
- No se puede cambiar el tamaño del almacenamiento interno del emulador de Android a través de AVD, config.ini o resize2fs
- Android Studio: Nuevo directorio creado que no aparece en la vista de carpetas
Para crear una Snackbar con el contexto de la aplicación que es visible en varias actividades:
- Obtener el
WindowManager
como servicio del sistema - Cree y agregue un
FrameLayout
( rootView ) con el tipoWindowManager.LayoutParams.TYPE_TOAST
yWindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
alWindowManager
- Espere hasta que
FrameLayout.onAttachedToWindow()
se llame enFrameLayout
( rootView ) - Obtener el token de ventana de
FrameLayout
( rootView ) conView.getWindowToken()
- Crear un
ContextThemeWrapper
con el contexto de la aplicación y un derivado@style/Theme.AppCompat
- Utilice el nuevo contexto para crear un
FrameLayout
adicional ( snackbarContainer ) - Agregue este
FrameLayout
( snackbarContainer ) con el tipoWindowManager.LayoutParams.TYPE_APPLICATION_PANEL
y flagWindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
- Espere hasta que
View.onAttachedToWindow()
se llame en elFrameLayout
( snackbarContainer ) - Cree la Snackbar como de costumbre con
FrameLayout
( snackbarContainer ) - Establezca la devolución de llamada
View.onDismissed()
a la Snackbar y elimine FrameLayouts ( rootView y snackbarContainer ) - Mostrar el snackbar
Snackbar.show()
Aquí hay un wrapper de trabajo ( NOTA: Deslizar para descartar no funciona, quizás alguien más encuentre los indicadores correctos de Fijo por CoordinatorLayout): WindowManager.LayoutParams
para recibir eventos táctiles
public class SnackbarWrapper { private final CharSequence text; private final int duration; private final WindowManager windowManager; private final Context appplicationContext; @Nullable private Snackbar.Callback externalCallback; @Nullable private Action action; @NonNull public static SnackbarWrapper make(@NonNull Context applicationContext, @NonNull CharSequence text, @Snackbar.Duration int duration) { return new SnackbarWrapper(applicationContext, text, duration); } private SnackbarWrapper(@NonNull final Context appplicationContext, @NonNull CharSequence text, @Snackbar.Duration int duration) { this.appplicationContext = appplicationContext; this.windowManager = (WindowManager) appplicationContext.getSystemService(Context.WINDOW_SERVICE); this.text = text; this.duration = duration; } public void show() { WindowManager.LayoutParams layoutParams = createDefaultLayoutParams(WindowManager.LayoutParams.TYPE_TOAST, null); windowManager.addView(new FrameLayout(appplicationContext) { @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); onRootViewAvailable(this); } }, layoutParams); } private void onRootViewAvailable(final FrameLayout rootView) { final CoordinatorLayout snackbarContainer = new CoordinatorLayout(new ContextThemeWrapper(appplicationContext, R.style.FOL_Theme_SnackbarWrapper)) { @Override public void onAttachedToWindow() { super.onAttachedToWindow(); onSnackbarContainerAttached(rootView, this); } }; windowManager.addView(snackbarContainer, createDefaultLayoutParams(WindowManager.LayoutParams.TYPE_APPLICATION_PANEL, rootView.getWindowToken())); } private void onSnackbarContainerAttached(final View rootView, final CoordinatorLayout snackbarContainer) { Snackbar snackbar = Snackbar.make(snackbarContainer, text, duration); snackbar.setCallback(new Snackbar.Callback() { @Override public void onDismissed(Snackbar snackbar, int event) { super.onDismissed(snackbar, event); // Clean up (NOTE! This callback can be called multiple times) if (snackbarContainer.getParent() != null && rootView.getParent() != null) { windowManager.removeView(snackbarContainer); windowManager.removeView(rootView); } if (externalCallback != null) { externalCallback.onDismissed(snackbar, event); } } @Override public void onShown(Snackbar snackbar) { super.onShown(snackbar); if (externalCallback != null) { externalCallback.onShown(snackbar); } } }); if (action != null) { snackbar.setAction(action.text, action.listener); } snackbar.show(); } private WindowManager.LayoutParams createDefaultLayoutParams(int type, @Nullable IBinder windowToken) { WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(); layoutParams.format = PixelFormat.TRANSLUCENT; layoutParams.width = WindowManager.LayoutParams.MATCH_PARENT; layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT; layoutParams.gravity = GravityCompat.getAbsoluteGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM, ViewCompat.LAYOUT_DIRECTION_LTR); layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; layoutParams.type = type; layoutParams.token = windowToken; return layoutParams; } @NonNull public SnackbarWrapper setCallback(@Nullable Snackbar.Callback callback) { this.externalCallback = callback; return this; } @NonNull public SnackbarWrapper setAction(CharSequence text, final View.OnClickListener listener) { action = new Action(text, listener); return this; } private static class Action { private final CharSequence text; private final View.OnClickListener listener; public Action(CharSequence text, View.OnClickListener listener) { this.text = text; this.listener = listener; } } }
EDITAR
Una vez que SnackbarWrapper
está definido, puedes usarlo así:
final SnackbarWrapper snackbarWrapper = SnackbarWrapper.make(getApplicationContext(), "Test snackbarWrapper", Snackbar.LENGTH_LONG); snackbarWrapper.setAction(R.string.snackbar_text, new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "Action", Toast.LENGTH_SHORT).show(); } }); snackbarWrapper.show();
Si no tienes un tema, puedes definirlo rápidamente en styles.xml
:
<style name="FOL_Theme_SnackbarWrapper" parent="@style/Theme.AppCompat"> <!--Insert customization here--> </style>
Si entiendo correctamente, usted hace esto:
- Actividad A iniciar Actividad B para enviar un mensaje
- Una vez enviado el mensaje, se muestra un mensaje de confirmación
- Regresa a la Actividad A
Puedes usar SnackBar para hacer eso usando un ActivityResult ( aquí hay un post StackOverflow con cómo usarlo)
Estos son los pasos:
- Actividad Actividad de lanzamiento B con startActivityForResult
- Haga sus cosas en la Actividad B
- Establezca el resultado (compruebe el vínculo anterior)
- Finalizar la actividad
- En la actividad A, obtenga ese código en OnActivityResult y muestre su SnackBar con el mensaje correcto
Esto le permite mostrar un Snackar en la Actividad A correspondiente al resultado de la Actividad B.
Esperanzas puede ayudar a su problema
Para tener un Toast
rectangular, establezca un fondo rectangular para el Toast o simplemente establezca un color de fondo diferente para el Toast.
Refiera este mensaje donde fue publicado como un problema. Pero en su caso es una posible solución.
ACTUALIZACIÓN: Ver la respuesta seleccionada.
La mejor solución a mi pregunta es usar un Timer
después de la presentación de la Snackbar
y luego en el método run()
del temporizador, iniciando la actividad.
Snackbar.show(); // Excluded make for brevity. Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { Intent chooseVideoIntent = new Intent(Intent.ACTION_GET_CONTENT); // Any type of content/file. Song, doc, video... chooseVideoIntent.setType("video/*"); startActivityForResult(chooseVideoIntent, CHOOSE_VIDEO_REQUEST); } }, 2 * 1000);
UPDATE: Encontré que usando findViewById(android.R.id.content)
como la vista en Snackbar.make()
la findViewById(android.R.id.content)
persiste entre los cambios de fragmento .
- OpcionesMenú de fragmentos en Viewpager mostrando los botones del otro
- Google play services 8.4.0 – classes.jar no encontrado – android studio