Przełączanie między obrazem szuflady nawigacyjnej Androida a karetką w górę podczas korzystania z fragmentów
Podczas korzystania z szuflady nawigacyjnej twórcy Androida zalecają, aby w pasku działań "tylko te ekrany, które są reprezentowane w szufladzie nawigacyjnej, miały rzeczywiście obraz szuflady nawigacyjnej" i " wszystkie inne ekrany mają tradycyjny Karat."
Zobacz tutaj po szczegóły: http://youtu.be/F5COhlbpIbY
Używam jednego działania do kontrolowania wielu poziomów fragmentów i mogę uzyskać obraz szuflady nawigacyjnej do wyświetlania i działania w ogóle poziomy.
Podczas tworzenia fragmentów niższego poziomu mogę wywołać ActionBarDrawerToggle
setDrawerIndicatorEnabled(false)
aby ukryć obraz szuflady nawigacyjnej i wyświetlić karetkę do góry
LowerLevelFragment lowFrag = new LowerLevelFragment();
//disable the toggle menu and show up carat
theDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout,
lowFrag, "lowerFrag").addToBackStack(null).commit();
Problem, który mam, polega na tym, że gdy wracam do fragmentów najwyższego poziomu, który nadal pokazuje Karat, zamiast oryginalnego obrazu szuflady nawigacyjnej. Jakieś sugestie, jak "odświeżyć" pasek akcji na górnych fragmentach, aby ponownie wyświetlić obraz szuflady nawigacyjnej?
Rozwiązanie
Tom ' s sugestia zadziałała. Oto co zrobiłem:
Główna aktywność
Ta aktywność kontroluje wszystkie fragmenty w aplikacji.
Przygotowując nowe fragmenty do zastąpienia innych, ustawiam DrawerToggle setDrawerIndicatorEnabled(false)
tak:
LowerLevelFragment lowFrag = new LowerLevelFragment();
//disable the toggle menu and show up carat
theDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportFragmentManager().beginTransaction().replace(R.id.frag_layout,
lowFrag).addToBackStack(null).commit();
Następnie, w nadpisaniu onBackPressed
, przywróciłem powyższe, ustawiając DrawerToggle na setDrawerIndicatorEnabled(true)
w następujący sposób:
@Override
public void onBackPressed() {
super.onBackPressed();
// turn on the Navigation Drawer image;
// this is called in the LowerLevelFragments
setDrawerIndicatorEnabled(true)
}
In The LowerLevelFragments
We fragmentach zmodyfikowałem onCreate
i onOptionsItemSelected
tak:
W onCreate
dodano setHasOptionsMenu(true)
, aby włączyć konfigurację menu opcji. Również ustawić setDisplayHomeAsUpEnabled(true)
, aby włączyć W actionbar:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// needed to indicate that the fragment would
// like to add items to the Options Menu
setHasOptionsMenu(true);
// update the actionbar to show the up carat/affordance
getActivity().getActionBar().setDisplayHomeAsUpEnabled(true);
}
Następnie w onOptionsItemSelected
gdy Po naciśnięciu wywołuje onBackPressed()
z aktywności, aby przesunąć się o jeden poziom w hierarchii i wyświetlić obraz szuflady nawigacyjnej:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Get item selected and deal with it
switch (item.getItemId()) {
case android.R.id.home:
//called when the up affordance/carat in actionbar is pressed
getActivity().onBackPressed();
return true;
…
}
12 answers
Napisałeś, że aby zaimplementować fragmenty niższego poziomu, zastępujesz istniejący fragment, w przeciwieństwie do implementacji fragmentu niższego poziomu w nowej aktywności.
Myślę, że będziesz musiał zaimplementować funkcję back ręcznie: gdy użytkownik naciśnie wstecz, masz kod, który wyskakuje ze stosu (np. w Activity::onBackPressed
override). Więc gdziekolwiek to zrobisz, możesz odwrócić setDrawerIndicatorEnabled
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-27 10:42:01
To proste jak 1-2-3.
Jeśli chcesz osiągnąć:
1) Wskaźnik szuflady - gdy w tylnym stosie nie znajdują się żadne fragmenty lub szuflada jest otwarta
2) Strzałka - gdy niektóre fragmenty znajdują się w tylnym stosie
private FragmentManager.OnBackStackChangedListener
mOnBackStackChangedListener = new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
syncActionBarArrowState();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
getSupportActionBar().setDisplayShowHomeEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
R.drawable.ic_navigation_drawer,
0,
0
) {
public void onDrawerClosed(View view) {
syncActionBarArrowState();
}
public void onDrawerOpened(View drawerView) {
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
getSupportFragmentManager().addOnBackStackChangedListener(mOnBackStackChangedListener);
}
@Override
protected void onDestroy() {
getSupportFragmentManager().removeOnBackStackChangedListener(mOnBackStackChangedListener);
super.onDestroy();
}
private void syncActionBarArrowState() {
int backStackEntryCount =
getSupportFragmentManager().getBackStackEntryCount();
mDrawerToggle.setDrawerIndicatorEnabled(backStackEntryCount == 0);
}
3) oba wskaźniki działają zgodnie z ich kształtem
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.isDrawerIndicatorEnabled() &&
mDrawerToggle.onOptionsItemSelected(item)) {
return true;
} else if (item.getItemId() == android.R.id.home &&
getSupportFragmentManager().popBackStackImmediate()) {
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
P. S. Zobacz Tworzenie szuflady nawigacyjnej dla programistów Androida na inne wskazówki dotyczące zachowania wskaźnika 3-liniowego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-15 11:44:23
I ' ve used next thing:
getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if(getSupportFragmentManager().getBackStackEntryCount() > 0){
mDrawerToggle.setDrawerIndicatorEnabled(false);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
else {
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-23 09:44:38
Jeśli przycisk paska akcji w górę nie działa, nie zapomnij dodać słuchacza:
// Navigation back icon listener
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
Mam pewien problem z zaimplementowaniem nawigacji szuflady z przyciskiem home, wszystko działało oprócz akcji buton.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-14 21:52:31
Spróbuj obsłużyć wybór pozycji głównej w głównej aktywności w zależności od stanu DrawerToggle. W ten sposób nie musisz dodawać tego samego kodu do każdego fragmentu.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Only handle with DrawerToggle if the drawer indicator is enabled.
if (mDrawerToggle.isDrawerIndicatorEnabled() &&
mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action buttons
switch (item.getItemId()) {
// Handle home button in non-drawer mode
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-02 02:33:37
FOLLOW UP
Rozwiązanie podane przez @ dzeikei jest schludne, ale można je rozszerzyć, używając fragmentów, aby automatycznie obsłużyć ustawienie wskaźnika szuflady, gdy tylny ster jest pusty.
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Only handle with DrawerToggle if the drawer indicator is enabled.
if (mDrawerToggle.isDrawerIndicatorEnabled() &&
mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action buttons
switch (item.getItemId()) {
// Handle home button in non-drawer mode
case android.R.id.home:
// Use getSupportFragmentManager() to support older devices
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.popBackStack();
// Make sure transactions are finished before reading backstack count
fragmentManager.executePendingTransactions();
if (fragmentManager.getBackStackEntryCount() < 1){
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
return true;
default:
return super.onOptionsItemSelected(item);
}
}
EDIT
Na pytanie @JJD.
Fragmenty są przechowywane/zarządzane w działaniu. Powyższy kod jest napisany raz w tej czynności, ale obsługuje tylko karetkę do onOptionsItemSelected
.
W jednej z moich aplikacji musiałem również obsługiwać zachowanie karetki w górę po naciśnięciu przycisku Wstecz. Może to być obsługiwane przez nadpisanie onBackPressed
.
@Override
public void onBackPressed() {
// Use getSupportFragmentManager() to support older devices
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.executePendingTransactions();
if (fragmentManager.getBackStackEntryCount() < 1){
super.onBackPressed();
} else {
fragmentManager.executePendingTransactions();
fragmentManager.popBackStack();
fragmentManager.executePendingTransactions();
if (fragmentManager.getBackStackEntryCount() < 1){
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
}
};
Zwróć uwagę na powielanie kodu pomiędzy onOptionsItemSelected
i onBackPressed
, którego można uniknąć, tworząc metodę i wywołując ją w obu miejscach.
UWAGA dodaję jeszcze dwa razy executePendingTransactions
co w moim przypadku było wymagane lub miałem czasami dziwne zachowania karetki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-28 10:21:22
Stworzyłem interfejs dla aktywności hostingowej, aby zaktualizować stan widoku menu hamburgera. Dla fragmentów najwyższego poziomu ustawiam przełącznik na true
, a dla fragmentów, dla których chcę wyświetlić strzałkę w górę false.
public class SomeFragment extends Fragment {
public interface OnFragmentInteractionListener {
public void showDrawerToggle(boolean showDrawerToggle);
}
private OnFragmentInteractionListener mListener;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
this.mListener = (OnFragmentInteractionListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnFragmentInteractionListener");
}
}
@Override
public void onResume() {
super.onResume();
mListener.showDrawerToggle(false);
}
}
Potem w mojej działalności ...
public class MainActivity extends Activity implements SomeFragment.OnFragmentInteractionListener {
private ActionBarDrawerToggle mDrawerToggle;
public void showDrawerToggle(boolean showDrawerIndicator) {
mDrawerToggle.setDrawerIndicatorEnabled(showDrawerIndicator);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-05 01:20:42
Ta odpowiedź działała, ale był z tym mały problem.
getSupportActionBar().setDisplayHomeAsUpEnabled(false)
nie został wywołany jawnie i powodował, że ikona szuflady była ukryta nawet wtedy, gdy w backstacku nie było przedmiotów, więc zmiana metody setActionBarArrowDependingOnFragmentsBackStack()
zadziałała dla mnie.
private void setActionBarArrowDependingOnFragmentsBackStack() {
int backStackEntryCount = getSupportFragmentManager()
.getBackStackEntryCount();
// If there are no items in the back stack
if (backStackEntryCount == 0) {
// Please make sure that UP CARAT is Hidden otherwise Drawer icon
// wont display
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
// Display the Drawer Icon
mDrawerToggle.setDrawerIndicatorEnabled(true);
} else {
// Show the Up carat
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Hide the Drawer Icon
mDrawerToggle.setDrawerIndicatorEnabled(false);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:27
Logika jest jasna. Show back button if fragment back stack is clear. Pokaż animację materiału, jeśli stos fragmentów nie jest jasny.
getSupportFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
syncActionBarArrowState();
}
}
);
private void syncActionBarArrowState() {
int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
mNavigationDrawerFragment.setDrawerIndicatorEnabled(backStackEntryCount == 0);
}
//add these in Your NavigationDrawer fragment class
public void setDrawerIndicatorEnabled(boolean flag){
ActionBar actionBar = getActionBar();
if (!flag) {
mDrawerToggle.setDrawerIndicatorEnabled(false);
actionBar.setDisplayHomeAsUpEnabled(true);
mDrawerToggle.setHomeAsUpIndicator(getColoredArrow());
} else {
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
mDrawerToggle.syncState();
getActivity().supportInvalidateOptionsMenu();
}
//download back button from this(https://www.google.com/design/icons/) website and add to your project
private Drawable getColoredArrow() {
Drawable arrowDrawable = ContextCompat.getDrawable(getActivity(), R.drawable.ic_arrow_back_black_24dp);
Drawable wrapped = DrawableCompat.wrap(arrowDrawable);
if (arrowDrawable != null && wrapped != null) {
// This should avoid tinting all the arrows
arrowDrawable.mutate();
DrawableCompat.setTint(wrapped, Color.GRAY);
}
return wrapped;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-07 12:58:25
Jeśli spojrzysz na aplikację GMAIL i przyjdziesz tutaj, aby wyszukać ikonę carret/affordance..
Proszę Cię o to, żadna z powyższych odpowiedzi nie była jasna. udało mi się zmodyfikować zaakceptowaną odpowiedź.-
NavigationDrawer -- > Listview zawiera podfragmenty.
-
Subfragmenty będą wymienione w następujący sposób
-
FirstFragment = = position 0 - - - > this will have subfragments --> fragment
- secondFragment
- trzecia część i tak dalej....
W firstFragment masz inny fragment.
Call this on DrawerActivity
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getFragmentManager().getBackStackEntryCount() > 0) {
mDrawerToggle.setDrawerIndicatorEnabled(false);
} else {
mDrawerToggle.setDrawerIndicatorEnabled(true);
}
}
});
I we fragmencie
setHasOptionsMenu(true);
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Get item selected and deal with it
switch (item.getItemId()) {
case android.R.id.home:
//called when the up affordance/carat in actionbar is pressed
activity.onBackPressed();
return true;
}
return false;
}
W metodzie aktywności szuflady OnBackPressed ustaw przełącznik szuflady na true, aby ponownie włączyć ikonę listy nawigacji.
Dzięki, Pusp
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-10 03:35:28
Możesz spojrzeć na ten mały przykład! https://github.com/oskarko/NavDrawerExample
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-26 15:56:21
IMO, użycie onnavigateup () (jak pokazano tutaj) w rozwiązaniu riwnodennyka lub Toma jest czystsze i wydaje się działać lepiej. Po prostu zastąp kod onOptionsItemSelected tym:
@Override
public boolean onSupportNavigateUp() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
// handle up navigation
return true;
} else {
return super.onSupportNavigateUp();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:05