Barra de herramientas y barra de acción contextual con AppCompat-v7

182

Estoy trabajando para usar la barra de herramientas recién agregada que se introdujo en Lollipop y la biblioteca AppCompat-v7. Seguí esta guía sobre cómo configurar la barra de herramientas. Noté que cuando invocas algo que mostrará la barra de acción contextual (como resaltar texto para copiar / pegar), empujará la barra de herramientas hacia abajo en la página. Puedes ver de lo que estoy hablando en la imagen al final de la página:

Entonces, esencialmente, lo configuré así. Tengo la barra de herramientas definida en un archivo xml que uso con las etiquetas de inclusión:

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"/>

Luego, lo instancia en mi opinión:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id="@+id/root"
    tools:context=".MainActivity">

    <include
        layout="@layout/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/> 

    <!-- Rest of view -->

    </LinearLayout>

En código, lo configuré así:

    // On Create method of activity:
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

¿Alguien sabe cómo hacerlo para que la barra de acción contextual aparezca sobre la barra de herramientas?

Barra de herramientas y barra de acción contextual

ariets
fuente
¿Qué tema está usando tu actividad?
alanv
David, acabo de hacer clic en el enlace y parece estar funcionando para mí.
Ariets

Respuestas:

320

Actualizar:

Solución: use la propiedad windowActionModeOverlay . Establezca esto en su tema:

<item name="windowActionModeOverlay">true</item>

y el modo de acción se mostrará sobre la barra de acción en lugar de presionarlo hacia abajo. (Si no está utilizando la última AppCompat, debe agregar el prefijo "android:" a la propiedad). Básicamente, le permite a AppCompat saber que tiene una barra de herramientas ubicada en la parte superior de la pantalla y que debe dibujar el ActionMode encima.


Antigua respuesta / solución alternativa:

Tuve el mismo problema. No importa qué tema establezca, siempre empuja hacia abajo la barra de herramientas que configuré como ActionBar. Intenté con y sin la biblioteca de soporte, pero no importó.

Lamentablemente no pude solucionarlo, así que he creado una solución alternativa. En mi ActionModeCallback's onCreateActionModeme escondo la barra de acción:

actionBarToolbar.setVisibility(View.GONE);

y en onDestroyActionModelo muestro nuevamente:

actionBarToolbar.setVisibility(View.VISIBLE);

La ocultación / visualización ocurre tan rápido que no se nota en mis dispositivos de prueba. Por supuesto, hay un inconveniente: aunque la animación de entrada todavía funciona, la animación de salida de la barra de acción contextual se pierde porque la barra de herramientas aparece inmediatamente sobre ella. Pero hasta que encontremos una mejor solución, supongo que estamos atrapados con esto.


(Mi actividad en realidad está extendiendo una BaseActivityclase personalizada que tiene un método llamado getActionBarToolbar(), tomado del código fuente de la aplicación Google I / O 2014 , por lo que puedo obtener fácilmente la Barra de herramientas:

BaseActivity activity = (BaseActivity) getActivity();
activity.getActionBarToolbar().setVisibility(View.GONE);

Lástima que la aplicación de E / S no use la barra de acción contextual).

Jacob Ras
fuente
Sí, esta fue la única solución a la que también pude llegar. Sin embargo, hay casos en los que la barra de acción contextual ocurre desde el sistema (por ejemplo, en una vista web o con un texto de edición). Aquellos para los que no recibe las devoluciones de llamada. Entonces, ¿cómo harías para mostrarlo / ocultarlo para eso? (¿O me equivoco y, de hecho, puede obtener las devoluciones de llamada para el CAB con esos)?
Ariets
1
Sí, puede TextView.setCustomSelectionActionModeCallback () para eso, como Aleksandar describió en su respuesta.
Jacob Ras
1
Oh, ya no puedo actualizar mi comentario. Pequeña adición: parece que setCustomSelectionActionModeCallback no se puede usar con ActionModeCallback desde la biblioteca de soporte. Estoy usando una verificación VERSION.SDK_INT para configurarlo. Todavía necesita probar si el problema también ocurre en dispositivos anteriores al Honeycomb.
Jacob Ras
@ariets por favor vea mi respuesta actualizada. Me siento un poco mal por haber olvidado por completo esa propiedad, pero al menos podemos deshacernos de la solución ahora ;-)
Jacob Ras
1
Divertido que estoy usando la última (compilación 'com.android.support:appcompat-v7:22.0.0') pero tengo que dejar de lado el androide: parte para que funcione ...
Warpzit
16

No lo inicies en tu actividad, sino en tu barra de herramientas. En tu actividad:

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.startActionMode(mActionModeCallback)

y tienes que usar

<item name="windowActionModeOverlay">true</item>
Franco
fuente
para mí lo hace para android.support.v7.app.ActionBar
Frank
Me sale este error-> startActionMode (android.view.ActionMode.Callback) en View no se puede aplicar a (android.support.v7.view.ActionMode.Callback)
Faheem
Ah bien. Mi versión mínima no es menor que 11. Por lo tanto, puedo usar un android.view.ActionMode. Devolución de llamada en un android.support.v7.widget.Toolbar, nunca usé android.support.v7.view.ActionMode.Callback.
Frank
Vale la pena mencionar AppCompatActivity.startSupportActionMode(callback), para obtener compatibilidad con atributos como app:iconTinten el elemento de menú xmls.
Geekley
14

Solo una pequeña adición: para

<item name="windowActionModeOverlay">true</item>
para trabajar es importante llamar super.onCreate(savedInstanceState) ANTES de llamar setContentView(R.layout.your_activity)a su actividad. Realmente hace la diferencia en este caso!

Daniel Veihelmann
fuente
11

En mi caso, <item name="windowActionModeOverlay">true</item>no funcionó, pero este trabajo: <item name="android:windowActionModeOverlay">true</item>el androides la clave.

Jenkyn
fuente
8
Se usa <item name="windowActionModeOverlay">true</item>con la barra de herramientas appcompat, de lo contrario se usa el androidespacio de nombres
Javier Mendonça
no me sirve en mi diseño estoy agregando barra de herramientas, en la actividad inicializar barra de herramientas y establecer soporte verdadero hecho por favor ayúdame
Harsha
<item name = "windowActionModeOverlay"> true </item> ¡funcionó como se esperaba!
Francois
8

La solución de Jacob funcionó para mí, pero la ActionBar contextual era transparente y la barra de herramientas visible a través de ella. Esto se puede resolver de la siguiente manera:

<style name="AppTheme.Base" parent="Theme.AppCompat.Light">
    ....
    ....
    <item name="actionModeStyle">@style/CustomActionMode</item>
</style>

<style name="CustomActionMode" parent="@style/Widget.AppCompat.ActionMode">
    <item name="background">@color/primary_material_light</item>
</style>

El tema "AppTheme.Base" debe ser el aplicado a la barra de herramientas.

Más detalles sobre el estilo contextual de ActionBar:

Cómo personalizar la barra de acción contextual usando appCompat en diseño de materiales

Pete
fuente
0

Método muy útil para llevar la barra de herramientas al frente toolbar.bringToFront()

kunal.c
fuente
2
View.bringToFront()es una operación muy pesada y generalmente debe evitarse a toda costa.
dominus
Tiene razón, pero para la animación, por ejemplo, de arriba a abajo de la pantalla, se superpondrá a la barra de herramientas. Por lo tanto, debemos usar toolbar.bringToFront () para animar debajo de la barra de herramientas. Si hay alguna forma alternativa de compartir
:)
0

Otra pequeña adición: asegúrese de establecer al menos una pantalla vacía en la actividad a través de setContentView(R.layout.empty_screen)si carga toda la interfaz de usuario en fragmentos ( ft.replace(android.R.id.content, fragment)).

Andreas Wenger
fuente