Reputation: 1107
I am creating an app that has 4 main sections. I would like to have a very simple way of doing the navigation which would mean if the phone supports an action bar, then I would like it to display a tabbed action bar. Otherwise the regular menu button showing the menu is fine.
The problem is though that the action bar seams un-manageable or un-created when trying it out on phones with an sdk version that actually supports action bars.
I am using a menu/menu.xml file to create the menu and items that I want to display. I am then using onCreateOptionsMenu() with MenuInflater to populate the menu for each Activity. This works just fine on all phones but on phones that use the action bar, I get a title-type bar with the app icon on the far left, the current Activity title next to it, and then on the far right is the icon for the first menu item followed by the 3 squares (which when you click on them, show the rest of the menu items). This situation stays the same regardless of the Activity that I am in.
What I want is a tabbed action bar to show up instead with the icon and text (if there is room for the text) and have whatever current Activity the user is viewing to be "selected" in the tabbed-action bar. The same way shown here:
http://developer.android.com/images/ui/actionbar.png (I can't make it an image due to being a new user)
Here is the code I am using:
manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.mypackage"
android:versionCode="1"
android:versionName="1.0" >
<uses-permission
android:name="android.permission.INTERNET" />
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission
android:name="android.permission.READ_PHONE_STATE" />
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="15" />
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.Holo">
<uses-library android:name="com.google.android.maps" />
<activity
android:name=".ActivityLoad"
android:label="label">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
....more activities....
</application>
</manifest>
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menuMap"
android:title="@string/A_MAP_TITLE"
android:icon="@drawable/nav_map"
android:showAsAction="ifRoom|withText">
</item>
<item
android:id="@+id/menuList"
android:title="@string/A_LIST_TITLE"
android:icon="@drawable/nav_list"
android:showAsAction="ifRoom|withText">
</item>
<item
android:id="@+id/menuMore"
android:title="@string/A_MORE_TITLE"
android:icon="@drawable/nav_more"
android:showAsAction="ifRoom|withText">
</item>
<item
android:id="@+id/menuReport"
android:title="@string/A_REPORT_TITLE"
android:icon="@drawable/nav_report"
android:showAsAction="ifRoom|withText">
</item>
</menu>
MyActivity.java
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.options, menu);
return super.onCreateOptionsMenu(menu);
}
I have tried setting the action bar navigation mode using this code in my activities onCreate() method but all that happens is a blank action bar is shown below the "bad" action bar that I get by default:
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
All the tutorials seam to just say "use a style" or something but I have no idea where to put a style xml file or how to set this to my menu or what I should actually be doing here. If anyone could help it would be greatly appreciated!
Upvotes: 1
Views: 9166
Reputation: 2003
First make sure your MyActivity.java is implementing ActionBar.TabListener which means you will need to override 3 functions. I don't know how you did your fragments but this is how I did it in MyActivity.java:
public class MyActivity extends FragmentActivity implements ActionBar.TabListener {
private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Set up the action bar.
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// For each of the section, add a tab to the action bar.
actionBar.addTab(actionBar.newTab().setText(R.string.title_status).setTabListener(this));
actionBar.addTab(actionBar.newTab().setText(R.string.title_configuration).setTabListener(this));
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
getActionBar().setSelectedNavigationItem(
savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(STATE_SELECTED_NAVIGATION_ITEM,
getActionBar().getSelectedNavigationIndex());
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, show the tab contents in the container
Fragment fragment = new DummySectionFragment();
Bundle args = new Bundle();
args.putInt(DummySectionFragment.ARG_SECTION_NUMBER, tab.getPosition() + 1);
fragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
/**
* A dummy fragment representing a section of the app, but that simply displays dummy text.
*/
public static class DummySectionFragment extends Fragment {
public DummySectionFragment() {
}
public static final String ARG_SECTION_NUMBER = "section_number";
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TextView textView = new TextView(getActivity());
textView.setGravity(Gravity.CENTER);
Bundle args = getArguments();
textView.setText(Integer.toString(args.getInt(ARG_SECTION_NUMBER)));
return textView;
}
}
}
In order to customize the actionbar you need to use a custom style that has Theme.Holo as a parent. This way it inherits everything from the Holo theme but then you can overwride what you want. Inside manifest.xml use:
<application
android:theme="@style/AppTheme">
instead of:
<application
android:theme="@android:style/Theme.Holo">
Then inside values/styles.xml put your custom style:
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<style name="AppTheme" parent="android:Theme.Holo.Light">
<item name="android:actionBarStyle">@style/MyActionBar</item>
<item name="android:actionBarTabStyle">@style/MyActionBarTabStyle</item>
<item name="android:actionBarTabBarStyle">@style/MyActionBarTabBar</item>
</style>
This is where it gets a little tricky. within the same file(values/styles.xml) you need to define each style you referenced above.
<style name="MyActionBar" parent="@android:style/Widget.Holo.Light.ActionBar">
<item name="android:background">@drawable/menu_bar</item> <!-- remove if you don't have custom background for action bar -->
<item name="android:displayOptions"></item> <!-- get rid of logo on left and title, if you want logo on left put useLogo here -->
<item name="android:customNavigationLayout">@layout/custom_action_bar</item> <!-- This is where you define how you want things to layout in your actionbar. I use a relative layout -->
</style>
<!-- Style for tab bar -->
<style name="MyActionBarTabBar" parent="@android:style/Widget.Holo.Light.ActionBar.TabBar">
<item name="android:showDividers">none</item>
<item name="android:paddingLeft">20dp</item>
</style>
<!-- Style for action bar tabs -->
<style name="MyActionBarTabStyle" parent="@android:style/Widget.Holo.Light.ActionBar.TabView">
<item name="android:background">@drawable/menu_tab</item> <!-- I use a background for my tabs also -->
</style>
If you don't care about custom background for each tab remove the last style from above. If you have a custom background for each tab (you will need a selected state .9.png image and a not selected state .9.png image), you will need drawable/menu_tab.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:constantSize="false"
android:dither="true"
android:variablePadding="false" >
<item android:state_selected="true" >
<inset android:insetTop="23dp"
android:insetBottom="26dp" >
<bitmap android:src="@drawable/menu_selected" ></bitmap>
</inset>
</item>
<item android:state_selected="false" >
<inset android:insetTop="20dp"
android:insetBottom="26dp" >
<bitmap android:src="@drawable/menu_not_selected" ></bitmap>
</inset>
</item>
</selector>
Now create layout/custom_action_bar.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:contentDescription="@string/LogoText"
android:paddingRight="20dp"
android:paddingTop="20dp"
android:src="@drawable/ic_launcher" />
</RelativeLayout>
The custom_action_bar can be however you want to layout the rest of the action bar elements. I just put the logo on the right but in your case you can use the overflow menu button or whatever you want. I use a custom background for the action bar and for each tab. If you do so you will need to create .9.png files to make sure they are compatible with different screens.
The finished result looks like:
Upvotes: 4