Change positions of menu items and hamburger button for a right-side drawer

馋奶兔 提交于 2019-12-23 05:39:09

问题


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

Now it looks like this:

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

}

The EndDrawerToggle class is from this answer.


回答1:


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.

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.

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

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

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

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


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.



来源:https://stackoverflow.com/questions/47114868/change-positions-of-menu-items-and-hamburger-button-for-a-right-side-drawer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!