android - layout_collapsemode - Barra de estado translĂșcida/transparente+CoordinatorLayout+Toolbar+Fragmento
coordinator behavior android (7)
Tengo la siguiente configuración:
- Estoy usando AppCompat
- MainActivity, que contiene un fragmento y tiene una barra de herramientas, que se oculta cuando se desplaza hacia abajo
-
Fragment
conRecyclerView
- Todas las vistas que deben ajustarse a la pantalla tienen el
android:fitsSystemWindows="true"
en el diseño xml
El problema es que no puedo obtener la barra de estado transparente en este caso. Lo que hago es seguir:
- Crea la actividad y llama a setContent.
Luego trato de ajustar la actividad para obtener mediante programación una barra de herramientas translúcida como la siguiente:
@TargetApi(Build.VERSION_CODES.LOLLIPOP) public void themeNavAndStatusBar(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return; Window w = activity.getWindow(); w.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); w.setFlags( WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); w.setFlags( WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); w.setNavigationBarColor(activity.getResources().getColor(android.R.color.transparent)); w.setStatusBarColor(activity.getResources().getColor(android.R.color.transparent)); }
Reemplace el marcador de posición en la actividad (
@+id/frame_container
) con el fragmento
La barra de estado es de color sólido en este caso, y las vistas no se dibujan debajo de ella ... ¿Por qué?
Lo que quiero
Quiero una barra de herramientas, que se desplace de la pantalla y se oculte por completo, mientras que el contenido debajo de esta barra de herramientas debe ajustarse en Pantalla y dibujarse detrás de la barra de navegación transparente.
Diseños
Aquí está mi actividad principal:
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/clMain"
android:fitsSystemWindows="true"
android:background="?attr/main_background_color"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:fitsSystemWindows="true"
android:background="@null"
app:elevation="0dp"
app:contentInsetLeft="0dp"
app:contentInsetStart="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="?actionBarThemeStyle"
app:popupTheme="?actionBarPopupThemeStyle"
app:layout_scrollFlags="scroll|enterAlways">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/ivToolbarDataSource"
android:layout_gravity="center_vertical"
android:layout_marginRight="2dp"
android:layout_width="24dp"
android:layout_height="24dp" />
<TextView
android:id="@+id/tvToolbarTitle"
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
android:theme="?actionBarThemeStyle"
android:layout_gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<TextView
android:id="@+id/tvToolbarSubTitle"
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle"
android:theme="?actionBarThemeStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</android.support.v7.widget.Toolbar>
<!-- BUG: http://stackoverflow.com/questions/30541409/coordinatorlayoutappbarlayout-does-not-draw-toolbar-properly -->
<View
android:layout_width="fill_parent"
android:layout_height="1dp"/>
</android.support.design.widget.AppBarLayout>
<FrameLayout
android:id="@+id/frame_container"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:layout_margin="32dp"
android:src="@drawable/ic_local_offer_white_24dp"
app:backgroundTint="?attr/colorPrimary"
app:borderWidth="0dp"
app:fabSize="normal"
app:rippleColor="?attr/colorPrimaryDark"
app:layout_anchorGravity="bottom|right|end"
app:layout_behavior="com.test.classes.ScrollAwareFABBehavior"/>
</android.support.design.widget.CoordinatorLayout>
Y aquí está mi fragmento, que se colocará en la actividad principal:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/srlImages"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/rvImages"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.v4.widget.SwipeRefreshLayout>
<TextView
android:id="@+id/tvEmpty"
android:gravity="center"
android:layout_centerInParent="true"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
EDITAR - Capturas de pantalla
Uso un tema base claro / oscuro y todo a mano (porque el usuario puede seleccionar cualquier color como color primario / acento), así que no importa que la barra de herramientas sea blanca (es el color de fondo del tema predeterminado y el color primario). También agregué un borde negro para que veas dónde termina la actividad ...
- Primera captura de pantalla: muestra la barra de herramientas, no se desplaza nada
- Segunda captura de pantalla: acabo de comenzar a desplazarme => la barra de herramientas ahora debería alejarse
- Tercera captura de pantalla: el contenido principal ahora debería desplazarse por debajo de la barra de navegación ...
Al final, por supuesto, haré que la barra de herramientas y la barra de navegación sean semi transparentes para un mejor efecto visual ...
Después de leer sus descripciones sobre su pregunta, pensé que los estilos de Google Photos coinciden con sus requisitos.
OK, solo hay algunos consejos para tu pregunta. Después de mi prueba, funciona.
- Si desea mostrar contenido detrás de la barra de estado, debe agregar
<item name="android:windowTranslucentStatus">true</item>
a su estilo cuando el nivel de la versión de Android sea mayor que 19 (a saber, KitKat ) - Si desea mostrar el contenido detrás de la barra de navegación, necesita agregar
<item name="android:windowTranslucentNavigation">true</item>
a su estilo cuando el nivel de la versión de Android sea mayor que 19 (es decir, KitKat ) - Si desea ocultar la
Toolbar
sin problemas cuando el contenido se desplaza hacia arriba y mostrarla sin problemas cuando se desplaza hacia abajo, debe agregar laapp:layout_collapseMode="parallax"
en los atributos de suToolbar
deToolbar
según sus códigos actuales. Por supuesto, necesita coordinar laToolbar
conCollapsingToolbarLayout
CoordinatorLayout
yAppBarLayout
.
Edite su styles.xml (v21), agregue el siguiente estilo
<style name="AppTheme.Home" parent="AppTheme.Base">
<!-- Customize your theme here. -->
<item name="android:windowTranslucentStatus">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:windowTranslucentNavigation">true</item>
</style>
Puede cambiar el tema principal según sus preferencias, pero ahora declare este tema en su archivo AndroidManifest.xml para una actividad particular como esta:
<activity
android:theme="@style/AppTheme.Home"
android:name=".HomeActivity"
android:launchMode="singleTop"
android:screenOrientation="portrait" />
Esto permitirá que su contenido sea visible bajo la barra de acción transparente.
Ahora use lo siguiente para alinear correctamente su barra de herramientas debajo de la Barra de estado, llame esto en su oncreate:
toolbar.setPadding(0, getStatusBarHeight(), 0, 0);
Obtenga la altura de la barra de estado usando lo siguiente:
public int getStatusBarHeight() {
int result = 0;
int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
}
Elimine lo siguiente de las etiquetas de diseño de su coordinador:
android:fitsSystemWindows="true"
Ahora, para contraer u ocultar su barra de herramientas, puede consultar el siguiente tutorial:
http://antonioleiva.com/collapsing-toolbar-layout/
Asegúrese de que está utilizando la siguiente versión de la biblioteca de soporte de diseño, ya que está libre de errores:
compile ''com.android.support:design:23.1.0''
Para mí, la razón no fue que no funcionara per se, sino que uso la biblioteca de materiales de Mike Penz y esta biblioteca usa pantalla completa + desplazamiento + fondo personalizado detrás de la barra de herramientas, así que tuve que resolver el problema respetando ese aspecto especial. preparar...
Sin embargo, recompensaré los puntos de la respuesta más informativa en mi opinión ...
Tuve el mismo problema y mi solución fue agregar android: fitsSystemWindows = "true" al DrawerLayout
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
....
</android.support.v4.widget.DrawerLayout>
Tuve problemas relevantes dependiendo de la configuración de android: fitsSystemWindows. Una vez falso: se dibujaron bocadillos debajo de la barra de navegación Una vez falso: la barra de estado no tenía fondo transparente
La solución fue realmente simple ... Solo para agregar android: layout_marginBottom = "48dp". Para el coordinador de la sesión así:
just to add <android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:map="http://schemas.android.com/apk/res-auto"
tools:context=".MapsActivity"
android:id="@+id/coordinatorLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="false"
android:layout_marginBottom="48dp">
En teoría, la barra de navegación debería tener un tamaño fijo "48dp", pero en futuras versiones potencialmente podría cambiar (como que la barra de estado se hizo más delgada en 1dp en Marshmallow), así que no confiaría en un tamaño fijo. Mejor también obtenerlo y aplicar en tiempo de ejecución.
Si está utilizando Google Map como yo, es posible que desee saber el tamaño de la barra de herramientas / barra de herramientas y la barra de navegación en tiempo de ejecución:
en onCreate usa este código:
final TypedArray styledAttributes = MapsActivity.this.getTheme().obtainStyledAttributes(
new int[]{android.R.attr.actionBarSize});
mToolbarHeight = (int) styledAttributes.getDimension(0, 0);
styledAttributes.recycle();
// translucent bars code. Will not fire below Lollipop
// Ask NavigationBar Height
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.coordinatorLayout),
new OnApplyWindowInsetsListener() { // setContentView() must be fired already
@Override
public WindowInsetsCompat onApplyWindowInsets(View v, WindowInsetsCompat insets) {
statusBar = insets.getSystemWindowInsetTop(); // You may also need this value
mNavBarHeight = insets.getSystemWindowInsetBottom();
if (mMap != null)
mMap.setPadding(0, mToolbarHeight, 0, mNavBarHeight);
// else will be set in onMapReady()
SharedPreferences.Editor editor = mSharedPref.edit();
editor
.putInt(NAVBAR_HEIGHT_KEY, mNavBarHeight)
.commit(); // Save the results in flash memory and run the code just once on app first run instead of doing it every run
return insets;
}
}
);
Y lo que es importante. Si tiene algunas capas adicionales, como el cajón, etc., póngalas en un encapsulado de CoordinatorLayout en el interior en lugar de en el exterior, ya que de lo contrario hará que otras vistas en el interior sean más cortas por el margen de fondo
como dijeron algunos usuarios, al configurar android:fitsSystemWindows="false"
, el diseño se superpuso debajo de la statusbar
.
Lo resolví configurando android:fitsSystemWindows="true"
y en la app:statusBarBackground="@android:color/transparent"
configuración de etiquetas CoordinatorLayout
app:statusBarBackground="@android:color/transparent"
.
tl; dr Establecer android:fitsSystemWindows="false"
al menos a la raíz CoordinatorLayout
y al contenedor de fragmentos interno, @frame_container
.
Es posible que esta no sea la solución final (es decir, podría haber otros fitsSystemWindows
a la fitsSystemWindows
de fitsSystemWindows
), así que dígame si tiene algún problema.
por qué
Cuando se trata de la barra de estado, creo que se fitsSystemWindows
a fitsSystemWindows
como:
-
fitsSystemWindows="false"
: dibuja la vista normalmente, debajo de la barra de estado debido a los indicadores de ventana que ha establecido. -
fitsSystemWindows="true"
: dibuja la vista normalmente, debajo de la barra de estado debido a los indicadores de ventana que ha establecido, pero agrega un relleno superior para que el contenido se dibuje debajo de la barra de estado y no se superpongan.
De hecho, en mi opinión, el blanco que ves no es el color de la barra de estado, sino el fondo de tu CoordinatorLayout
. Esto se debe a fitsSystemWindows="true"
en el coordinador: dibuja el fondo a toda la ventana, pero agrega un relleno superior al contenido para que las vistas internas no estén cubiertas por la barra de estado.
Esto no es lo que quieres. Su contenido interno debe estar cubierto por la barra de estado, por lo que debe configurar fitsSystemWindows="false"
para el coordinador (para que no se aplique el relleno superior) y probablemente para el contenido en sí.
Una vez que entienda cómo funciona, es fácil depurar y lograr el efecto que está buscando . En realidad, no lo es. Los años pasan, pero aún paso horas tratando de encontrar la combinación adecuada de windowsSystemWindows, porque la mayoría de las Vistas (al menos en las bibliotecas de soporte) anulan el comportamiento predeterminado que mencioné anteriormente, en formas que en su mayoría no son intuitivas. Vea este post para una pequeña guía sobre cómo usarlo.