Равномерно разнесенные пункты меню на Панели инструментов

Итак, я пытаюсь реализовать android.support.v7.widget.Toolbar в своей работе и сделать его похожим на ранее поддерживаемый split ActionBar.

Здесь XML для моей панели инструментов:

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

Вот стиль для панели инструментов, которую я использую:

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

Стиль кнопок меню панели инструментов, мой первоначальный план состоял в том, чтобы вычислить minWidth на основе размера экрана, а затем установить его для каждой кнопки меню.

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

И, наконец, вот что я вызываю в своей деятельности.

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

Проблема в том, что элементы меню внизу Toolbar выравниваются вправо следующим образом: Right aligned menu items

Однако я хочу, чтобы они были равномерно распределены следующим образом:

Evenly spaced menu items

Ответы

Ответ 1

Вот, что сработало * для меня:

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

Когда я говорю "сработал", я имею в виду, что он сосредоточил все в моем меню, тексте и изображениях. Если вы используете только значки для своего меню, тогда он будет выглядеть великолепно. Я все еще ищу способ сосредоточить их, и текст будет рядом с значками.

Ответ 2

Ребята, это заняло у меня некоторое время, чтобы разобраться, и здесь вы немного поработали, но это работает.

Я использую это на Toolbar для отображения в нижней части экрана, как старый SplitActionBar...

ИСПОЛЬЗУЙТЕ равномерно распределенные элементы меню на панели инструментов

Я бы не рекомендовал использовать более 5 или 6 предметов, он может немного переполняться...

/**
 * 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);
                }
            }
        }
    }
}

Ответ 3

Проверьте это.

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

Замените ImageView тем, что вы хотите.

Ответ 4

Это решение лучше всего подходит для каждого из вышеперечисленных решений, Благодаря inner_class7, Kuffs и MrEngineer13.
Это решение равномерно распределяет пункты меню и отображает текст.

Открытый класс EvenlyDistributedToolbar расширяет 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" />

Ответ 5

Моя рекомендация - следовать рекомендациям . Если вы используете toolbar, оставьте menu, где они предназначены для перехода.

введите описание изображения здесь

Однако, если вы хотите равный интервал, рассмотрите возможность использования Tabs

введите описание изображения здесь

или Нижняя панель навигации

введите описание изображения здесь

Этот ответ рассказывает о том, как настроить нижнюю панель навигации.

Ответ 6

Если вы создаете меню программно, а не раздуваете ресурсы, вы можете сделать это:

Используйте SplitToolbar, как указано в другом ответе. Получить ссылку на панель инструментов с помощью FindViewById, как обычно. Если панель инструментов не существует в макете, меню функционирует как обычная нерасширенная версия.

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

Затем в вашем коде создания меню сделайте следующее.

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