I am working on an app that has a support Fragment
with a SearchView
widget and RecyclerView
to present search results which sends the user to a FragmentActivity
to display the details of the selection. All of this works fine, but I'm seeing inconsistent behavior between the Nexus 6 emulator and the actual device in regards to the backstack. In the emulator, everything works as I would expect, with the user being taken back to the search results fragment if pressing the Back button while on the details FragmentActivity. On the actual Nexus 6 device, the user is taken all the way back to the AppCompatActivity
which contains my app's menu (this activity uses the support FragmentManager
, which adds the fragments it manages to the backstack):
private void replaceFragment(Fragment supportFragment) {
String fragmentName = supportFragment.getClass().getSimpleName();
supportFragmentManager.beginTransaction()
.addToBackStack(fragmentName)
.replace(R.id.frame_menu_container, supportFragment, fragmentName)
.commit();
}
The code to send the user from the Fragment to the FragmentActivity is just an intent with extras:
Intent intent = new Intent(getActivity(), PlayerDetailsActivity.class);
intent.putExtra(TransientPlayer.BUNDLE_KEY, transientPlayer);
startActivity(intent);
I am not doing anything special with the backstack (yet) - this is with default behavior.
What could be the issue here? I've done some reading on the backstack and I haven't seen anything yet on manually adding something to the backstack when you're going back from a FragmentActivy to a Fragment where you're not using the FragmentManager.
EDIT 1: Here's the layout XML where frame_menu_container
is defined:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<FrameLayout
android:id="@+id/frame_menu_container"
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_home">
</FrameLayout>
</RelativeLayout>
EDIT 2: OK, here is a textual description of my high-level activities and fragments:
NavigationMenuActivity
, which extends AppCompatActivity
. This is where all the fragments are swapped in and out as needed, and the SupportFragmentManager
is used and where I have the replaceFragment()
method.
I have the following fragments, all of which either display static information, make REST calls to retrieve and display data, or allow the user to send feedback. All extend android.support.v4.app.Fragment
, and none of them have other fragments or activities the user can go to.
- HomeFragment
- CalendarFragment
- StandingsFragment
- PlayerSearchFragment (see below)
- AboutFragment
- FeedbackFragment
The only exception in functionality for these fragments is the PlayerSearchFragment
, which also extends android.support.v4.app.Fragment
. This fragment contains a RecyclerView
that displays the results of a REST call when users want to search for players. When results are returned and the user selects an item from the list, they are sent to a PlayerDetailsActivity
which extends FragmentActivity
.
The PlayerDetailsActivity
uses a FragmentTabHost
view which contains different types of information about the player that can be viewed. This is the "end of the line" down this path - there are no other fragments or activities the user can go to. This is where the issue is. When I hit the Back button while on this activity, my intention is to have the user go back to the PlayerSearchFragment
fragment (search results), which in this case, they do if I'm in a Nexus 6 emulator, but they go all the way back to the NavigationMenuActivity
activity if I'm on my actual Nexus 6 device.
I have the following method in the PlayerDetailsActivity
which is called when the Back button is pressed, but it always shows zero entries:
@Override
public void onBackPressed() {
FragmentManager fragmentManager = getSupportFragmentManager();
int count = fragmentManager.getBackStackEntryCount();
Log.i(TAG, "Backstack : There are " + count + " entries");
for (int i = 0; i > count; i++) {
FragmentManager.BackStackEntry backStackEntry = fragmentManager.getBackStackEntryAt(i);
Log.i(TAG, String.format("Backstack : id=%d, name=%s, shortTitle=%s, breadcrumbTitle=%s",
backStackEntry.getId(),
backStackEntry.getName(),
backStackEntry.getBreadCrumbShortTitle(),
backStackEntry.getBreadCrumbTitle()));
}
super.onBackPressed();
}
My hope is to have the experience be the same for all devices, whether hardware or emulator.
While I still don't have an answer as to why I couldn't get this to work the way I had hoped, I do have a workaround, and it does work well for what I need to do. Basically, I override the Up and Back navigation callbacks in
PlayerDetailsActivity
and use an intent (with data) to explicitly send the user back toNavigationMenuActivity
. The data I send in the intent is basically just a boolean that tells me if I'm coming from thePlayerDetailsActivity
and if so, show that fragment rather than the Home fragment, like so:The above changes were after I changed the class to extend from
AppCompatActivity
and added the following inPlayerDetailsActivity.onCreate()
to activate the ActionBar for Up navigation:Also, in
NavigationMenuActivity.onCreate()
I do this:I don't know if this is the most 'appropriate' way to do this, but it work well and does what I need across a handful of hardware devices and Nexus 4/5/6 emulators.