Nie można przechwycić zdarzenia kliknięcia przycisku strony głównej paska narzędzi

106

Zaimplementowałem najnowszą bibliotekę appcompat i używam Toolbarpaska akcji jako paska akcji. Ale problem polega na tym, że nie mogę złapać zdarzenia kliknięcia przycisku głównego / ikony hamburgera. Próbowałem i szukałem wszystkiego, ale nie wydaje się, aby znaleźć podobny problem.

To jest moja Activityklasa:

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

A to jest moja klasa 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);
}

kiedy kliknąłem pozycję menu, zostanie wywołana pozycja dziennika „wybrana pozycja”. Ale kiedy klikam przycisk strony głównej, otwiera się szuflada nawigacji, ale dziennik „wybrany dom” nigdy nie jest wywoływany. Ustawiłem również onOptionsItemSelectedmetodę w moim Activity, ale nadal nie jest wywoływana.

Dark Leonhart
źródło

Odpowiedzi:

224

Jeśli chcesz wiedzieć, kiedy kliknięto dom AppCompatActivity, spróbuj tego w następujący sposób:

Najpierw powiedz Androidowi, że chcesz używać swojego Toolbarjako ActionBar:

setSupportActionBar(toolbar);

Następnie ustaw Home tak, aby był wyświetlany w setDisplayShowHomeEnabledten sposób:

getSupportActionBar().setDisplayShowHomeEnabled(true);

Wreszcie, android.R.id.homejak zwykle, nasłuchuj zdarzeń kliknięcia :

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

Jeśli chcesz wiedzieć, kiedy kliknięto przycisk nawigacji Toolbarw klasie innej niż AppCompatActivity, możesz użyć tych metod, aby ustawić ikonę nawigacji i nasłuchiwać zdarzeń kliknięcia. Ikona nawigacji pojawi się po lewej stronie, w Toolbarmiejscu, w którym znajdował się przycisk „Strona główna”.

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

Jeśli chcesz wiedzieć, kiedy hamburger kliknięciu i gdy szuflada otwiera się, jesteś już słuchać tych wydarzeń za pośrednictwem onDrawerOpeneda onDrawerClosedwięc będziemy chcieli, aby zobaczyć, czy te wywołania zwrotne dopasować swoje wymagania.

MrEngineer13
źródło
1
Próbowałem wcześniej pierwszej części, ale nie działa. Wypróbowałem drugą część i działa. Ale ikona się nie zmienia, jeśli zarejestruję pasek narzędzi w szufladzie nawigacji. Jeszcze jedno pytanie, czy jest jakiś zamiennik dla tego setDrawerIndicatorEnabled? Próbowałem z tą nową szufladą nawigacyjną i otrzymałem błąd. Dziękuję
Dark Leonhart
Drugie rozwiązanie działa. Ale jak możemy wykryć kliknięcie przycisku głównego i przycisku szuflady w drugim rozwiązaniu. Kliknięcie ikony szuflady nie powoduje otwarcia szuflady.
Dory
2
Kiedy ustawisz NavigationOnClickListener dla paska narzędzi, tracisz „natywne” zachowanie szuflady :(
IlyaEremin
7
Więc teraz potrzebujemy oddzielnego nasłuchiwania kliknięć, kiedy wcześniej we fragmentach moglibyśmy sprawdzić android.R.id.home w onOptionsItemSelected ()? To naprawdę bardzo irytujące
Daniel Wilson
1
re: Pasek narzędzi, jeśli ustawisz nowy NavigationOnClickListener (za pomocą setNavigationOnClickListener), możesz później w razie potrzeby przywrócić NavDrawer, ponownie wywołując setDrawerListener z ActionBarDrawerToggle.
straya
24
    mActionBarDrawerToggle = mNavigationDrawerFragment.getActionBarDrawerToggle();
    mActionBarDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // event when click home button
        }
    });

w mycase ten kod działa idealnie

vuhung3990
źródło
Jesteś naprawdę świetne, to działało, nigdy nie myślałem, że mogę w stanie uchwyt paska narzędzi przycisk Wstecz przez DrawerToggle ..
Sai
Aby ActionBarDrawerToggle.setToolbarNavigationClickListener działało, należy najpierw wywołać to: mActionBarDrawerToggle.setHomeAsUpIndicator (R.drawable.menu_icon); mActionBarDrawerToggle.setDrawerIndicatorEnabled (false); i samodzielnie zarządzać kliknięciami. (otwórz / zamknij szufladę po kliknięciu)
luky
11

W ten sposób robię to, aby powrócić do właściwego fragmentu, w przeciwnym razie, jeśli masz kilka fragmentów na tym samym poziomie, powrócisz do pierwszego, jeśli nie zmienisz zachowania przycisku Wstecz na pasku narzędzi.

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });
Marcos
źródło
Czy w Kotlinie mamy metodę kliknięcia „Zastąp”?
Akhila Madari
@AkhilaMadari spróbuj czegoś takiego w Kotlin: val toolbar = findViewById (R.id.toolbar) as Toolbar setSupportActionBar (toolbar) toolbar.setNavigationOnClickListener {/ * zrób coś, co chcesz * / finish ()}
Marcos
3

Myślę, że prawidłowe rozwiązanie z obsługą biblioteki 21 jest następujące

// 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                          
        }                       
    });                 
}
Čikić Nenad
źródło
w this.getResValues().homeIconDrawable(), kto jest this?
LuisComS
To jest aktywność. Getresvalues ​​to moja metoda, więc nie ma tu znaczenia. Setlogo akceptuje identyfikator zasobu do rysowania.
Čikić Nenad
4
to poradzi sobie z kliknięciem użytkownika w dowolnym miejscu na całym pasku narzędzi, nie sądzę, żeby o to pytał
Mina Fawzy.
1

Obsługiwałem przycisk Wstecz i Początek w szufladzie nawigacji, jak

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

iw każdym onViewCreatedwołam

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ((HomeActivity)getActivity()).updateDrawerIcon();
    ((HomeActivity) getActivity()).setActionBarTitle("List");
}
AndroidGeek
źródło
0

W ten sposób zaimplementowałem projekt przedmaterialny i wydaje się, że nadal działa, teraz przeszedłem na nowy Toolbar. W moim przypadku chcę zalogować użytkownika, jeśli spróbuje otworzyć nawigację boczną po wylogowaniu (i złapać zdarzenie, aby nawigacja boczna się nie otworzyła). W twoim przypadku nie mogłeś 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);
}
darnmason
źródło
Ach, zapomniałem, że odkryłem, że nie mogę złapać kliknięcia przycisku głównego we fragmencie, zadałem tutaj pytanie i zasugerowałem obejście polegające na ręcznym przekazaniu wydarzenia na wszystkie twoje fragmenty. stackoverflow.com/q/21938419/1007151
darnmason
0

Zmieniłem nieco DrawerLayout, aby uzyskać zdarzenia i móc konsumować i zdarzać, na przykład jeśli chcesz użyć actionToggle as back, jeśli jesteś w widoku szczegółowym:

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

}
Adrian
źródło
0

Najłatwiejszym podejściem, jakie możemy zrobić, jest zmiana ikony domu na znaną ikonę i porównanie elementów do rysowania (ponieważ ikona android.R.id.home może się różnić w zależności od różnych wersji API

więc ustaw pasek narzędzi jako actionbar 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 
                    }
                }
            }
Sajidh Zahir
źródło
0

W moim przypadku musiałem umieścić ikonę za pomocą:

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

Następnie słuchaj zdarzeń kliknięcia z domyślnymi identyfikatorami onOptionsItemSelected i android.R.id.home

Diego Laballos
źródło
1
To nie zadziała. android.R.id.homenigdy nie strzelaj
Trancer
0

Dla każdego, kto szuka implementacji Xamarina (ponieważ zdarzenia są wykonywane inaczej w C #), po prostu utworzyłem tę NavClickHandlerklasę w następujący sposób:

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

Następnie przypisano niestandardowy przycisk menu hamburgera w następujący sposób:

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

I na koniec przypisano przełącznikowi menu szuflady ToolbarNavigationClickListener typu klasy, którą utworzyłem wcześniej:

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

Następnie masz niestandardowy przycisk menu z obsługą zdarzeń kliknięcia.

Trevor Hart
źródło
0

Wypróbuj ten kod

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

Dodaj poniższy kod do metody onCreate ()

ActionBar ab = getSupportActionBar();
    ab.setDisplayHomeAsUpEnabled(true);
Faxriddin Abdullayev
źródło