toolbar.setNavigationOnClickListener无法工作

18

toolbar.setNavigationOnClickListener 这个函数不起作用,不知道为什么。

activity_main.xml 布局文件

<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".login.LoginActivity">

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="?attr/colorPrimary"
        app:popupTheme="@style/AppTheme.PopupOverlay">

    </android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main" />

container_main.xml布局

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">
    <FrameLayout
        android:id="@+id/frame_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <!-- Listview to display slider menu -->
    <ListView
        android:id="@+id/list_slidermenu"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@color/list_background"
        android:choiceMode="singleChoice"
        android:divider="@color/list_divider"
        android:dividerHeight="1dp"
        android:listSelector="@drawable/list_selector" />

</android.support.v4.widget.DrawerLayout>

Java活动类

import android.app.Fragment;
import android.app.FragmentManager;
import android.content.res.TypedArray;
import android.os.Bundle;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {

    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    private ActionBarDrawerToggle mDrawerToggle;

    // slide menu items
    private String[] navMenuTitles;


    private TypedArray navMenuIcons;

    private ArrayList<NavDrawerItem> navDrawerItems;
    private NavDrawerListAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // enabling action bar app icon and behaving it as toggle button
        Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
        toolbar.setNavigationIcon(R.drawable.ic_drawer);
        setSupportActionBar(toolbar);
        // load slide menu items
        navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);

        // nav drawer icons from resources
        navMenuIcons = getResources()
                .obtainTypedArray(R.array.nav_drawer_icons);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.list_slidermenu);

        navDrawerItems = new ArrayList<>();

        // adding nav drawer items to array
        // Home
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[0], navMenuIcons.getResourceId(0, -1)));
        // Find People
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[1], navMenuIcons.getResourceId(1, -1)));
        // Photos
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[2], navMenuIcons.getResourceId(2, -1)));
        // Communities, Will add a counter here
        navDrawerItems.add(new NavDrawerItem(navMenuTitles[3], navMenuIcons.getResourceId(3, -1)));


        // Recycle the typed array
        navMenuIcons.recycle();
        // setting the nav drawer list adapter
        adapter = new NavDrawerListAdapter(getApplicationContext(),
                navDrawerItems);
        mDrawerList.setAdapter(adapter);


        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
                toolbar,
                R.string.app_name,
                R.string.app_name
        ){
            public void onDrawerClosed(View view) {
                //getActionBar().setTitle(mTitle);
                // calling onPrepareOptionsMenu() to show action bar icons
                invalidateOptionsMenu();
            }

            public void onDrawerOpened(View drawerView) {
                //getActionBar().setTitle(mDrawerTitle);
                // calling onPrepareOptionsMenu() to hide action bar icons
                invalidateOptionsMenu();
            }

            @Override
            public void onDrawerSlide(View drawerView, float slideOffset) {
                super.onDrawerSlide(drawerView, slideOffset);
            }
        };
        mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Log.d("COMECOU", "COMECOU");
            }
        });
        mDrawerLayout.setDrawerListener(mDrawerToggle);


        if (savedInstanceState == null) {
            // on first time display view for first nav item
            displayView(0);
        }


    }

    /**
     * Displaying fragment view for selected nav drawer list item
     * */
    private void displayView(int position) {
        // update the main content by replacing fragments
        Fragment fragment = null;
        switch (position) {
            case 0:
                fragment = new HomeFragment();
                break;
            case 1:
                fragment = new FindPeopleFragment();
                break;
            case 2:
                fragment = new PhotosFragment();
                break;
            case 3:
                fragment = new CommunityFragment();
                break;
            case 4:
                fragment = new PagesFragment();
                break;
            case 5:
                fragment = new WhatsHotFragment();
                break;

            default:
                break;
        }

        if (fragment != null) {
            FragmentManager fragmentManager = getFragmentManager();
            fragmentManager.beginTransaction()
                    .replace(R.id.frame_container, fragment).commit();

            // update selected item and title, then close the drawer
            mDrawerList.setItemChecked(position, true);
            mDrawerList.setSelection(position);
            setTitle(navMenuTitles[position]);
            mDrawerLayout.closeDrawer(mDrawerList);
        } else {
            // error in creating fragment
            Log.e("MainActivity", "Error in creating fragment");
        }
    }

}

我忘了说,如果我滑动屏幕,可以看到菜单按钮,但是没有登录或触发任何操作。

更新

如果您想知道如何解决这个问题,请查看我的回答。


@jlam55555 不,只是监听器没有被触发。 - PedroAGSantos
7个回答

83

还有一点需要记住的是,

setSupportActionBar(toolbar);

之前调用

toolbar.setNavigationOnClickListener()

是行不通的。


1
@Mohammad Mahtabi 为什么它不能工作?找不到任何线索。 - The incredible Jan

8

我看到你正在使用ActionBarDrawerToggle,因此setNavigationOnClickListener()是错误的。正确的方法是setToolbarNavigationClickListener()。这将使其行为类似于切换按钮。

mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("TOU AQUI", "TOU AQUI");
    }
});

1
我已经更新了我的代码,按照你说的做了,但是什么也没有发生 :( - PedroAGSantos
1
尝试使用 setDrawerIndicatorEnabled(false) - Henry
在那种情况下,你能否编辑你的问题,以便发布正确的布局。 - Henry
@PedroAGSantos,答案在哪里呢? - Marco Zanetti
1
我的回答在@MarcoZanetti下面,抱歉我删掉了它,因为我相信有更好的答案。 - PedroAGSantos
显示剩余2条评论

1
我发现了一个错误,我们无法将工具栏放在抽屉布局之外。
以下是它的外观:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">



    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <!-- Framelayout to display Fragments -->
            <FrameLayout
                android:id="@+id/frame_container"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="#2196F3"
                android:minHeight="?attr/actionBarSize"/>
        </FrameLayout>

        <!-- Listview to display slider menu -->
        <ListView
            android:id="@+id/list_slidermenu"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@color/list_background"
            android:choiceMode="singleChoice"
            android:divider="@color/list_divider"
            android:dividerHeight="1dp"
            android:listSelector="@drawable/list_selector" />

    </android.support.v4.widget.DrawerLayout>

</FrameLayout>

1
你应该在这种情况下使用ActionBarDrawerToggle#setToolbarNavigationClickListener
来自Android文档:
当DrawerToggle与Toolbar一起构建时,它会在导航图标上设置点击监听器。如果您想在禁用DrawerToggle(setDrawerIndicatorEnabled(boolean))时侦听导航图标上的单击事件,则应使用此方法调用您的侦听器,并且当抽屉指示器被禁用时,DrawerToggle将将单击事件转发给该侦听器。

0

根本问题在于ActionBarDrawerToggle。构造函数看起来像这样:

ActionBarDrawerToggle(Activity activity, Toolbar toolbar, DrawerLayout drawerLayout, DrawerArrowDrawable slider, @StringRes int openDrawerContentDescRes, @StringRes int closeDrawerContentDescRes) {
        //...
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mDrawerIndicatorEnabled) {
                    toggle();
                } else if (mToolbarNavigationClickListener != null) {
                    mToolbarNavigationClickListener.onClick(v);
                }
            }
        });
}

我真的不能理解这个逻辑:

  1. toolbar.setNavigationOnClickListener为汉堡图标设置点击监听器。
  2. 当用户点击汉堡时:

    2.1 如果汉堡可见,则打开/隐藏抽屉。

    2.2 如果汉堡不可见,则调用单击监听器。

因此,在大多数情况下,汉堡图标应该是可见的,因此在所有这些情况下,setNavigationOnClickListener都不起作用且无用。

可能它看起来应该像这样:

ActionBarDrawerToggle(Activity activity, Toolbar toolbar, DrawerLayout drawerLayout, DrawerArrowDrawable slider, @StringRes int openDrawerContentDescRes, @StringRes int closeDrawerContentDescRes) {

        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                toggle();
                if (mToolbarNavigationClickListener != null) {
                    mToolbarNavigationClickListener.onClick(v);
                }
            }
        });
}

一个解决方法是重写toolbar.setNavigationOnClickListener并在那里调用toggle。虽然这个方法是包私有的:
package android.support.v7.app

import android.support.v4.widget.DrawerLayout
import android.support.v7.widget.Toolbar
import android.view.View


object SupportUtils {
    fun setHamburgerListener(listener: () -> Unit,
                             drawerToggle: ActionBarDrawerToggle,
                             drawerLayout: DrawerLayout,
                             toolbar: Toolbar) {
        drawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener {
            override fun onDrawerStateChanged(newState: Int) {
                drawerToggle.onDrawerStateChanged(newState)
            }

            override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
                drawerToggle.onDrawerSlide(drawerView, slideOffset)
            }

            override fun onDrawerClosed(drawerView: View) {
                drawerToggle.onDrawerClosed(drawerView)
            }

            override fun onDrawerOpened(drawerView: View) {
                drawerToggle.onDrawerOpened(drawerView)
            }

        })

        toolbar.setNavigationOnClickListener {
            listener()
            drawerToggle.toggle()
        }
    }
}

0
在我的情况下 - ScrollView 处理了所有的触摸事件。我在 Toolbar 后面添加了 android:layout_marginTop="?android:attr/actionBarSize",这样就可以正常工作了。希望能对某些人有所帮助 )

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rootView"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/common_toolbar" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="?android:attr/actionBarSize"
        >

       <RelativeLayout
           android:layout_width="match_parent"
           android:layout_height="wrap_content"
        >
    ... ...

0
    private fun setUpToolbarWithHomeAsUp() {

        setSupportActionBar(toolbar)
        val actionBar = supportActionBar


        actionBar?.let{
            actionBar.setHomeButtonEnabled(true)
            actionBar.setDisplayShowTitleEnabled(false)
        }
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        when (item.itemId) {
            android.R.id.home -> {
                //What ever you want
                return true
            }
        }
        return super.onOptionsItemSelected(item)
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接