Klickereignis der Home-Schaltfläche der Symbolleiste kann nicht erfasst werden


106

Ich habe die neueste Appcompat-Bibliothek implementiert und die Toolbarals Aktionsleiste verwendet . Das Problem ist jedoch, dass ich das Klickereignis für den Home-Button / das Hamburger-Symbol nicht abfangen kann. Ich habe alles versucht und gesucht, aber es scheint kein ähnliches Problem zu finden.

Das ist meine ActivityKlasse:

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

Und das ist meine NavigationDrawerFragment-Klasse:

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

Wenn ich auf ein Menüelement geklickt habe, wird das Protokoll "Element ausgewählt" aufgerufen. Wenn ich jedoch auf die Home-Schaltfläche klicke, wird die Navigationsleiste geöffnet, aber das Protokoll "Home ausgewählt" wird nie aufgerufen. Ich habe auch eine onOptionsItemSelectedMethode in meiner festgelegt Activity, aber sie wird immer noch nicht aufgerufen.

Antworten:


224

Wenn Sie wissen möchten, wann auf Home geklickt wird AppCompatActivity, sollten Sie es folgendermaßen versuchen:

Sagen Sie zuerst Android, dass Sie Ihr Toolbarals Ihr verwenden möchten ActionBar:

setSupportActionBar(toolbar);

Stellen Sie dann Home so ein, dass es setDisplayShowHomeEnabledwie folgt angezeigt wird :

getSupportActionBar().setDisplayShowHomeEnabled(true);

Hören Sie zum Schluss android.R.id.homewie gewohnt auf Klickereignisse:

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

Wenn Sie wissen möchten, wann Toolbarin einer anderen Klasse als einer auf die Navigationsschaltfläche geklickt wird AppCompatActivity, können Sie mit diesen Methoden ein Navigationssymbol festlegen und auf Klickereignisse warten. Das Navigationssymbol wird auf der linken Seite angezeigt, Toolbarwo sich früher die Schaltfläche "Home" befand.

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

Wenn Sie wissen möchten, wann auf den Hamburger geklickt wird und wann die Schublade geöffnet wird, hören Sie bereits über auf diese Ereignisse onDrawerOpenedund onDrawerClosedmöchten sehen, ob diese Rückrufe Ihren Anforderungen entsprechen.


1
Versuchte den ersten Teil vor, aber es funktioniert nicht. Versuchte den zweiten Teil, und es funktioniert. Das Symbol ändert sich jedoch nicht, wenn ich die Symbolleiste in der Navigationsleiste registriere. Noch eine Frage, gibt es dafür einen Ersatz für setDrawerIndicatorEnabled? Ich habe es mit dieser neuen Navigationsschublade versucht und Fehler erhalten. Vielen Dank u
Dark Leonhart

Die zweite Lösung funktioniert. Aber wie können wir in der zweiten Lösung den geklickten Home-Button und den Schubladen-Button erkennen? Wenn ich auf das Schubladen-Symbol klicke, wird die Schublade nicht geöffnet.
Dory

2
Wenn Sie NavigationOnClickListener für die Symbolleiste festlegen, verlieren Sie das "native" Schubladenverhalten :(
IlyaEremin

7
Jetzt brauchen wir also einen separaten Klick-Listener, wenn wir vorher in Fragmenten in onOptionsItemSelected () nach android.R.id.home suchen konnten? Das ist wirklich sehr nervig
Daniel Wilson

1
Betreff: Symbolleiste: Wenn Sie einen neuen NavigationOnClickListener festlegen (mithilfe von setNavigationOnClickListener), können Sie den NavDrawer später gegebenenfalls wiederherstellen, indem Sie setDrawerListener erneut mit Ihrem ActionBarDrawerToggle aufrufen.
Straya

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

In meinem Fall funktioniert dieser Code perfekt


Sie sind wirklich großartig, es hat funktioniert, ich hätte nie gedacht, dass ich die Schaltfläche zum Zurücksetzen der Symbolleiste über DrawerToggle verarbeiten kann.
Sai

Damit ActionBarDrawerToggle.setToolbarNavigationClickListener funktioniert, muss zuerst Folgendes aufgerufen werden: mActionBarDrawerToggle.setHomeAsUpIndicator (R.drawable.menu_icon); mActionBarDrawerToggle.setDrawerIndicatorEnabled (false); und verwalten Sie die Klickereignisse selbst. (Schublade beim Klicken öffnen / schließen)
luky

9

So mache ich es, um zum richtigen Fragment zurückzukehren. Andernfalls, wenn Sie mehrere Fragmente auf derselben Ebene haben, würde es zum ersten zurückkehren, wenn Sie das Verhalten der Symbolleisten-Zurück-Schaltfläche nicht überschreiben.

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            finish();
        }
    });

Haben wir in Kotlin die Klickmethode "Überschreiben"?
Akhila Madari

@AkhilaMadari versuchen Sie so etwas in Kotlin: val toolbar = findViewById (R.id.toolbar) als Symbolleiste setSupportActionBar (Symbolleiste) toolbar.setNavigationOnClickListener {/ * tun Sie etwas, was Sie wollen * / finish ()}
Marcos

3

Ich denke, die richtige Lösung mit der Support-Bibliothek 21 ist die folgende

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

in this.getResValues().homeIconDrawable(), wer ist this?
LuisComS

Dies ist eine Aktivität. Getresvalues ​​ist meine Methode, daher ist sie hier nicht relevant. Setlogo akzeptiert eine zeichnbare Ressourcen-ID.
Čikić Nenad

4
Dies wird Benutzer Klick auf eine beliebige Stelle in der gesamten Symbolleiste behandeln, ich glaube nicht, was er gefragt hat
Mina Fawzy

1

Ich habe zurück und Home-Taste in der Navigationsleiste wie behandelt

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

und in jedem onViewCreatedrufe ich an

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

0

So habe ich das Pre-Material-Design implementiert und es scheint immer noch zu funktionieren, jetzt habe ich auf das neue umgestellt Toolbar. In meinem Fall möchte ich den Benutzer anmelden, wenn er versucht, das seitliche Navigationssystem zu öffnen, während er abgemeldet ist (und das Ereignis abfangen, damit das seitliche Navigationssystem nicht geöffnet wird). In deinem Fall konntest du nicht 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);
}

Ah, ich habe vergessen, dass ich festgestellt habe, dass ich den Klick auf die Home-Schaltfläche in einem Fragment nicht abfangen konnte. Ich habe hier eine Frage gestellt und eine Problemumgehung vorgeschlagen, bei der das Ereignis manuell an alle Ihre Fragmente übergeben wird. stackoverflow.com/q/21938419/1007151
darnmason

0

Ich habe das DrawerLayout ein wenig geändert, um die Ereignisse abzurufen und in der Lage zu sein, Ereignisse zu konsumieren, z. B. wenn Sie actionToggle als Zurück verwenden möchten, wenn Sie sich in der Detailansicht befinden:

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

}

0

Der einfachste Ansatz ist, das Home-Symbol in ein bekanntes Symbol zu ändern und Drawables zu vergleichen (da sich das android.R.id.home-Symbol von verschiedenen API-Versionen unterscheiden kann

Legen Sie daher eine Symbolleiste als Aktionsleiste fest. 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 
                    }
                }
            }

0

In meinem Fall musste ich das Symbol setzen mit:

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

Hören Sie sich dann Klickereignisse mit der Standard-ID onOptionsItemSelected und android.R.id.home an


1
Dies wird nicht funktionieren. android.R.id.homeNiemals feuern
Trancer

0

Für alle, die nach einer Xamarin-Implementierung suchen (da Ereignisse in C # anders ausgeführt werden), habe ich diese NavClickHandlerKlasse einfach wie folgt erstellt:

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

Weisen Sie dann eine benutzerdefinierte Hamburger-Menüschaltfläche wie folgt zu:

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

Und schließlich wurde dem Schubladenmenü ein ToolbarNavigationClickListener des Klassentyps zugewiesen, den ich zuvor erstellt habe:

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

Und dann haben Sie eine benutzerdefinierte Menüschaltfläche, mit der Klickereignisse behandelt werden.


0

Versuchen Sie diesen Code

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

Fügen Sie Ihrem onCreate () -Metod den folgenden Code hinzu

ActionBar ab = getSupportActionBar();
    ab.setDisplayHomeAsUpEnabled(true);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.