更改右侧抽屉的菜单项和汉堡按钮的位置

问题描述:

在我的Toolbar中,我有一个菜单,其中包含一项设置",以及一个DrawerLayout,其中的汉堡包图标右对齐.

In my Toolbar, I have a menu with one item "settings", and a DrawerLayout with a hamburger icon aligned to the right.

现在看起来像这样:

我希望这个汉堡在右边,

I want the hamburger to be on the right, like this:

menu.xml:

<menu xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/settings"
        android:icon="@drawable/ic_settings_black_48dp"
        app:showAsAction="always" />
</menu>

MainActivity:

public class MainActivity extends AppCompatActivity {
    private DrawerLayout mDrawerLayout;
    //EndDrawerToggle is class for setup DrawerLayout with an end-aligned drawer
    private EndDrawerToggle drawerToggle;   

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context=this;
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        Toolbar myToolbar = (Toolbar) findViewById(R.id.my_toolbar);
        myToolbar.setTitle("");
        setSupportActionBar(myToolbar);
        drawerToggle = new EndDrawerToggle(this,
                mDrawerLayout,
                myToolbar,
                R.string.drawer_open,
                R.string.drawer_close);
        mDrawerLayout.addDrawerListener(drawerToggle);    
        //....
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.settings) {
            //do smth
        }
        return super.onOptionsItemSelected(item);
    }

}

EndDrawerToggle类来自此答案.

Toolbar中的菜单将始终固定在末尾,除了直接修改Toolbar之外,没有其他可做的事情不知何故的行为.

The menu in a Toolbar will always be pinned to the end, and there's not much that can be done about that, apart from directly modifying Toolbar's behavior somehow, which would not be trivial.

一个选择是完全放弃菜单,并将您自己的Button添加到Toolbar进行设置.但是,这可能有点笨拙,因为EndDrawerToggleButton是动态创建和添加的,因此最后要堆叠的所有其他View都必须创建或添加类似地,或者在设置了切换开关之后变戏法.

One option would be to forgo the menu altogether, and add your own Button to the Toolbar for the settings. This might be a little unwieldy, though, since EndDrawerToggle's Button is created and added dynamically, and so any other Views you'd want stacked before it on the end would have to be either created and added similarly, or juggled around after the toggle has been set.

但是,通过一些修改,我们可以使EndDrawerToggle直接与菜单集成,将其切换可绘制设置为我们最后添加的始终显示的菜单项上的图标.实际上,这实际上是一个更简单的类,因为我们不需要为drawable提供ImageButton,就像我们将切换直接添加到Toolbar时所做的那样.

However, with some modifications, we can get EndDrawerToggle to integrate directly with the menu, setting its toggle drawable as the icon on an always-shown menu item we add at the end. This actually ends up being a simpler class, since we don't need to provide an ImageButton for the drawable, as we did when adding the toggle directly to the Toolbar.

import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.graphics.drawable.DrawerArrowDrawable;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;


public class EndMenuDrawerToggle implements DrawerLayout.DrawerListener {

    private final DrawerLayout drawerLayout;
    private final Toolbar toolbar;
    private final DrawerArrowDrawable arrowDrawable;
    private final int openDrawerContentDesc, closeDrawerContentDesc;
    private MenuItem toggleItem;

    public EndMenuDrawerToggle(DrawerLayout drawerLayout, Toolbar toolbar,
                               int openDrawerContentDesc, int closeDrawerContentDesc) {
        this.drawerLayout = drawerLayout;
        this.toolbar = toolbar;

        this.openDrawerContentDesc = openDrawerContentDesc;
        this.closeDrawerContentDesc = closeDrawerContentDesc;

        arrowDrawable = new DrawerArrowDrawable(toolbar.getContext());
        arrowDrawable.setDirection(DrawerArrowDrawable.ARROW_DIRECTION_END);
    }

    public void setToggleOnMenu(Menu menu) {
        toggleItem = menu.add(openDrawerContentDesc);
        toggleItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
        toggleItem.setIcon(arrowDrawable);
        toggleItem.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
                @Override
                public boolean onMenuItemClick(MenuItem item) {
                    toggle();
                    return true;
                }
            }
        );

        setPosition(drawerLayout.isDrawerOpen(GravityCompat.END) ? 1f : 0f);
    }

    private void toggle() {
        final int drawerLockMode = drawerLayout.getDrawerLockMode(GravityCompat.END);
        if (drawerLayout.isDrawerVisible(GravityCompat.END)
            && (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_OPEN)) {
            drawerLayout.closeDrawer(GravityCompat.END);
        }
        else if (drawerLockMode != DrawerLayout.LOCK_MODE_LOCKED_CLOSED) {
            drawerLayout.openDrawer(GravityCompat.END);
        }
    }

    private void setPosition(float position) {
        if (position == 1f) {
            arrowDrawable.setVerticalMirror(true);
            toggleItem.setTitle(closeDrawerContentDesc);
        }
        else if (position == 0f) {
            arrowDrawable.setVerticalMirror(false);
            toggleItem.setTitle(openDrawerContentDesc);
        }
        arrowDrawable.setProgress(position);
    }

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset) {
        setPosition(Math.min(1f, Math.max(0f, slideOffset)));
    }

    @Override
    public void onDrawerOpened(View drawerView) {
        setPosition(1f);
    }

    @Override
    public void onDrawerClosed(View drawerView) {
        setPosition(0f);
    }

    @Override
    public void onDrawerStateChanged(int newState) {}
}

初始化基本相同;照常实例化,并在DrawerLayout上添加为DrawerListener.

Initialization is basically the same; instantiate per usual, and add as a DrawerListener on the DrawerLayout.

drawerToggle = new EndMenuDrawerToggle(mDrawerLayout,
                                       myToolbar,
                                       R.string.open_drawer_end,
                                       R.string.close_drawer_end);
mDrawerLayout.addDrawerListener(drawerToggle);
...

区别在于onCreateOptionsMenu()方法,在这里我们将菜单中的菜单传递给切换器的setToggleOnMenu()方法.

The difference comes in the onCreateOptionsMenu() method, where we pass the menu we inflate there to the toggle's setToggleOnMenu() method.

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);

    drawerToggle.setToggleOnMenu(menu);

    return true;
}

我们不使用此类调用syncState(),因为可绘制对象将在上述方法中正确同步.

We do not call syncState() with this class, as the drawable will be correctly synced in the method above.

请注意,此示例只是将MenuItem添加到现有的Menu,并将该项目设置为SHOW_AS_ACTION_ALWAYS.对于给定的菜单,这将可以按需工作,但是,如果将其与任何具有溢出项的菜单一起使用,则三点溢出图标将显示在切换开关之后.

Do note that this example simply adds a MenuItem to the existing Menu, and sets that item as SHOW_AS_ACTION_ALWAYS. This will work as desired with the given menu, but if this is used with any menu that will have overflow items, the three-dot overflow icon is going to appear past the toggle.

在这种情况下,如果您仍然想在最后进行切换,则必须手动"处理溢出;例如,通过为三点图标添加自定义项,然后在弹出窗口中打开单独的菜单.

In that case, if you still want the toggle at the very end, the overflow will have to be handled "manually"; e.g., by adding a custom item for the three-dot icon, and opening a separate menu in a popup.