I am trying to build an app that will implement Action Bar tabs. One of the tabs should contain a MapFragment.
How can I implement an action bar with tabs, under one of which is a map Fragment?
Can you help me with how to proceed with this?
Here is what I have so far :
main class
package com.nfc.demo;
import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.os.Bundle;
public class NFCDemoActivity extends Activity {
Tab selectedTab = null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar bar = getActionBar();
bar.setDisplayShowHomeEnabled(false);
bar.setDisplayShowTitleEnabled(false);
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setCustomView(R.layout.main);
ActionBar.Tab mapTab = bar.newTab().setText("Map");
ActionBar.Tab settingsTab = bar.newTab().setText("Settings");
ActionBar.Tab aboutTab = bar.newTab().setText("About");
MapFragment mapFragment = new MapFragment();
SettingsFragment settingsFragment = new SettingsFragment();
AboutFragment aboutFragment = new AboutFragment();
mapTab.setTabListener(new TabListener(mapFragment));
settingsTab.setTabListener(new TabListener(settingsFragment));
aboutTab.setTabListener(new TabListener(aboutFragment));
Tab selectedTab = (Tab) getLastNonConfigurationInstance();
if (selectedTab == null) {
bar.addTab(mapTab, false);
bar.addTab(settingsTab, false);
bar.addTab(aboutTab, true);
}
setContentView(R.layout.main);
}
public Object onRetainNonConfigurationInstance() {
return selectedTab;
}
protected boolean isRouteDisplayed() {
return false;
}
protected class TabListener implements ActionBar.TabListener {
private Fragment fragment;
public TabListener(Fragment fragment) {
this.fragment = fragment;
}
public void onTabSelected(Tab tab, FragmentTransaction fragmentTransaction) {
fragmentTransaction.replace(R.id.mainFragment, this.fragment, null);
selectedTab = tab;
}
public void onTabUnselected(Tab tab, FragmentTransaction fragmentTransaction) {
fragmentTransaction.remove(this.fragment);
}
public void onTabReselected(Tab tab, FragmentTransaction fragmentTransaction) {
//do nothing
}
}
}
The Fragment classes are all just returning an inflater with an .xml layout.
XML Layouts :
main.xml ( map should be on this XML file )
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/mainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</LinearLayout>
settings.xml AND about.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="@+id/textView123"
android:text="asdfg"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
But adding the MapFragment
thows a error:
Error inflating class fragment
error caused by java.lang.IllegalArgumentException:
Binary XML file line #2: Duplicate id 0x7f040005, tag null, or parent id 0x1020002 with another fragment for com.google.android.gms.maps.MapFragment 12-28 21:14:07.991: E/AndroidRuntime(26189): at android.app.Activity.onCreateView(Activity.java:4722)
I've been trying to figure out how to proceed for a couple of days but I am really confused. Any help/tips would be greatly appreciated.
Also, what about getLastNonConfigurationInstance()
? It is deprecated.
In the following solution, it is possible to add a GoogleMap to an Action Bar tab/dropdown. The key to doing this lies in correctly setting up your fragment to destroy the MapFragment when switching to another fragment in the Action Bar.
Create an Activity that implements the Action Bar functionality:
Activity
and implements ActionBar.OnNavigationListener
.public boolean onNavigationItemSelected(int position, long id)
.position
object to determine the selected tab and set the fragment to a new instance using the FragmentManager like this: getFragmentManager().beginTransaction().replace(R.id.container, fragment).commit()
.Create a fragment that holds the map:
Fragment
to use as your tab's fragment. Read [1] to better understand the MapFragment.onCreateView
.
@Override
public void onDestroyView() {
super.onDestroyView();
MapFragment f = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
if (f != null)
getFragmentManager().beginTransaction().remove(f).commit();
}