Coloque Snackbar en el orden z más alto para evitar ser bloqueado por AutoCompleteTextView desplegable
Tengo un Snackbar
que es como sigue:
- Sugerencia de float de AutoCompleteTextView
- Android- Problema con reemplazo de tamaño de imagen en versiones android diferentes para el texto MultiAutoCompleteTextview
- ¿Cómo implementar autocompletetextview con listview?
- Google Place API - autocompletar - cómo obtener código postal?
- Cómo mostrar las sugerencias de AutoCompleteTextView en orientación horizontal
Sin embargo, si la lista desplegable de AutoCompleteTextView
es demasiado larga, la lista desplegable bloqueará la Snackbar
.
Como se puede ver en la imagen anterior, la Snackbar
está mostrando. Sin embargo, su visibilidad está bloqueada por la larga caída hacia abajo. Usted puede ver de la imagen de arriba
Intento utilizar el siguiente Snackbar code
. Añadir bringToFront()
no ayuda mucho.
private void showSnackbar(String message) { Snackbar snackbar = Snackbar.make(getActivity().findViewById(R.id.content), message, Snackbar.LENGTH_LONG); snackbar.getView().bringToFront(); snackbar.show(); }
R.id.content
es un CoordinatorLayout
:
<android.support.design.widget.CoordinatorLayout android:id="@+id/content" android:background="?attr/MyActivityBackground" android:layout_width="match_parent" android:layout_height="match_parent" android:foreground="?attr/headerShadow" />
¿Hay alguna buena manera, para evitar Snackbar
de ser cubierto por AutoCompleteTextView
's desplegable?
- AutoCompleteTextView no funciona cuando introdujo el primer carácter
- AutoCompleteTextView no muestra ningún elemento desplegable
- AutoCompleteTextView onItemClick posición del artículo o id usando HashMap
- Diseño de material Android: eliminar animación de sugerencias
- Falta el diccionario predeterminado en AutoCompleteTextView / MultiAutoCompleteTextView
- Cómo configurar el cursor a la derecha (EditText)?
- AutocompleteTextView dinámico con ArrayAdapter y TextWatcher
- Cambiar filtro AutoCompleteTextView de "startsWith" a "Contains"?
Podría tener una solución para ese caso. Por supuesto, hay algunas suposiciones, pero tal vez la solución le conviene.
La clave aquí es poner AutoCompleteTextView
dentro de CoordinatorLayout
y añadir CoordinatorLayout.Behavior
personalizado a ella.
-
Cree el
Behavior
apropiado para su clase:public class AutoCompleteTextViewBehaviour extends CoordinatorLayout.Behavior<AutoCompleteTextView> { public AutoCompleteTextViewBehaviour(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean layoutDependsOn(CoordinatorLayout parent, AutoCompleteTextView child, View dependency) { return dependency instanceof Snackbar.SnackbarLayout; } }
-
Anular un método
layoutDependsOn
:@Override public boolean layoutDependsOn(CoordinatorLayout parent, AutoCompleteTextView child, View dependency) { return dependency instanceof Snackbar.SnackbarLayout; }
-
Obtener referencia a la vista emergente
AutoCompleteTextView
:Lamentablemente no he encontrado una solución simple para eso. Sin embargo se puede hacer a través de la reflexión.
@Nullable private View getPopupList(AutoCompleteTextView child) { try { Field popupField; Class clazz; if (child instanceof AppCompatAutoCompleteTextView) { clazz = child.getClass().getSuperclass(); } else { clazz = child.getClass(); } popupField = clazz.getDeclaredField("mPopup"); popupField.setAccessible(true); ListPopupWindow popup = (ListPopupWindow) popupField.get(child); Field popupListViewField = popup.getClass().getDeclaredField("mDropDownList"); popupListViewField.setAccessible(true); return (View) popupListViewField.get(popup); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return null; }
-
onDependentViewChanged
overrideonDependentViewChanged
:@Override public boolean onDependentViewChanged(CoordinatorLayout parent, final AutoCompleteTextView child, View dependency) { if (popupList == null) { popupList = getPopupList(child); if (popupList == null) { return super.onDependentViewChanged(parent, child, dependency); } } int dropdownBottom = child.getBottom() + child.getDropDownVerticalOffset() + popupList.getHeight(); int snackBarTop = dependency.getTop(); int difference = dropdownBottom - snackBarTop; if (difference > 0) { child.setDropDownHeight(popupList.getHeight() - difference); return true; } else { child.setDropDownHeight(ViewGroup.LayoutParams.WRAP_CONTENT); } return super.onDependentViewChanged(parent, child, dependency); }
-
Aplique el comportamiento a
AutocompleteTextView
en.xml
:app:layout_behavior="com.example.package.AutoCompleteTextViewBehaviour"/>
Por supuesto, esta es una solución muy básica, que por ejemplo no anima la altura de la lista, pero creo que esto es un buen comienzo. Aquí está la esencia completa.
Puede calcular y ajustar la altura de la ventana emergente como una alternativa. En la siguiente imagen, estoy configurando la altura de la lista desplegable como abajo:
textView.viewTreeObserver.addOnGlobalLayoutListener { textView.dropDownHeight = snackbarView.top - textView.bottom }
Este cálculo es para el caso en que la altura de la lista de sugerencias es lo suficientemente larga. Es posible que desee establecer esa propiedad en WRAP_CONTENT
en WRAP_CONTENT
lugar.
Por lo que sé, no es posible cambiar el "orden z" a menos que añada la barra de Snack directamente al WindowManager
. AutoCompleteTextView
internamente está usando ListPopupWindow
para mostrar la ventana de sugerencias y ListPopupWindow
tiene el tipo de ventana de WindowManager.LayoutParams.TYPE_APPLICATION_PANEL
= 1000 que es mayor que el tipo de ventana de Activity que es de WindowManager.LayoutParams.TYPE_APPLICATION
= 2.
¿Por qué no acaba de establecer android:dropDownHeight
a un valor fijo dp
? Incluso puede definirlo para que se base dinámicamente en el tamaño de la pantalla por referencia a un recurso de dimension
. Es una línea de código, resuelve su problema, fácil de mantener y de entender (en seis meses usted se preguntará, para qué se utiliza todo el material de Behavior
).
Pienso que usted tiene que tomar muchos piensa en la consideración:
- Debe haber espacio para todos. Teclado, snackbar y autocompletar Textview
- No puede cambiar la altura del teclado (por su aplicación), por lo que debe cambiar la altura del Autocompletar TextView por encima de la barra de menús (que está por encima del teclado)
Paso 1. Implementar un nuevo comportamiento
Es necesario comprobar si el dispositivo operativo admite snackbar.
public class MoveUpwardBehavior extends CoordinatorLayout.Behavior<View> { private static final boolean SNACKBAR_BEHAVIOR_ENABLED; @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { return SNACKBAR_BEHAVIOR_ENABLED && dependency instanceof Snackbar.SnackbarLayout; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight()); child.setTranslationY(translationY); return true; } static { SNACKBAR_BEHAVIOR_ENABLED = Build.VERSION.SDK_INT >= 11; } }
Paso 2. Implementar vista personalizada para que podamos aplicar MoveUpwardBehavior a ella.
En este caso, hacemos que LinearLayout interactúe con snackbar. Es muy fácil, como se ha dicho, pasar la clase a la anotación DefaultBehavior.
@CoordinatorLayout.DefaultBehavior(MoveUpwardBehavior.class) public class CustomLinearLayout extends LinearLayout { public CustomLinearLayout(Context context) { super(context); } public CustomLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } }
Paso 3. Casi Terminado!
Añadir CustomLinearLayout en el diseño. Recuerde, debe ser incluido por CoordinatorLayout!
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.alisondemo.musicgenre.CustomLinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> ... </com.example.alisondemo.musicgenre.CustomLinearLayout> </android.support.design.widget.CoordinatorLayout>
Pero … ¿por qué ni siquiera tenemos que implementar el comportamiento para FAB?
Forme el código fuente de la clase android.support.design.widget.FloatingActionButton, como puede ver:
@DefaultBehavior (FloatingActionButton.Behavior.class) public class FloatingActionButton extends ImageView {… Sí, en realidad tiene su propio comportamiento implementado.
Conclusión
Podemos implementar cualquier tipo de comportamiento que queramos en cualquier punto de vista. Debe ser muy interesante. 🙂
Usted puede ver sólo demo: http://alisonhuang-blog.logdown.com/posts/290009-design-support-library-coordinator-layout-and-behavior
El código fuente completo está ahora en GitHub https://github.com/Alishuang/MusicGenre