Overview
Hi there, I'm currently trying to develop a android app with the new material design and compatipility back to API15. This time I would like to use only one activity and multiple fragments by replacing them in the activity. While doing so, I've already run in multiple problems which i've either solved or just didn't reappeared... However, I still have a problem with the BackStack in the FragmentManager. It seems as the back button and the back icon in the toolbar (not actionbar!) are not working properly. I have the feeling, that this problem is somehow caused due to the use of AppCompatActivity. BTW: Since I find it very hard to understand whats the right way to code a api22 android app with one Activity/ multiple Fragments, every tip/critique from you guys is very welcome!
Problem
Back button and back icon in toolbar not working.
When I open the settings via the toolbar, neither the back button nor the back icon in the toolbar brings me back to the previous fragment. The back icon in the toolbar just doesn't do anything and the (software) back button closes the app
Code
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Load in first fragment
getFragmentManager().beginTransaction()
.add(R.id.fragment_container, new MyListFragment())
.commit();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
// Replace current fragment with settings fragment
getFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new SettingsFragment())
.addToBackStack(null)
.commit();
return true;
}
return super.onOptionsItemSelected(item);
}
}
MyListFragment
Just a simple ListFragment
SettingsFragment
public class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Activate back icon in toolbar
((AppCompatActivity)getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true);
// Inflate preferences
addPreferencesFromResource(R.xml.settings);
}
}
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimaryDark"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
value/style.xml (same as value-v21/style.xml)
<resources>
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item>
<item name="@color/primary">#2196F3</item>
<item name="@color/primaryDark">#1976D2</item>
<item name="@color/accent">#FF4081</item>
</style>
</resources>
Update
The (software) back button now works when overwriting onBackPressed() as following:
public void onBackPressed() {
getFragmentManager().popBackStack();
}
However, the back icon in the toolbar still doesn't take me back.
The issue with the 'back' button in your Toolbar
, is that it is not designed for back navigation. The backwards facing arrow in the Toolbar
is for 'up' navigation (incredibly confusing at times -- and often shares the same behavior as the device 'back' button). See this link for further explanation:
http://developer.android.com/design/patterns/navigation.html
While there are certainly ways to override 'up' behavior, (e.g., overriding android.R.id.home
in the onOptionsItemSelected
method), it might make more sense to add a SettingsActivity that manages the SettingsFragment. You can then set the parent Activity
of the SettingsActivity to the MainActivity in your manifest. Then both back and up should work the way you want without overriding any standard OS behavior:
http://developer.android.com/training/implementing-navigation/ancestral.html
Hope that helps!