Barra degli strumenti e ActionBar contestuale con AppCompat-v7


182

Sto lavorando per utilizzare la barra degli strumenti appena aggiunta che è stata introdotta in Lollipop e nella libreria AppCompat-v7. Ho seguito questa guida sull'impostazione della barra degli strumenti e ho notato che quando invochi qualcosa che attiverà la barra contestuale (come evidenziare il testo per copiare / incollare), spingerà la barra degli strumenti verso il basso sulla pagina. Puoi vedere di cosa sto parlando nell'immagine in fondo alla pagina:

Quindi, essenzialmente, l'ho impostato in questo modo. Ho la barra degli strumenti definita in un file xml che utilizzo con i tag include:

<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"/>

Quindi, ho un'istanza a mio avviso:

<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>

Nel codice, l'ho impostato in questo modo:

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

Qualcuno sa come farlo in modo che la ActionBar contestuale si sovrapponga alla barra degli strumenti?

Barra degli strumenti e barra contestuale


Quale tema utilizza la tua attività?
alanv,

David, ho appena cliccato sul link e sembra funzionare per me.
Ariete

Risposte:


320

Aggiornare:

Soluzione: utilizzare la proprietà windowActionModeOverlay . Imposta questo nel tuo tema:

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

e la modalità di azione verrà mostrata sopra la barra delle azioni invece di spingerla verso il basso. (Se non stai utilizzando l'AppCompat più recente, devi aggiungere il prefisso "android:" alla proprietà). In sostanza, AppCompat sa che hai una barra degli strumenti situata nella parte superiore dello schermo e che dovrebbe disegnare ActionMode su di essa.


Vecchia risposta / soluzione alternativa:

Ho riscontrato lo stesso problema. Indipendentemente dal tema che ho impostato, spinge sempre verso il basso la barra degli strumenti che ho impostato come ActionBar. Ho provato con e senza la libreria di supporto, ma non importava.

Purtroppo non sono stato in grado di risolverlo, quindi ho creato una soluzione alternativa. Nel mio ActionModeCallback's onCreateActionModemi nascondo nella barra delle operazioni:

actionBarToolbar.setVisibility(View.GONE);

e in onDestroyActionModelo mostro di nuovo:

actionBarToolbar.setVisibility(View.VISIBLE);

Nascondersi / mostrare avviene così rapidamente che non si nota sui miei dispositivi di prova. C'è ovviamente un rovescio della medaglia: sebbene l'animazione enter funzioni ancora, l'animazione di uscita della barra delle azioni contestuali si perde perché la barra degli strumenti si apre immediatamente su di essa. Ma fino a quando non troveremo una soluzione migliore, credo che ne siamo bloccati.


(La mia attività sta attualmente estendendo una BaseActivityclasse personalizzata che ha un metodo chiamato getActionBarToolbar(), preso dal codice sorgente dell'app I / O 2014 di Google , in modo da poter facilmente recuperare la barra degli strumenti:

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

Peccato che l'app I / O non utilizzi la barra delle azioni contestuali.)


Sì, questa era l'unica soluzione a cui potevo arrivare. Tuttavia, ci sono casi in cui la ActionBar contestuale si verifica dal sistema (ad esempio in un WebView o con un EditText). Quelli per cui non si ottengono i callback. Quindi, come faresti a mostrarlo / nasconderlo per quello? (O sbaglio e puoi, in effetti, ottenere i callback per il CAB con quelli)?
Ariete

1
Sì, puoi TextView.setCustomSelectionActionModeCallback () per questo, come Aleksandar ha descritto nella sua risposta.
Jacob Ras,

1
Oh, già non riesco più ad aggiornare il mio commento. Piccola aggiunta: sembra che setCustomSelectionActionModeCallback non possa essere utilizzato con ActionModeCallback dalla libreria di supporto. Sto usando un controllo VERSION.SDK_INT per impostarlo. Devo ancora verificare se il problema si verifica anche su dispositivi pre-Honeycomb.
Jacob Ras,

@ariets, per favore, vedi la mia risposta aggiornata. Mi sento un po 'fuori di testa per aver completamente dimenticato quella proprietà, ma almeno ora possiamo sbarazzarci della soluzione alternativa ;-)
Jacob Ras,

1
Divertente sto usando l'ultimo (compilare 'com.android.support:appcompat-v7:22.0.0') ma devo lasciare fuori l'androide: parte perché funzioni ...
Warpzit,

16

Non avviarlo sulla tua attività, ma sulla barra degli strumenti. Nella tua attività:

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

e devi usare

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

per me lo fa per android.support.v7.app.ActionBar
Frank

Ottengo questo errore-> startActionMode (android.view.ActionMode.Callback) in View non può essere applicato a (android.support.v7.view.ActionMode.Callback)
Faheem

Ah ok. La mia versione minima non è più piccola di 11. Quindi posso usare un android.view.ActionMode. Richiamata su un android.support.v7.widget.Toolbar, non ho mai usato android.support.v7.view.ActionMode.Callback.
Frank,

Vale la pena menzionare AppCompatActivity.startSupportActionMode(callback), per ottenere la compatibilità con gli attributi come app:iconTintnella voce di menu xmls.
Geekley,

14

Solo una piccola aggiunta: per

<item name="windowActionModeOverlay">true</item>
per lavorare è importante chiamare super.onCreate(savedInstanceState) PRIMA di chiamare setContentView(R.layout.your_activity)nella tua attività. In questo caso fa davvero la differenza!


11

Nel mio caso, <item name="windowActionModeOverlay">true</item>non ha funzionato, ma questo lavoro: <item name="android:windowActionModeOverlay">true</item>il androidè la chiave.


8
Si utilizza <item name="windowActionModeOverlay">true</item>con la barra degli strumenti di appcompat, altrimenti si utilizza lo androidspazio dei nomi.
Javier Mendonça,

inutile per me nel mio layout sto aggiungendo la barra degli strumenti, nell'attività inizializza la barra degli strumenti e imposta il supporto vero fatto per favore aiutatemi
Harsha

<item name = "windowActionModeOverlay"> true </item> ha funzionato come previsto!
Francois,

8

La soluzione di Jacob ha funzionato per me, ma la ActionBar contestuale era trasparente e la barra degli strumenti era visibile attraverso di essa. Questo può essere risolto come segue:

<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>

Il tema "AppTheme.Base" deve essere quello applicato alla barra degli strumenti.

Maggiori dettagli sullo stile contestuale di ActionBar:

come personalizzare la barra di azione contestuale usando appCompat nella progettazione dei materiali


0

Metodo molto utile per portare in primo piano la barra degli strumenti toolbar.bringToFront()


2
View.bringToFront()è un'operazione molto pesante e generalmente dovrebbe essere evitata ad ogni costo.
Dominus

Hai ragione, ma per l'animazione, ad esempio dall'alto verso il basso dello schermo, si sovrapporrà alla barra degli strumenti. Quindi dobbiamo usare toolbar.bringToFront () per animare sotto la barra degli strumenti. Se c'è un modo alternativo che puoi condividere
:)

0

Un'altra piccola aggiunta: assicurati di impostare almeno uno schermo vuoto nell'attività tramite setContentView(R.layout.empty_screen)se carichi l'intera interfaccia utente in frammenti ( ft.replace(android.R.id.content, fragment)).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.