web-dev-qa-db-fra.com

afficher la vue en haut de la barre d'action

Existe-t-il un moyen de rendre une vue au-dessus de la barre d'actions? Je veux créer une petite boîte à astuces qui dirigera l'utilisateur vers un élément de la barre d'action. Je sais qu'un Toast avec une vue d'ensemble sera rendu au-dessus de la barre d'action. Est-ce que quelqu'un sait comment faire cela avec une vue?

J'ai tenté d'utiliser FrameLayout avec layout_gravity="top" et gonfler une vue, puis l'ajouter à la présentation de l'activité en cours.

Je vous remercie d'avance.

Edit : Voici une image de ce que je pensais: enter image description here

Edit : Peut-être que des détails supplémentaires sont nécessaires. Je cherche un moyen, ou pour savoir s'il est même possible d'ajouter une vue à la hiérarchie des vues de l'activité pour qu'elle soit restituée en dernier.

Semblable à CSS, je veux un ordre d'index z plus élevé pour cette vue particulière (la boîte flottante bleue dans l'image), de sorte qu'elle soit rendue au-dessus de la région de la barre d'action dans l'activité. La vue n'est en aucun cas associée à la barre d'actions, elle est simplement dessinée par dessus.

37
lunaleaps

Après avoir lutté avec moi-même un certain temps, voici la solution (testée - fonctionnant bien):

Les étapes générales sont les suivantes:

  1. Créer une vue wrapper
  2. Détachez les enfants de la vue d'écran, placez l'emballage et fixez les enfants
  3. Gonflez le contenu aux enfants
  4. Le contrôle de l'encapsuleur vous aidera à contrôler exactement la barre d'actions et le contenu en dessous.
  5. Maintenant, en utilisant le wrapper, vous pouvez ajouter des "frères" à la barre d'action/zone principale. Ce frère est exactement ce que vous décrivez à votre image.

Voyons un peu de code.

Tout d'abord, créez une méthode pour aider à créer une vue wrapper. le wrapper sera placé entre tout l'écran et le contenu de votre application. étant un ViewGroup vous pourrez plus tard contrôler complètement son contenu.

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

Maintenant, interférer avec la création régulière de Activity , et au lieu d'utiliser setContentView , utilisez la méthode que nous avons créée.

    @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()"
}

C'est à peu près ça.

Remarques

  • J'ai utilisé visionneuse de hiérarchie d'Android pour comprendre quelle est la bonne hiérarchie. (n'a pas deviné ces 0 et 1 index)
  • Si vous utilisez une sorte de tiroir de menu dans votre activité, vous devrez peut-être le configurer un peu différemment car les tiroirs créent déjà ce wrapper pour vous
  • J'ai beaucoup appris en regardant cette grande bibliothèque

EDIT: Reportez-vous à la réponse @ CristopherOyarzúnAltamirano pour plus d'assistance sur les nouvelles versions Android versions

Bonne chance!

22
Sean

J'essayais de réaliser autre chose mais j'avais besoin d'une solution similaire à celle-ci. J'avais besoin de dessiner un calque opaque couvrant tout l'écran, même la barre d'action - un peu comme une boîte de dialogue. Je l'ai fait de cette façon:

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

cela peut être utilisé pour dessiner n'importe quoi n'importe où sur l'écran.

33
Siavash

Il existe un moyen beaucoup plus simple d'y parvenir. ActionBar conserve sa disposition dans la classe ActionBarContainer qui hérite simplement de FrameLayout. Donc, pour afficher quelque chose sur l'ActionBar, vous devez saisir une référence à ActionBarContainer et y ajouter votre propre vue personnalisée. Voici le code

    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);
15
Nouman Hanif

J'ai trouvé cette solution de contournement basée sur la réponse @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);}

J'ai trouvé un moyen beaucoup plus simple de le faire. Je viens d'appliquer Android: translationZ = "10dp" à la vue dont j'ai besoin pour couvrir la barre d'action.

J'ai choisi 10dp mais cela peut être tout ce que vous voulez tant qu'il est supérieur à l'élévation de la barre d'action

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

Ne vous inquiétez pas non plus de l'avertissement suivant de Android studio:

"translationZ ne peut pas être utilisé avec l'API <21".

Il sera ignoré, mais vous ne vous en souciez pas vraiment car la barre d'outils ne doit pas couvrir votre vue avec des API inférieures à 21.

3
Jack'

Essayez d'utiliser ActionBar.setCustomView (). C'est le seul moyen de modifier l'apparence de cette zone de l'écran. Vous ne pouvez pas coller une vue dans la zone "au-dessus" de l'ActionBar, car cette zone est essentiellement contrôlée par le système. D'autre part, vous pouvez fournir votre propre mise en page pour cela.

Si vous expliquez plus en détail ce que vous essayez de faire, les répondants pourraient avoir de meilleures idées de conception.

1
Joe Malin

https://github.com/michaelye/EasyDialogDemo

voir la démo ci-dessus, cela peut vous aider

dialog.setLocation(new location[])//point in screen

vous pouvez définir l'emplacement [] vous-même.

1
MichaelYe

(Référence: http://www.vogella.com/articles/AndroidActionBar/article.html )
Vues personnalisées dans ActionBar
Vous pouvez également ajouter une vue personnalisée à ActionBar. Pour cela, vous utilisez la méthode setCustomView pour la classe ActionView. Vous devez également activer l'affichage des vues personnalisées via la méthode setDisplayOptions() en passant le ActionBar.DISPLAY_SHOW_CUSTOM drapeau.

Par exemple, vous pouvez définir un fichier de mise en page qui contient un élément 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" >

Cette disposition peut être affectée à ActionBar via le code suivant. L'exemple de code allow attache un écouteur à la vue personnalisée.

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

Utilisez le Android:actionLayout dans votre fichier 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>

Créez ensuite votre mise en page 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" />

Pour gérer le clic, procédez comme suit:

@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);}

C'est si :)

0
Shajeel Afzal