2013-03-07 28 views
36

C'è un modo per eseguire il rendering di una vista sopra la barra delle azioni? Voglio creare un piccolo tip tip che indirizzerà l'utente a un elemento nella barra delle azioni. So che un Toast con una vista impostata verrà visualizzato sopra la barra delle azioni. Qualcuno sa come farlo con una vista?visualizzazione di visualizzazione nella parte superiore della barra delle azioni

Ho tentato di utilizzare FrameLayout con layout_gravity="top" e gonfiare una vista e quindi aggiungerla al layout dell'attività in esecuzione.

Ti ringrazio in anticipo.

Edit: Ecco un'immagine di quello che stavo pensando: enter image description here

Edit: Forse è necessario un po 'più in dettaglio. Sto cercando un modo, o per scoprire se è anche possibile aggiungere una vista alla gerarchia della vista dell'attività in modo che sia reso per ultimo.

Analogamente al CSS, voglio un ordine z-index più alto per questa vista particolare (la casella blu nell'immagine), in modo tale che venga visualizzata nella parte superiore della barra delle azioni nell'attività. La vista non è in alcun modo associata alla barra delle azioni, è semplicemente disegnata sopra di essa.

+0

Hai trovato una soluzione a questo problema? Sto volendo eseguire lo stesso compito nella mia app ora, ma non vedo nessuna risposta rilevante qui sotto. –

+0

@MM Dai un'occhiata alla mia risposta. L'ho appena aggiunto. – Sean

risposta

21

Dopo aver lottato con me stesso un po 'di tempo, ecco la soluzione (testato - lavorare bene):

I passi generali sono:

  1. creare una vista involucro
  2. Stacca lo schermo visualizza i bambini, posiziona l'involucro e allega i bambini
  3. Gonfia il contenuto ai bambini
  4. Il controllo del wrapper ti aiuterà a controllare esattamente la barra delle azioni e il contenuto sottostante.
  5. Ora, utilizzando il wrapper, è possibile aggiungere "fratelli" alla barra delle azioni/area principale. Quel fratello è esattamente ciò che hai descritto nella tua immagine.

Vediamo un po 'di codice.

Innanzitutto, creare un metodo per aiutare a creare una vista wrapper. il wrapper verrà posizionato tra l'intero schermo e il contenuto della tua app. essendo uno ViewGroup puoi in seguito controllare completamente il suo contenuto.

private ViewGroup setContentViewWithWrapper(int resContent) { 
     ViewGroup decorView = (ViewGroup) this.getWindow().getDecorView(); 
     ViewGroup decorChild = (ViewGroup) decorView.getChildAt(0); 

     // Removing decorChild, we'll add it back soon 
     decorView.removeAllViews(); 

     ViewGroup wrapperView = new FrameLayout(this); 

     // You should set some ID, if you'll want to reference this wrapper in that manner later 
     // 
     // The ID, such as "R.id.ACTIVITY_LAYOUT_WRAPPER" can be set at a resource file, such as: 
     // <resources xmlns:android="http://schemas.android.com/apk/res/android"> 
     //  <item type="id" name="ACTIVITY_LAYOUT_WRAPPER"/> 
     // </resources> 
     // 
     wrapperView.setId(R.id.ACTIVITY_LAYOUT_WRAPPER); 

     // Now we are rebuilding the DecorView, but this time we 
     // have our wrapper view to stand between the real content and the decor 
     decorView.addView(wrapperView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 
     wrapperView.addView(decorChild, decorChild.getLayoutParams()); 
     LayoutInflater.from(this).inflate(getActivityLayout(), 
        (ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(1), true); 

     return wrapperView; 
    } 

Ora, interferiscono con il normale Activity creazione, e invece di usare setContentView, utilizzare il metodo che abbiamo creato.

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    // DON'T CALL `setContentView`, 
    // we are replacing that line with this code: 
    ViewGroup wrapperView = setContentViewWithWrapper(R.layout.activity_layout); 

    // Now, because the wrapper view contains the entire screen (including the notification bar 
    // which is above the ActionBar) I think you'll find it useful to know the exact Y where the 
    // action bar is located. 
    // You can use something like that: 
    ViewGroup actionBar = (ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(0); 
    int topOffset = actionBar.getTop(); 

    // Now, if you'll want to add a view: 
    // 1. Create new view 
    // 2. Set padding top - use "topOffset" 
    // 3. Add the view to "wrapperView" 
    // 4. The view should be set at front. if not - try calling to "bringToFront()" 
} 

Questo è tutto.

Note

  • ho usato Android's hierarchy-viewer per capire qual è la gerarchia giusta. (Non immagino quei 0 e 1 indici)
  • Se si utilizza un qualche tipo di un cassetto menù nella vostra attività, potrebbe essere necessario configurarlo un po 'diverso in quanto i cassetti stanno già creando che wrapper per voi
  • ho imparato molto, cercando in this great library

EDIT: fare riferimento a @ CristopherOyarzúnAltamirano risposta per un ulteriore supporto più recenti versioni di Android

Buona fortuna!

+0

Ehi amico. Ho alcuni problemi con l'implementazione di questa soluzione per Android 4.4. Ho questa eccezione, qualche idea? com.android.internal.widget.ActionBarOverlayLayout non può essere lanciato su android.widget.LinearLayout. – Dan1one

+2

Questo è lavoro per ICS e Jelly, ma Ginger e Kitkat disegnano gerarchia in un modo diverso. –

+0

@ CristopherOyarzúnAltamirano Proprio così. – Sean

0

Utilizzare android:actionLayout nel file menu.xml.

<?xml version="1.0" encoding="utf-8"?><menu xmlns:android="http://schemas.android.com/apk/res/android"> 
<item android:id="@+id/menu_id" 
     android:title="@string/menu_string_to_show" 
     android:icon="@drawable/ic_menu_icon_name" 
     android:showAsAction="always" 
     android:actionLayout="@layout/action_button_foo" /></menu> 

quindi creare il layout di action_button_foo.xml:

<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:gravity="center" 
android:text="@string/menu_string_to_show" 
android:drawableLeft="@drawable/ic_menu_icon_name" 
android:background="@drawable/bg_btn_action_bar" 
android:clickable="true" /> 

Per gestire fare clic effettuare le seguenti operazioni:

@Overridepublic boolean onCreateOptionsMenu(Menu menu) { 
getMenuInflater().inflate(R.menu.my_menu, menu); 

final MenuItem item = menu.findItem(R.id.menu_id); 
item.getActionView().setOnClickListener(new OnClickListener() { 
    @Override 
    public void onClick(View v) { 
     onOptionsItemSelected(item); 
    } 
}); 

return super.onCreateOptionsMenu(menu);} 

Ecco se :)

+0

Grazie per la rapida risposta! Ma credo che questo stia creando una voce di menu per la barra delle azioni? Voglio solo disegnare una vista in cima alla barra delle azioni. Ma questa vista non dovrebbe essere parte della barra delle azioni, non è reattiva. – lunaleaps

+0

Cosa intendi per visione? –

+0

Sarebbe una TextView in un file di layout e uno sfondo di immagine. Se guardi l'immagine aggiunta nel mio OP, sarebbe la scatola blu mobile – lunaleaps

1

Prova utilizzando ActionBar.setCustomView (). Questo è l'unico modo per cambiare l'aspetto di quell'area dello schermo. Non è possibile inserire una vista nell'area "sopra" l'ActionBar, poiché tale area è sostanzialmente controllata dal sistema. D'altra parte, lo può fornire il proprio layout per lo.

Se spieghi più in dettaglio che cosa stai cercando di fare, i rispondenti potrebbero avere alcune idee di progettazione migliori.

+0

Cool, ho incluso un'immagine di ciò che stavo pensando. Vedo che Toasts può avere un set di visualizzazione. E sono curioso di sapere come rendono i loro punti di vista in cima alla barra delle azioni. – lunaleaps

0

(Riferimento: http://www.vogella.com/articles/AndroidActionBar/article.html)
Visualizzazioni personalizzate nella ActionBar
È inoltre possibile aggiungere una visualizzazione personalizzata alla ActionBar. Per questo si utilizza il metodo setCustomView per la classe ActionView. È inoltre necessario abilitare la visualizzazione di viste personalizzate tramite il metodo setDisplayOptions() passando il flag ActionBar.DISPLAY_SHOW_CUSTOM.

Ad esempio, è possibile definire un file di layout che contiene un elemento EditText.

<?xml version="1.0" encoding="utf-8"?> 
<EditText xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/searchfield" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:inputType="textFilter" > 

Questa disposizione può essere assegnato alla ActionBar tramite il seguente codice. Il codice di esempio consente di collegare un listener alla vista personalizzata.

package com.vogella.android.actionbar.customviews; 

import android.app.ActionBar; 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.KeyEvent; 
import android.widget.EditText; 
import android.widget.TextView; 
import android.widget.TextView.OnEditorActionListener; 
import android.widget.Toast; 

public class MainActivity extends Activity { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 

ActionBar actionBar = getActionBar(); 
// add the custom view to the action bar 
actionBar.setCustomView(R.layout.actionbar_view); 
EditText search = (EditText) actionBar.getCustomView().findViewById(R.id.searchfield); 
search.setOnEditorActionListener(new OnEditorActionListener() { 

    @Override 
    public boolean onEditorAction(TextView v, int actionId, 
     KeyEvent event) { 
    Toast.makeText(MainActivity.this, "Search triggered", 
     Toast.LENGTH_LONG).show(); 
    return false; 
    } 
}); 
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM 
    | ActionBar.DISPLAY_SHOW_HOME); 
} 
} 
+0

Ah, ok, da quello che ho capito, stai aggiungendo una notifica 'Toast' quando clicco sulla barra delle azioni, in particolare su' EditText'. Mi stavo chiedendo di più su come rendere visivamente una vista/layout sulla parte superiore della barra delle azioni. Come so come Android crea una gerarchia di viste. Come posso inserire una vista da renderizzare per ultima nella gerarchia in modo che appaia "sopra" la barra di azione nel senso di ordinare z-index o "portare la vista in primo piano". O è persino possibile? In ogni caso, grazie per il tuo aiuto Vishal. – lunaleaps

+0

Quindi stai dicendo che devi inserire una vista personalizzata sulla barra delle azioni senza usare setCustomView. Penso che tu debba andare alla barra delle azioni personalizzata. –

+0

Meglio andare per barra delle azioni personalizzata (Crea la tua barra delle azioni). Puoi fare quello che vuoi con quello. –

5

ho trovato questa soluzione in base alla risposta @Sean:

 //This is for Jelly, ICS, Honeycomb 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB && Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2){ 
      LayoutInflater.from(this).inflate(resContent, (ViewGroup)((LinearLayout)wrapperView.getChildAt(0)).getChildAt(1), true);} 
     //This is for KitKat and Jelly 4.3 
     else if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2){ 
      LayoutInflater.from(this).inflate(resContent, (ViewGroup) (((ViewGroup) wrapperView.getChildAt(0)).getChildAt(0)), true);} 
     //This is for Ginger 
     else{ 
      LayoutInflater.from(this).inflate(resContent, (ViewGroup) ((LinearLayout)((FrameLayout) wrapperView.getChildAt(0)).getChildAt(0)).getChildAt(1), true);} 
+1

Ho un errore sui dispositivi Gingerbird con questo metodo. L'ho modificato in questo modo: LayoutInflater.from (this) .inflate (resContent, (ViewGroup) ((FrameLayout) decorChild), true); –

14

C'è un modo molto più semplice per raggiungere questo obiettivo. ActionBar mantiene il suo layout nella classe ActionBarContainer che eredita semplicemente da FrameLayout. Quindi, per visualizzare qualcosa sopra l'ActionBar, devi prendere un riferimento a ActionBarContainer e aggiungere la tua visualizzazione personalizzata al suo interno. Ecco il codice

int abContainerViewID = getResources().getIdentifier("action_bar_container", "id", "android");  
    FrameLayout actionBarContainer = (FrameLayout)findViewById(abContainerViewID);  
    LayoutInflater myinflater = getLayoutInflater();   
    View customView = myinflater.inflate(R.layout.yourCustomeViewLayout, null); 
    actionBarContainer.addView(customView); 
29

Stavo cercando di ottenere qualcos'altro ma avevo bisogno di una soluzione simile a questa. Avevo bisogno di disegnare uno strato opaco che coprisse l'intero schermo, anche la barra delle azioni, una specie di finestra di dialogo.L'ho fatto in questo modo:

ViewGroup vg = (ViewGroup)(getWindow().getDecorView().getRootView()); 
vg.addView(myNewView, params); 

questo può essere utilizzato per disegnare qualsiasi cosa sullo schermo.

2

Ho trovato un modo molto più semplice per farlo. Ho appena applicato android: translationZ = "10dp" alla vista che devo coprire la barra delle azioni.

ho scelto 10dp ma in realtà può essere tutto quello che vuoi, purché sia ​​superiore alla quota del ActionBar

<ImageView 
     android:layout_width="100dp" 
     android:layout_height="100dp" 
     android:translationZ="10dp" 
     android:src="@drawable/potatoe" /> 

Inoltre, non ti preoccupare seguente avviso Android di Studio:

"translationZ non può essere utilizzato con l'API < 21".

verrà ignorato, ma non mi interessa, perché la barra degli strumenti non deve coprire la tua vista con le API inferiore a 21.

Problemi correlati