Не удается отловить событие нажатия кнопки "Домой" на панели инструментов

Я реализовал новейшую библиотеку appcompat и использовал Toolbar в качестве панели действий. Но проблема в том, что я не могу поймать событие нажатия кнопки «Домой» / значка гамбургера. Я пробовал и смотрел все, но, похоже, не нашел похожей проблемы.

Это мой Activity класс:

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

    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    // Set up the drawer.
    navDrawerFragment = 
        (NavigationDrawerFragment) getSupportFragmentManager()
        .findFragmentById(R.id.navigation_drawer);
    navDrawerFragment.setUp(
        R.id.navigation_drawer, 
        (DrawerLayout) findViewById(R.id.drawer_layout), 
        toolbar);
}

А это мой класс NavigationDrawerFragment:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (savedInstanceState != null) {
        currentSelectedPosition = savedInstanceState.getInt(
            STATE_SELECTED_POSITION);
        fromSavedInstanceState = true;
    }

    // Select either the default item (0) or the last selected item.
    selectItem(currentSelectedPosition);
}

@Override
public void onActivityCreated (Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // Indicate that this fragment would like 
    // to influence the set of actions in the action bar.
    setHasOptionsMenu(true);
}

public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        drawerListView = (ListView) inflater.inflate(
            R.layout.fragment_navigation_drawer, container, false);
        drawerListView.setOnItemClickListener(
            new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, 
                View view, int position, long id) {
                selectItem(position);
            }
        });
        //mDrawerListView.setAdapter();
        //mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
        return drawerListView;
}

public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
    fragmentContainerView = getActivity().findViewById(fragmentId);
    this.drawerLayout = drawerLayout;

    // set a custom shadow that overlays the main 
    // content when the drawer opens
    drawerLayout.setDrawerShadow(
        R.drawable.drawer_shadow, GravityCompat.START);
    // set up the drawer's list view 
    // with items and click listener

    ActionBar actionBar = getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);
    actionBar.setHomeButtonEnabled(true);

    // ActionBarDrawerToggle ties together the the proper interactions
    // between the navigation drawer and the action bar app icon.
    drawerToggle = new ActionBarDrawerToggle(
        getActivity(), 
        drawerLayout, 
        toolbar, 
        R.string.navigation_drawer_open, 
        R.string.navigation_drawer_close) {
        public void onDrawerClosed(View view) {
            super.onDrawerClosed(view);
        }

        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);
        }
    };

    // If the user hasn't 'learned' about the drawer, 
    // open it to introduce them to the drawer,
    // per the navigation drawer design guidelines.
    if (!userLearnedDrawer && !fromSavedInstanceState) {
        drawerLayout.openDrawer(fragmentContainerView);
    }

    // Defer code dependent on restoration of previous instance state.
    drawerLayout.post(new Runnable() {
        @Override
        public void run() {
            drawerToggle.syncState();
        }
    });

    drawerLayout.setDrawerListener(drawerToggle);
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(STATE_SELECTED_POSITION, currentSelectedPosition);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    // Forward the new configuration the drawer toggle component.
    drawerToggle.onConfigurationChanged(newConfig);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Log.d("cek", "item selected");
    if (drawerToggle.onOptionsItemSelected(item)) {
        Log.d("cek", "home selected");
        return true;
    }

    return super.onOptionsItemSelected(item);
}

когда я щелкаю пункт меню, вызывается журнал «выбранный элемент». Но когда я нажимаю кнопку «Домой», открывается панель навигации, но журнал «Дом выбран» никогда не вызывается. Я также установил метод onOptionsItemSelected внутри своего Activity, но он по-прежнему не вызывается.


person Dark Leonhart    schedule 27.10.2014    source источник


Ответы (11)


Если вы хотите знать, когда нажата кнопка «Домой» - это AppCompatActivity, попробуйте это следующим образом:

Сначала сообщите Android, что хотите использовать свой Toolbar в качестве ActionBar:

setSupportActionBar(toolbar);

Затем установите Home для отображения через setDisplayShowHomeEnabled следующим образом:

getSupportActionBar().setDisplayShowHomeEnabled(true);

Наконец, как обычно, прислушайтесь к событиям щелчка на android.R.id.home:

@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
    if (menuItem.getItemId() == android.R.id.home) {
        Timber.d("Home pressed");
    }
    return super.onOptionsItemSelected(menuItem);
}

Если вы хотите знать, когда нажимается кнопка навигации на Toolbar в классе, отличном от AppCompatActivity, вы можете использовать эти методы для установки значка навигации и прослушивания событий щелчка на нем. Значок навигации появится с левой стороны вашего Toolbar там, где раньше была кнопка «домой».

toolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_nav_back));
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d("cek", "home selected");
    }
});

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

person MrEngineer13    schedule 29.10.2014
comment
Раньше пробовал первую часть, но не работает. Пробовал вторую часть, все работает. Но значок не изменится, если я зарегистрирую панель инструментов в навигационном ящике. Еще один вопрос, есть ли для этого замена setDrawerIndicatorEnabled? Я пробовал с этим новым навигационным ящиком и получаю ошибку. Спасибо - person Dark Leonhart; 30.10.2014
comment
Второе решение работает. Но как мы можем обнаружить нажатие кнопки `` Домой '' и кнопки ящика во втором решении. Когда я щелкаю значок ящика, он не открывает ящик. - person Dory; 13.11.2014
comment
Когда вы устанавливаете NavigationOnClickListener для панели инструментов, вы теряете собственное поведение ящика :( - person IlyaEremin; 18.01.2015
comment
Итак, теперь нам нужен отдельный прослушиватель кликов, когда раньше во фрагментах мы могли проверять android.R.id.home в onOptionsItemSelected ()? Это действительно очень раздражает - person Daniel Wilson; 01.02.2015
comment
re: Панель инструментов, если вы установили новый NavigationOnClickListener (используя setNavigationOnClickListener), вы можете восстановить NavDrawer позже, когда это необходимо, снова вызвав setDrawerListener с помощью ActionBarDrawerToggle. - person straya; 16.03.2015
comment
@straya Это спасло меня после многочасовых ударов головой о стену. Повторная установка слушателя была недостающей частью. Спасибо! - person Osborne Cox; 05.06.2015
comment
ActionBarActivity не устарел? - person gerfmarquez; 07.08.2015
comment
@gerfmarquez Полагаю, этот пост был написан раньше. Вместо этого вы должны использовать AppCompatActivity. - person crubio; 09.09.2015
comment
@ MrEngineer13 Вы знаете id из mNavButtonView? :) - person theapache64; 08.02.2016
comment
Как вернуть значок домой к исходной стрелке назад? - person Michel Feinstein; 28.10.2018

    mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
    mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // event when click home button
        }
    });

в моем случае этот код отлично работает

person vuhung3990    schedule 19.07.2015
comment
Вы действительно молодцы, это сработало, я никогда не думал, что смогу обрабатывать кнопку возврата на панели инструментов с помощью DrawerToggle .. - person Sai; 20.01.2016
comment
Чтобы ActionBarDrawerToggle.setToolbarNavigationClickListener работал, нужно сначала вызвать это: mActionBarDrawerToggle.setHomeAsUpIndicator (R.drawable.menu_icon); mActionBarDrawerToggle.setDrawerIndicatorEnabled (ложь); и сам управлять событиями кликов. (открыть / закрыть ящик по щелчку) - person luky; 19.12.2016

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

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });
person Marcos    schedule 03.05.2016
comment
Есть ли у нас в Котлине метод переопределения щелчка? - person Akhila Madari; 14.05.2019
comment
@AkhilaMadari попробуйте что-нибудь подобное в Kotlin: val toolbar = findViewById (R.id.toolbar) as Toolbar setSupportActionBar (toolbar) toolbar.setNavigationOnClickListener {/ * сделайте то, что хотите * / finish ()} - person Marcos; 16.05.2019

Я думаю, что правильное решение с библиотекой поддержки 21 следующее

// action_bar is def resource of appcompat; 
// if you have not provided your own toolbar I mean  
Toolbar toolbar = (Toolbar) findViewById(R.id.action_bar);
if (toolbar != null) {
    // change home icon if you wish
    toolbar.setLogo(this.getResValues().homeIconDrawable());
    toolbar.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //catch here title and home icon click                          
        }                       
    });                 
}
person Čikić Nenad    schedule 21.02.2015
comment
в this.getResValues().homeIconDrawable(), кто такой this? - person LuisComS; 01.10.2015
comment
Это занятие. Getresvalues ​​- это мой метод, поэтому здесь он не актуален. Setlogo принимает выдаваемый идентификатор ресурса. - person Čikić Nenad; 01.10.2015
comment
это будет обрабатывать щелчок пользователя в любом месте на всей панели инструментов, я не думаю, что это то, о чем он спрашивал - person Mina Fawzy; 22.11.2015

Я обработал кнопку "Назад" и "Домой" в навигационном ящике, например

public class HomeActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {
    private ActionBarDrawerToggle drawerToggle;
    private DrawerLayout drawerLayout;
    NavigationView navigationView;
    private Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_home);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        resetActionBar();

        navigationView = (NavigationView) findViewById(R.id.navigation_view);
        navigationView.setNavigationItemSelectedListener(this);

        //showing first fragment on Start
        getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN).replace(R.id.content_fragment, new FirstFragment()).commit();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //listener for home
        if(id==android.R.id.home)
        {  
            if (getSupportFragmentManager().getBackStackEntryCount() > 0)
                onBackPressed();
            else
                drawerLayout.openDrawer(navigationView);
            return  true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
       if (drawerLayout.isDrawerOpen(GravityCompat.START)) 
            drawerLayout.closeDrawer(GravityCompat.START);
       else 
            super.onBackPressed();
    }

    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Begin the transaction

        Fragment fragment = null;
        // Handle navigation view item clicks here.
        int id = item.getItemId();
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (id == R.id.nav_companies_list) {
            fragment = new FirstFragment();
            // Handle the action
        } 


        // Begin the transaction
        if(fragment!=null){

            if(item.isChecked()){
                if(getSupportFragmentManager().getBackStackEntryCount()==0){
                    drawer.closeDrawers();
            }else{
                    removeAllFragments();
                    getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
                    drawer.closeDrawer(GravityCompat.START);
                }

            }else{
                removeAllFragments();
                getSupportFragmentManager().beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE).replace(R.id.WikiCompany, fragment).commit();
                drawer.closeDrawer(GravityCompat.START);
            }
        }

        return true;
    }

    public void removeAllFragments(){
        getSupportFragmentManager().popBackStackImmediate(null,
                FragmentManager.POP_BACK_STACK_INCLUSIVE);
    }

    public void replaceFragment(final Fragment fragment) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        fragmentManager.beginTransaction().setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
                .replace(R.id.WikiCompany, fragment).addToBackStack("")
                .commit();
    }


    public void updateDrawerIcon() {
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    Log.i("", "BackStackCount: " + getSupportFragmentManager().getBackStackEntryCount());
                    if (getSupportFragmentManager().getBackStackEntryCount() > 0)
                        drawerToggle.setDrawerIndicatorEnabled(false);
                    else
                        drawerToggle.setDrawerIndicatorEnabled(true);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }, 50);
    }

    public void resetActionBar()
    {
        //display home
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);
    }

    public void setActionBarTitle(String title) {
        getSupportActionBar().setTitle(title);
    }
}

и в каждом onViewCreated я звоню

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ((HomeActivity)getActivity()).updateDrawerIcon();
    ((HomeActivity) getActivity()).setActionBarTitle("List");
}
person AndroidGeek    schedule 30.09.2016

Вот как я реализовал его до-материальный дизайн, и, похоже, он все еще работает, я перешел на новый Toolbar. В моем случае я хочу зарегистрировать пользователя, если он попытается открыть боковую навигацию при выходе из системы (и поймать событие, чтобы боковая навигация не открывалась). В вашем случае вы не смогли return true;.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (!isLoggedIn() && item.getItemId() == android.R.id.home) {
        login();
        return true;
    }
    return mDrawerToggle.onOptionsItemSelected(item) || super.onOptionsItemSelected(item);
}
person darnmason    schedule 28.10.2014
comment
Ах, я забыл, я обнаружил, что не могу поймать нажатие кнопки «Домой» во фрагменте, я задал вопрос и предложил обходной путь, который должен был вручную передать событие всем вашим фрагментам. stackoverflow.com/q/21938419/1007151 - person darnmason; 30.10.2014

Я немного изменил DrawerLayout, чтобы получать события и иметь возможность потреблять и события, например, если вы хотите использовать actionToggle как назад, если вы находитесь в подробном представлении:

public class ListenableDrawerLayout extends DrawerLayout {

    private OnToggleButtonClickedListener mOnToggleButtonClickedListener;
    private boolean mManualCall;

    public ListenableDrawerLayout(Context context) {
        super(context);
    }

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

    public ListenableDrawerLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /**
     * Sets the listener for the toggle button
     *
     * @param mOnToggleButtonClickedListener
     */
    public void setOnToggleButtonClickedListener(OnToggleButtonClickedListener mOnToggleButtonClickedListener) {
        this.mOnToggleButtonClickedListener = mOnToggleButtonClickedListener;
    }

    /**
     * Opens the navigation drawer manually from code<br>
     * <b>NOTE: </b>Use this function instead of the normal openDrawer method
     *
     * @param drawerView
     */
    public void openDrawerManual(View drawerView) {
        mManualCall = true;
        openDrawer(drawerView);
    }

    /**
     * Closes the navigation drawer manually from code<br>
     * <b>NOTE: </b>Use this function instead of the normal closeDrawer method
     *
     * @param drawerView
     */
    public void closeDrawerManual(View drawerView) {
        mManualCall = true;
        closeDrawer(drawerView);
    }


    @Override
    public void openDrawer(View drawerView) {

        // Check for listener and for not manual open
        if (!mManualCall && mOnToggleButtonClickedListener != null) {

            // Notify the listener and behave on its reaction
            if (mOnToggleButtonClickedListener.toggleOpenDrawer()) {
                return;
            }

        }
        // Manual call done
        mManualCall = false;

        // Let the drawer layout to its stuff
        super.openDrawer(drawerView);
    }

    @Override
    public void closeDrawer(View drawerView) {

        // Check for listener and for not manual close
        if (!mManualCall && mOnToggleButtonClickedListener != null) {

            // Notify the listener and behave on its reaction
            if (mOnToggleButtonClickedListener.toggleCloseDrawer()) {
                return;
            }

        }
        // Manual call done
        mManualCall = false;

        // Let the drawer layout to its stuff
        super.closeDrawer(drawerView);
    }

    /**
     * Interface for toggle button callbacks
     */
    public static interface OnToggleButtonClickedListener {

        /**
         * The ActionBarDrawerToggle has been pressed in order to open the drawer
         *
         * @return true if we want to consume the event, false if we want the normal behaviour
         */
        public boolean toggleOpenDrawer();

        /**
         * The ActionBarDrawerToggle has been pressed in order to close the drawer
         *
         * @return true if we want to consume the event, false if we want the normal behaviour
         */
        public boolean toggleCloseDrawer();
    }

}
person Adrian    schedule 19.03.2015

Самый простой подход, который мы могли бы сделать, - это изменить значок дома на известный значок и сравнить чертежи (потому что значок android.R.id.home может отличаться в разных версиях api

поэтому установите панель инструментов как панель действий SetSupportActionBar (_toolbar);

_toolbar.NavigationIcon = your_known_drawable_here;

   for (int i = 0; i < _toolbar.ChildCount; i++)
            {
                View v = _toolbar.GetChildAt(i);
                if (v is ImageButton)
                {
                    ImageButton imageButton = v as ImageButton;

                    if (imageButton.Drawable.GetConstantState().Equals(_bookMarkIcon.GetConstantState()))
                    {
                       //here v is the widget that contains the home  icon you can add your click events here 
                    }
                }
            }
person Sajidh Zahir    schedule 21.10.2016

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

toolbar.setNavigationIcon(R.drawable.ic_my_home);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);

А затем прослушайте события щелчка с идентификатором onOptionsItemSelected по умолчанию и android.R.id.home.

person Diego Laballos    schedule 19.12.2016
comment
Это не сработает. android.R.id.home никогда не стрелять - person Trancer; 01.02.2017

Для всех, кто ищет реализацию Xamarin (поскольку события в C # выполняются по-другому), я просто создал этот класс NavClickHandler следующим образом:

public class NavClickHandler : Java.Lang.Object, View.IOnClickListener
{
    private Activity mActivity;
    public NavClickHandler(Activity activity)
    {
        this.mActivity = activity;
    }
    public void OnClick(View v)
    {
        DrawerLayout drawer = (DrawerLayout)mActivity.FindViewById(Resource.Id.drawer_layout);
        if (drawer.IsDrawerOpen(GravityCompat.Start))
        {
            drawer.CloseDrawer(GravityCompat.Start);
        }
        else
        {
            drawer.OpenDrawer(GravityCompat.Start);
        }
    }
}

Затем назначил настраиваемую кнопку меню гамбургера следующим образом:

        SupportActionBar.SetDisplayHomeAsUpEnabled(true);
        SupportActionBar.SetDefaultDisplayHomeAsUpEnabled(false);
        this.drawerToggle.DrawerIndicatorEnabled = false;
        this.drawerToggle.SetHomeAsUpIndicator(Resource.Drawable.MenuButton);

И, наконец, назначил переключателю меню панели инструментов ToolbarNavigationClickListener типа класса, который я создал ранее:

        this.drawerToggle.ToolbarNavigationClickListener = new NavClickHandler(this);

И затем у вас есть настраиваемая кнопка меню с обработанными событиями щелчка.

person Trevor Hart    schedule 05.07.2017

Попробуйте этот код

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();
    if(id == android.R.id.home){
        //You can get 
    }
    return super.onOptionsItemSelected(item);
}

Добавьте приведенный ниже код в свой метод onCreate ()

ActionBar ab = getSupportActionBar();
    ab.setDisplayHomeAsUpEnabled(true);
person Faxriddin Abdullayev    schedule 22.07.2017