web-dev-qa-db-fra.com

Eléments de menu uniformément espacés dans la barre d'outils

J'ai donc essayé d'implémenter Android.support.v7.widget.Toolbar dans mon activité et de lui donner un aspect similaire à l'ActionBar divisé précédemment pris en charge.

Voici le XML pour ma barre d'outils:

<Android.support.v7.widget.Toolbar
    Android:id="@+id/toolbar_btm"
    Android:layout_height="wrap_content"
    Android:layout_width="match_parent"
    Android:minHeight="?attr/actionBarSize"
    Android:background="@color/toolbar_bkgnd"
    Android:layout_alignParentBottom="true"
    app:theme="@style/ToolBarTheme" />

Voici le style de la barre d'outils que j'utilise:

<style name="ToolBarTheme" parent="Theme.AppCompat">
    <item name="actionButtonStyle">@style/ActionButtonStyle</item>
    <item name="Android:actionButtonStyle">@style/ActionButtonStyle</item>
    <item name="Android:textColor">@Android:color/white</item>
</style>

Le style des boutons de menu de la barre d’outils, mon plan initial était de calculer la valeur minWidth en fonction de la taille de l’écran, puis de la définir pour chaque bouton de menu.

<style name="ActionButtonStyle" parent="@Android:style/Widget.Holo.Light.ActionButton">
    <item name="Android:minWidth">56dip</item>
    <item name="Android:paddingLeft">0dip</item>
    <item name="Android:paddingRight">0dip</item>
</style>

Et enfin, voici ce que j'appelle dans mon activité. 

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_btm);
toolbarBtm.inflateMenu(R.id.menu);

Le problème est que les éléments de menu dans la Toolbar inférieure sont alignés à droite, comme suit: Right aligned menu items

Cependant, je veux qu'ils soient régulièrement espacés comme ceci: 

Evenly spaced menu items

21
MrEngineer13

Voici ce qui a fonctionné * pour moi:

EnhancedMenuInflater.Java

import Android.support.v4.internal.view.SupportMenuItem;
import Android.support.v7.internal.view.menu.MenuItemImpl;
import Android.view.Menu;
import Android.view.MenuInflater;
import Android.view.MenuItem;

import here.is.your.R;

public class EnhancedMenuInflater {

    public static void inflate(MenuInflater inflater, Menu menu, boolean forceVisible) {
        inflater.inflate(R.menu.menu, menu);

        if (!forceVisible) {
            return;
        }

        int size = menu.size();
        for (int i = 0; i < size; i++) {
            MenuItem item = menu.getItem(i);
            // check if app:showAsAction = "ifRoom"
            if (((MenuItemImpl) item).requestsActionButton()) {
                item.setShowAsAction(SupportMenuItem.SHOW_AS_ACTION_ALWAYS);
            }
        }
    }
}

MainActivity.Java

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    if (toolbar == null) {
        EnhancedMenuInflater.inflate(getMenuInflater(), menu, false);
    }
    return super.onCreateOptionsMenu(menu);
}

// somewhere after views have been set.
if (toolbar != null) {
    EnhancedMenuInflater.inflate(getMenuInflater(), toolbar.getMenu(), true);
    toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
        @Override
        public boolean onMenuItemClick(MenuItem item) {
            return onOptionsItemSelected(item);
        }
    });
}

SplitToolbar.Java

import Android.content.Context;
import Android.support.v7.widget.ActionMenuView;
import Android.support.v7.widget.Toolbar;
import Android.util.AttributeSet;
import Android.view.View;
import Android.view.ViewGroup;

public class SplitToolbar extends Toolbar {
    public SplitToolbar(Context context) {
        super(context);
    }

    public SplitToolbar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SplitToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void addView(View child, ViewGroup.LayoutParams params) {
        if (child instanceof ActionMenuView) {
            params.width = LayoutParams.MATCH_PARENT;
        }
        super.addView(child, params);
    }
}

Layout.xml

<here.is.my.SplitToolbar
    Android:id="@+id/toolbar"
    Android:layout_width="match_parent"
    Android:layout_height="wrap_content"
    Android:layout_alignParentBottom="true"/>

Quand je dis travaillé, je veux dire que tout est centré dans le menu, le texte et les images. Si vous utilisez uniquement des icônes pour votre menu, alors il aura fière allure. Je cherche toujours un moyen de les centrer et d'avoir le texte à côté des icônes.

10
MrEngineer13

METTRE &AGRAVE; JOUR

Google a maintenant des fonctionnalités très similaires qui gonflent les manières habituelles de gonfler les menus en utilisant un nouvel appel de widget BottomNavigationView

- Réponse originale - 

Les gars, cela m'a pris du temps à comprendre et voilà, c'est une opération un peu lourde mais ça marche.

J'utilise ceci sur une Toolbar à afficher en bas de l'écran comme l'ancien SplitActionBar...

VOICI les éléments de menu répartis uniformément sur votre barre d'outils

Je ne recommanderais pas d'utiliser plus de 5 ou 6 éléments, cela peut devenir un peu encombré ...

/**
 * This method will take however many items you have in your  
 * menu/menu_main.xml and distribute them across your devices screen
 * evenly using a Toolbar. Enjoy!!
 */
public void setupEvenlyDistributedToolbar(){
    // Use Display metrics to get Screen Dimensions
    Display display = getWindowManager().getDefaultDisplay();
    DisplayMetrics metrics = new DisplayMetrics();
    display.getMetrics(metrics);

    // Toolbar
    mToolbar = (Toolbar) findViewById(R.id.navigationToolbar);
    // Inflate your menu
    mToolbar.inflateMenu(R.menu.menu_bottom);

    // Add 10 spacing on either side of the toolbar
    mToolbar.setContentInsetsAbsolute(10, 10);

    // Get the ChildCount of your Toolbar, this should only be 1
    int childCount = mToolbar.getChildCount();
    // Get the Screen Width in pixels
    int screenWidth = metrics.widthPixels;

    // Create the Toolbar Params based on the screenWidth
    Toolbar.LayoutParams toolbarParams = new Toolbar.LayoutParams(screenWidth, LayoutParams.WRAP_CONTENT);

    // Loop through the child Items
    for(int i = 0; i < childCount; i++){
        // Get the item at the current index
        View childView = mToolbar.getChildAt(i);
        // If its a ViewGroup
        if(childView instanceof ViewGroup){
            // Set its layout params
            childView.setLayoutParams(toolbarParams);
            // Get the child count of this view group, and compute the item widths based on this count & screen size
            int innerChildCount = ((ViewGroup) childView).getChildCount();
            int itemWidth  = (screenWidth / innerChildCount);               
            // Create layout params for the ActionMenuView
            ActionMenuView.LayoutParams params = new ActionMenuView.LayoutParams(itemWidth, LayoutParams.WRAP_CONTENT);
            // Loop through the children
            for(int j = 0; j < innerChildCount; j++){
                View grandChild = ((ViewGroup) childView).getChildAt(j);
                if(grandChild instanceof ActionMenuItemView){
                    // set the layout parameters on each View
                    grandChild.setLayoutParams(params);
                }
            }
        }
    }
}
10
kandroidj

Regarde ça.

<Android.support.v7.widget.Toolbar
        xmlns:Android="http://schemas.Android.com/apk/res/Android"
        xmlns:tools="http://schemas.Android.com/tools"
        xmlns:abc="http://schemas.Android.com/apk/res-auto"
        Android:id="@+id/toolbar"
        Android:layout_height="?attr/actionBarSize"
        Android:layout_width="match_parent">

    <LinearLayout
        Android:layout_width="match_parent"
        Android:layout_height="match_parent">

        <ImageView
            Android:layout_width="0dp"
            Android:layout_height="match_parent"
            Android:layout_weight="1"
            Android:id="@+id/action1"
            Android:background="@color/red_700"/>

        <ImageView
            Android:layout_width="0dp"
            Android:layout_height="match_parent"
            Android:layout_weight="1"
            Android:id="@+id/action2"
            Android:background="@color/red_200"/>

        <ImageView
            Android:layout_width="0dp"
            Android:layout_height="match_parent"
            Android:layout_weight="1"
            Android:id="@+id/action3"
            Android:background="@color/red_100"/>

    </LinearLayout>

</Android.support.v7.widget.Toolbar>

Remplacez ImageView par ce que vous voulez.

3
natario

Cette solution tire le meilleur parti de chacune des solutions ci-dessus, Merci à inner_class7, Kuffs & MrEngineer13.
Cette solution distribue uniformément les éléments de menu et affiche le texte.

public class EvenlyDistributedToolbar étend Android.support.v7.widget.Toolbar {

    private View actionMenuView;
    public EvenlyDistributedToolbar(Context context) {
        super(context);
        setContentInsetsAbsolute(0, 0);
    }

    public EvenlyDistributedToolbar(Context context, AttributeSet attrs) {
        super(context, attrs);
        setContentInsetsAbsolute(0, 0);
    }

    public EvenlyDistributedToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setContentInsetsAbsolute(0, 0);
    }

    @Override
    public void addView(View child, ViewGroup.LayoutParams params) {
        if (child instanceof ActionMenuView) {
            actionMenuView  = child ;
            params.width = LayoutParams.MATCH_PARENT;

            ((ViewGroup)actionMenuView).setOnHierarchyChangeListener(new OnHierarchyChangeListener() {

                @Override 
                public void onChildViewRemoved(View parent, View child) {

                } 

                @Override 
                public void onChildViewAdded(View parent, View child) {
                    if (child instanceof ActionMenuItemView) {
                        //Show the menu item text as well as the the icon
                        ActionMenuItemView actionMenuItemView = (ActionMenuItemView) child;
                        // set the layout parameters on each View
                        actionMenuItemView.setExpandedFormat(true);
                        Drawable[] arr = actionMenuItemView.getCompoundDrawables();

                        if (arr != null && arr.length == 4 && arr[0] != null) {
                            actionMenuItemView.setGravity(Gravity.LEFT | Gravity.CENTER_VERTICAL);
                        }
                        else if (arr != null && arr.length == 4 && arr[2] != null) {
                            actionMenuItemView.setGravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL);
                        }
                        actionMenuItemView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
                        actionMenuItemView.setOnLongClickListener(null);

                    }
                } 
            }); 
        }
        super.addView(child, params);
    }


    /**
     * Show All items, call after the menu inflated
     */
    public void showAll() {
        Menu menu = getMenu();

        int size = menu.size();
        for (int i = 0; i < size; i++) {
            MenuItem item = menu.getItem(i);
            // check if app:showAsAction = "ifRoom"
            if (((MenuItemImpl) item).requestsActionButton()) {
                item.setShowAsAction(SupportMenuItem.SHOW_AS_ACTION_ALWAYS);
            }
        }
    }


}

        <com.util.EvenlyDistributedToolbar
                    Android:layout_width="match_parent"
                    Android:layout_height="wrap_content" />
1
avi

Voici une solution que j’ai posée pour une autre question similaire, car dans ma barre d’outils inférieure, je voulais des boutons équidistants: Android ajoute deux barres d’outils dans la même activité

1

Ma recommandation est de suivre les directives design . Si vous utilisez une barre d'outils , laissez les éléments menu là où ils sont conçus.

enter image description here

Cependant, si vous voulez un espacement égal, envisagez d'utiliser Tabs

enter image description here

ou une barre de navigation inférieure

enter image description here

Cette réponse indique comment configurer une barre de navigation inférieure.

0
Suragch

La solution proposée par public void setupEvenlyDistributedToolbar(){} par kandroidj fonctionne parfaitement. Cependant, pour rendre la solution un peu plus complète, vous avez besoin d'une OnclickListener personnalisée:

ci-joint est ma mise en œuvre 

private void setupOnClickListener4Toolbar(Toolbar toolbar) {
    Menu bottomMenu = toolbar.getMenu();
    for (int i = 0; i < bottomMenu.size(); i++) {
        bottomMenu.getItem(i).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem item) {
                return onOptionsItemSelected(item);
            }
        });
    }
}
0
Pedro Campos

Si vous créez votre menu par programme plutôt que de le gonfler à partir de ressources, vous pouvez procéder comme suit:

Utilisez la SplitToolbar comme mentionné dans une autre réponse. Obtenez une référence à la barre d'outils en utilisant FindViewById comme d'habitude. Si la barre d'outils n'existe pas dans la présentation, le menu fonctionne comme une version normale non divisée.

import Android.content.Context;
import Android.support.v7.widget.ActionMenuView;
import Android.support.v7.widget.Toolbar;
import Android.util.AttributeSet;
import Android.view.View;
import Android.view.ViewGroup;

public class SplitToolbar extends Toolbar {
    public SplitToolbar(Context context) {
        super(context);
    }

    public SplitToolbar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public SplitToolbar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void addView(View child, ViewGroup.LayoutParams params) {
        if (child instanceof ActionMenuView) {
            params.width = LayoutParams.MATCH_PARENT;
        }
        super.addView(child, params);
    }
}

Ensuite, dans votre code de création de menu, procédez comme suit.

@Override
public boolean onPrepareOptionsMenu(Menu menu) {

    if (toolbar != null) {
       toolbar.setContentInsetsAbsolute(0,0);
        menu = toolbar.getMenu();
        toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() {
            @Override
            public boolean onMenuItemClick(MenuItem menuItem) {
                // Call back to the original menu code to handle menu clicks
                return onOptionsItemSelected(menuItem);
            }
        });
    }

    // Now build your menu as normal
    menu.clear();

    MenuItem b = menu.add(0, WHATEVER, 0, R.string.WHATEVER);
             b.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
             b.setIcon(R.drawable.ic_menu_encrypt);
    // End of normal menu code

    // Now set the button options.
    if (toolbar != null) {
        int size = menu.size();
        for (int i = 0; i < size; i++) {
            MenuItem item = menu.getItem(i);
            // check if app:showAsAction = "ifRoom"
            if (((MenuItemImpl) item).requestsActionButton()) {
                item.setShowAsAction(SupportMenuItem.SHOW_AS_ACTION_ALWAYS);
            }
        }
    }
    Return true; 
}
0
Kuffs