it-swarm.com.de

Symbolleiste - Wechseln Sie mit nur einer Aktivität von der Schublade zur Rückseite

Ich habe eine Weile gesucht, wie ich zwischen dem Symbol zum Öffnen/Schließen der Schublade (vom Hamburger zum Pfeil) zu einem einfachen Pfeil nach hinten wechseln kann. Meine Anwendung hat momentan nur eine Aktivität, die zwischen mehreren Fragmenten wechselt. An einem Punkt möchte ich zwischen einem der Hauptfragmente (dh einem der Fragmente in der Schublade) zu einem Fragment wechseln, das sich hierarchisch unter dem vorherigen Fragment befindet (dh einem "Add New" -Fragment). In diesem neuen Fragment möchte ich, dass die Symbolleiste die Zurück-Schaltfläche anstelle der Schubladen-Schaltfläche anzeigt.

Ich habe mich schon lange umgesehen und verschiedene Lösungen ausprobiert. Hier sind die bemerkenswertesten:

Im Moment denke ich an eine lange, mühsame Methode zum Erstellen eines benutzerdefinierten Symbols, das ich ein- und ausblenden kann (und das native Schubladen-Symbol ein-/ausblenden). Gibt es jedoch eine bessere Möglichkeit, zwischen den Schubladen- und den Zurück-Tasten zu wechseln? 

Als nebenstehende Frage habe ich mir die Material Design-Dokumente angesehen, und einige Beispiele haben ein X in der oberen linken Ecke. Wie anders ist das zu implementieren, als die Tasten "Schublade" und "Zurück/Auf" zu implementieren?

Vielen Dank ~

Bearbeiten:

Ich kann herausfinden, wie das Symbol ersetzt wird, aber wie bekomme ich das Klickereignis?

Bisher war dies mein bester Vorsprung:

Was ich jetzt ausprobiert habe:

  • Deaktivierte bei Bedarf den DrawerToggle (dh mDrawerToggle.setDrawerIndicatorEnabled(useDrawer);)
  • Hinzufügen von Protokollen in onOptionsItemSelected in meinem NavigationDrawerFragment, in My Activity und im DialogFragment. Ich teste derzeit, welche Ausführung ausgeführt wird, wenn item.getItemId() == Android.R.id.home true ist. Keine dieser Protokollanweisungen wird ausgelöst

Zum besseren Kontext habe ich jetzt ein Vollbild-Fragment, das dem Menü eine Schaltfläche "Speichern" hinzufügt und das Schubladensymbol in ein "X" ändert. Das Fragment kann das Save-Menü-Ereignis abrufen, jedoch nicht einmal die Aktivität und der Zeichner, wenn das X getippt wird.

Edit2:

Wie gefordert, hier ein Code. Beachten Sie, dass dies alles von diesem Github-Repo ist, an dem ich gerade arbeite (beachten Sie, dass ich hier oder dort ein paar nutzlose Funktionen aus dem Schnelltest habe).

ACTIVITYMAIN:

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

    // Add the toolbar
    mToolbar = (Toolbar) findViewById(R.id.toolbar);
    if (mToolbar != null) {
        setSupportActionBar(mToolbar);
    }

    // Initialize the drawer
    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);

    // Set up the drawer
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout),
            mToolbar);

    // TODO: Check if this helps to catch the main toolbar button click
    getSupportActionBar().setDisplayShowHomeEnabled(true);

    // Get the titles for the Toolbar
    mTitles = getResources().getStringArray(R.array.drawer_items);

    mDrawerPosition = -1;
    if (savedInstanceState == null) {
        // If there was no saved position, then the default, starting position should be used
        forceChangeItemSelected(0);
    }
    else {
        // Otherwise, get the saved position from the bundle
        int position = savedInstanceState.getInt(KEY_DRAWERPOS);
        mNavigationDrawerFragment.setSelectedItem(position);
        // Title needs to be re-set
        getSupportActionBar().setTitle(mTitles[position]);
    }

    // If I include the below bit, then the DrawerToggle doesn't function
        // I don't know how to switch it back and forth
    mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d(LOG_TAG, "Navigation was clicked");

        }
    });
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    Log.d(LOG_TAG, "Activity responding to menu click...");
    if(item.getItemId() == Android.R.id.home) Log.d(LOG_TAG, "Activity got it....");

    // If the fragment is supposed to handle things, then let it
    if(mIsFragmentHandlingMenus) return false;

    int id = item.getItemId();
    if(id == R.id.save) {
        // This isn't implemented! If chosen, then there's a bug!
        Log.e(LOG_TAG, "onOptionsItemSelected: Save was selected!");
    }

    return super.onOptionsItemSelected(item);
}

@Override
public void fragmentHandlingMenus(boolean isFragmentHandlingMenus) {
    // Simply store the setting
    mIsFragmentHandlingMenus = isFragmentHandlingMenus;

    // Toggle the drawer as necessary
    mNavigationDrawerFragment.toggleDrawerUse(!isFragmentHandlingMenus);
}

NavigationDrawerFragment :

public void toggleDrawerUse(boolean useDrawer) {
    // Enable/Disable the icon being used by the drawer
    mDrawerToggle.setDrawerIndicatorEnabled(useDrawer);

    // TODO: Enable/Disable the drawer even being able to open/close
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Log.d(LOGTAG, "Drawer responding to menu click...");
    if(item.getItemId() == Android.R.id.home) Log.d(LOGTAG, "Drawer got it....");
    if (mDrawerToggle.onOptionsItemSelected(item)) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

GoalAdderFragment :

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // Allow this fragment to handle toolbar menu items
    setHasOptionsMenu(true);

    // Set up the toolbar
    ((ActionBarActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    ((ActionBarActivity) getActivity()).getSupportActionBar().setHomeAsUpIndicator(Android.R.drawable.ic_menu_close_clear_cancel);
    ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(getResources().getString(R.string.title_addgoal));
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    // Cache the Activity as the frag handler if necessary
    if(mFragHandler == null)
        mFragHandler = (TransactionHandler.FragmentTransactionHandler) getActivity();
    // Tell the Activity to let fragments handle the menu events
    mFragHandler.fragmentHandlingMenus(true);
}

@Override
public void onDetach() {
    super.onDetach();

    // Tell the Activity that it can now handle menu events once again
    mFragHandler.fragmentHandlingMenus(false);
}

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Log.d(LOGTAG, "Item id: " + item.getItemId() + " | Save id: " + R.id.save);
    Toast.makeText(getActivity(), "Fragment activated!", Toast.LENGTH_SHORT).show();

    switch (item.getItemId()) {
        case R.id.save:
            return true;
        case Android.R.id.home:
            return true;
        default:
            break;
    }

    return false;
}

Lösung:

Dies ist die ultimative Lösung, die ich mit Hilfe der untenstehenden akzeptierten Antwort gefunden habe:

NavigationDrawerFragment:

private View.OnClickListener mOriginalListener;

public void setUp(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) {
     /* Rest of setting up code */

     // Save the default listener after setting everything else up
     mOriginalListener = mDrawerToggle.getToolbarNavigationClickListener();
}

// Tells the toolbar+drawer to switch to the up button or switch back to the normal drawer
public void toggleDrawerUse(boolean useDrawer) {
    // Enable/Disable the icon being used by the drawer
    mDrawerToggle.setDrawerIndicatorEnabled(useDrawer);

    // Switch between the listeners as necessary
    if(useDrawer)
        mDrawerToggle.setToolbarNavigationClickListener(mOriginalListener);
    else
        mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(), "Custom listener", Toast.LENGTH_SHORT).show();
            }
        });
}
39
Jawad

Das ist wahrscheinlich nicht das, was Sie gerne hören würden, aber selbst in konzeptioneller Hinsicht würde ich mich eher für eine neue Tätigkeit als für ein Fragment entscheiden. 

Ihre Haupttätigkeit ist streng mit der Schublade verknüpft. Das Laden eines neuen Fragments ohne Zugriff auf die Schublade hat für mich keinen Sinn (wenn Sie jedoch der Meinung sind, warten Sie bitte auf andere Antworten). Eine neue Aktivität würde beide Probleme lösen, da sie keine Schublade hätte und ein Kind der Hauptsache sein könnte.

Ihre Nebenfrage sieht auch richtig aus. Eine "Neu hinzufügen" -Aktivität könnte aus den Richtlinien in das visuelle Muster "Vollbild-Dialog" passen. Sehen:

http://www.google.com/design/spec/components/dialogs.html#dialogs-full-screen-dialogs

Dieses Muster hat einen "Speichern", einen positiven Button oben rechts und ein X. Konzeptionell bedeutet der X-Button, einen Prozess abzubrechen/abzubrechen, anstatt einen Backstack nach oben zu navigieren. Es bedeutet, dass Sie etwas ablehnen, ohne dass etwas unternommen wird. Das passt gut zu dem, was Sie tun möchten.

Aus gestalterischer Sicht ist dies leicht durch eine neue Activity möglich, die den Überblick behalten kann. Wenn der Punkt von Fragmenten im Wesentlichen in der Lage ist, zwei oder mehr auf einmal in Tablets und auf einem größeren Bildschirm darzustellen, wäre ich mit einem alten Fragment auf meiner linken Seite und einem "Add New" -Fragment auf der rechten Seite nicht so glücklich .

Vielmehr würde ich - auf Tablets - einen schwebenden Dialog wählen, wie von den Richtlinien vorgeschlagen.

http://www.google.com/design/spec/components/dialogs.html#dialogs-confirmation-dialogs

Also Vollbildaktivität mit einer X-Taste für Telefone und schwebendem Dialog (mit Schaltflächen unten) für Tablets. Dies ist für mich der am meisten Richtlinien kohärente Ansatz.


Ich empfehle den gesamten Link zu lesen. Auf den Unterschied zwischen <- und X,

Das X unterscheidet sich von einem Aufwärtspfeil, der verwendet wird, wenn der Status der Ansicht ständig gespeichert wird oder wenn Apps über Entwurfs- oder Autosave-Funktionen verfügen. Beispielsweise wird in den Einstellungen ein Aufwärtspfeil verwendet, da alle Änderungen sofort übernommen werden. 

Und auch

Durch Berühren des X in this Settings Beispiel werden alle Änderungen verworfen. Änderungen werden nur gespeichert, wenn Sie auf Speichern drücken.

12
natario

Geben Sie diesen Code in onCreate() Ihrer Activity ein. Funktioniert gut für mich. Sogar mit compileSdk 23 und höher.

    drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    if(toolbar != null) {
        toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        toggle.syncState();
        drawer.setDrawerListener(toggle);
        getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
            @Override
            public void onBackStackChanged() {
                if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
                    getSupportActionBar().setDisplayHomeAsUpEnabled(true); // show back button
                    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            onBackPressed();
                        }
                    });
                } else {
                    //show hamburger
                    getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                    toggle.syncState();
                    toolbar.setNavigationOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            drawer.openDrawer(GravityCompat.START);
                        }
                    });
                }
            }
        });
43
matusalem

Es sollte sogar für neueste API 24 funktionieren.

In Ihrer Aktivität onCreate() tun Sie dies:

final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
final DrawerLayout drawer = (DrawerLayout) view.findViewById(R.id.drawer_layout);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);

final ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, 
    R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();

final View.OnClickListener originalToolbarListener = toggle.getToolbarNavigationClickListener();

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
    @Override
    public void onBackStackChanged() {
        if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
            toggle.setDrawerIndicatorEnabled(false);
            toggle.setToolbarNavigationClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    getSupportFragmentManager().popBackStack();
                }
            });
        } else {
            toggle.setDrawerIndicatorEnabled(true);
            toggle.setToolbarNavigationClickListener(originalToolbarListener);
        }
    }
});
27
mixel

Die Antwort von @matusalem funktioniert großartig. Ich hatte nur ein bisschen hinzuzufügen - seien Sie vorsichtig, denn die Schublade kann auch durch Wischen von der linken Seite des Bildschirms geöffnet werden. Für einige mag dies erwünscht sein, aber für mich war die Schublade deaktiviert, da sie in keinem Fragment außer meinem Hauptfragment Sinn machte. Der Swipe kann hier leicht deaktiviert werden. - Navigationsleiste - Swipe deaktivieren

Das gehört wahrscheinlich in einem Kommentar zur Antwort, aber ich habe nicht genug Ansehen. Entschuldigen Sie.

4
tpankake

Ich hatte das gleiche Problem beim Wechseln zwischen Hamburgermenü und Rückwärtspfeil in derselben Aktivität, wenn Fragmente geändert wurden. Hier ist meine Arbeitslösung, hoffe es hilft jemandem.

Hörer in Ihrer Aktivität:

private View.OnClickListener toolbarMenuListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //will be called only if toggle.setDrawerIndicatorEnabled(false); !
            Log.v(tag,"toggle onClick:"+v.getId()+" Android.R.id.home:"+Android.R.id.home);
            onBackPressed();
        }
    };

Code onCreate () so etwas wie:

...
...
setSupportActionBar(toolbar);
toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();

//set listener so you know when back on arrow is pressed
toggle.setToolbarNavigationClickListener(toolbarMenuListener);
...
...

Teil, an dem Sie mit Kommentaren interessiert sind (zurückgegebene Klasse ist ein Teil meiner Klasse, kann für ungültig erklärt werden):

/**
     * Method to set up action bar drawer.
     * @param enableBackDrawerIcon set true if want to show drawer back arrow,
     *                             false to show hamburger menu.
     * @param title shown next to drawer icon
     */
    public BaseMenusActivity drawerSetupToggle(boolean enableBackDrawerIcon, String title) {
        //NOTE: order of methods call is important!
        // If you change order order of setDrawerIndicatorEnabled and setDisplayHomeAsUpEnabled
        // method calls it won't work, weird bugs will happen (like no icon at all)
        if(enableBackDrawerIcon){
            Log.v(tag,"show drawer back icon");
            //hides hamburger menu and enables View.OnClickListener to be called
            toggle.setDrawerIndicatorEnabled(false);
            //show back arrow
            if(getSupportActionBar()!=null)
                getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        } else {
            Log.v(tag,"show hamburger menu");
            //hide back arrow
            if(getSupportActionBar()!=null)
                getSupportActionBar().setDisplayHomeAsUpEnabled(false);
            //shows hamburger menu and prevents View.OnClickListener to be called
            toggle.setDrawerIndicatorEnabled(true);
        }

        setTitle(title);
        return this;
    }

NOTE: Reihenfolge der aufgerufenen Methoden ist wichtig! Wäre besser, wenn ich es einfach in zwei Zeilen schreiben könnte, aber NICHT ARBEITEN (zumindest für mich):

toggle.setDrawerIndicatorEnabled(!enableBackDrawerIcon);
     getSupportActionBar().setDisplayHomeAsUpEnabled(enableBackDrawerIcon);

Wenn Sie daran interessiert sind, warum die Reihenfolge der Methoden in Unordnung gerät, schauen Sie sich die Implementierung dieser Methoden an.

0
user1540907
//This if block makes the menu back button to respond to clicks
    //The onOptionsItemSelected fun for whatever reason was not capturing back menu clicks
    if (toolbar != null) {
       /* toggle = ActionBarDrawerToggle(
                this, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close)
        toggle.syncState()
        drawer_layout.setDrawerListener(toggle)*/
        supportFragmentManager.addOnBackStackChangedListener(object : FragmentManager.OnBackStackChangedListener {
            override fun onBackStackChanged() {
                if (supportFragmentManager.backStackEntryCount > 0) {
                    supportActionBar?.setDisplayHomeAsUpEnabled(true) // show back button
                    toolbar.setNavigationOnClickListener(object : View.OnClickListener {
                        override fun onClick(v: View) {
                            onBackPressed()
                        }
                    })
                } else {
                    //show hamburger
                    supportActionBar?.setDisplayHomeAsUpEnabled(false)
                    toggle.syncState()
                    toolbar.setNavigationOnClickListener(object : View.OnClickListener {
                        override fun onClick(v: View) {
                            drawer_layout.openDrawer(GravityCompat.START)
                        }
                    })
                }
            }
        })

    }

Sie müssen kommentieren "toggle = ActionBarDrawerToggle ( This, drawer_layout, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close) Toggle.syncState () .__ drawer_layout.setDrawerListener (toggle) 4-7 Zeilen) Wenn Sie das automatisch generierte Navigationslayout in Android Studio verwenden, wird das Verhalten der Zurück-Menü-Taste sonst unregelmäßig. Das habe ich gemacht und es hat perfekt für mich funktioniert. Hoffe das hilft jemandem

0
defemz