Tabhost in the action bar of Honeycomb app? - android

I have an app (for Honeycomb) with a main activity that shows a sort of dashboard, with three buttons and a title. When the user clicks a button they are taken to a screen where they can enter data and do a calculation. I would like to have two approaches to the calculation in this second ('calculator') activity, and would like to implement this through having two tabs in the action bar (only when you are in this calculator activity).
I haven't used a tabhost widget or tabs ever before, so how do I go about having a tab widget in the action bar and changing the rest of the screen (everything but the action bar and system bar) when the other tab is selected?
If someone could point me towards some source code specifically for Honeycomb action bar tabs, that would be great.
Thanks for any help, and have a great day.

See Honycomb Gallery which makes use of action bar tabs.

Tabs in the action bar is a very neat feature. To make this question complete here on SO, I'll provide an example; This code goes in your Activity's onCreate
final ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// remove the activity title to make space for tabs
actionBar.setDisplayShowTitleEnabled(false);
// instantiate some fragments for the tabs
Fragment fragment1 = new Fragment1();
Fragment fragment2 = new Fragment2();
// add a new tab and set its title text and tab listener
actionBar.addTab(actionBar.newTab().setText(R.string.title_tab1)
.setTabListener(new MyTabListener(fragment1)));
actionBar.addTab(actionBar.newTab().setText(R.string.title_tab2)
.setTabListener(new MyTabListener(fragment2)));
You can put the MyTablListener as an inner class of your activity, It could look something like this;
class MyTabListener implements ActionBar.TabListener {
private Fragment fragment;
public MyTabListener(Fragment fragment) {
this.fragment = fragment;
}
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
ft.replace(R.id.activity_new_formula_fragment_content, fragment, null);
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
}

Related

How to change position of Tab Navigation?

I currently have Tab Based app and the tabs are on bottom. Is there any way to put them up?
Add Tabs To Action Bar
To create tabs using ActionBar, you need to enable
NAVIGATION_MODE_TABS, then create several instances of ActionBar.Tab
and supply an implementation of the ActionBar.TabListener interface
for each one. For example, in your activity's onCreate() method, you
can use code similar to this:
#Override
public void onCreate(Bundle savedInstanceState) {
final ActionBar actionBar = getActionBar();
// Specify that tabs should be displayed in the action bar.
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create a tab listener that is called when the user changes tabs.
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
// show the given tab
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
// hide the given tab
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
// probably ignore this event
}
};
// Add 3 tabs, specifying the tab's text and TabListener
for (int i = 0; i < 3; i++) {
actionBar.addTab(actionBar.newTab().setText("Tab " + (i + 1)).setTabListener(tabListener));
}
}
How you handle the ActionBar.TabListener callbacks to change tabs
depends on how you've constructed your content. But if you're using
fragments for each tab with ViewPager as shown above, the following
section shows how to switch between pages when the user selects a tab
and also update the selected tab when the user swipes between pages.
From Docs.

What's the new way to use different fragments for different tabs?

I have been looking far and wide at different solutions for this problem: How do I show different things in different tabs with the ActionBar in Android?
I have found a method: Using fragments as XML then put them as the layout for the different tabs. But most code that is posted is either outdated and deprecated or very complicated.
public class MainActivity extends ActionBarActivity implements ActionBar.TabListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample_main);
// Set the Action Bar to use tabs for navigation
ActionBar ab = getSupportActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Add three tabs to the Action Bar for display
ab.addTab(ab.newTab().setText("Tab 1").setTabListener(this));
ab.addTab(ab.newTab().setText("Tab 2").setTabListener(this));
ab.addTab(ab.newTab().setText("Tab 3").setTabListener(this));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate menu from menu resource (res/menu/main)
getMenuInflater().inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
// Implemented from ActionBar.TabListener
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// This is called when a tab is selected.
}
// Implemented from ActionBar.TabListener
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// This is called when a previously selected tab is unselected.
}
// Implemented from ActionBar.TabListener
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// This is called when a previously selected tab is selected again.
}
This is a sample from Android providing an example for the ActionBar and its own capabilities. This would be a good start, except it's deprecated. And most either this or something else that's deprecated. So I am wondering, What's the new way to use different fragments for different tabs?
# Try to follow below steps:
Design your activity_main.xml with Toolbar, TabLayout and ViewPager
Design layout XML's your fragments that you want to show for each Tab content.
Use FragmentPagerAdapter to populate Fragments on ViewPager
Set FragmentPagerAdapter to ViewPager using ViewPager.setAdapter(FragmentPagerAdapter)
Use TabLayout.setupWithViewPager(ViewPager) to give ability to ViewPager to work with TabLayout functionalities.
Here is a complete tutorial.
# If you are using AndroidStudio, then you can easily create it using default TabbedActivity template. Follow below Steps:
Open AndroidStudio
File > New > New Project
Give a project name > Choose minimum SDK versions then press Next
Select TabbedActivity then press Next
Choose Navigation Style: "Action Bar Tabs(with ViewPager) > Finish
Hope this will help~
A good example can be found here: https://gist.github.com/talhahasanzia/84e44e831f9c5f9b14835a253f3614dd

How to refresh the content of a tab in an actionBar (Android)?

Here the summary of my 'project' on Android 4.x and the problem I can't solve:
i have an actionBar with 2 tabs (i know it is deprecated):
...
Fragment fragmentTab1 = new FragmentTab1();
Fragment fragmentTab2 = new FragmentTab2();
Fragment fragmentTab3 = new FragmentTab3();
ActionBar.Tab tab1, tab2;
ActionBar actionBar = getActionBar();
tab1 = actionBar.newTab().setText("tab1");
tab2 = actionBar.newTab().setText("tab2");
tab1.setTabListener(new MyTabListener(fragmentTab1));
tab2.setTabListener(new MyTabListener(fragmentTab2));
actionBar.addTab(tab1);
actionBar.addTab(tab2);
...
I would like to change the fragment of a tab and refresh what the user sees, doing that in a method (not only when the tab is (re)selected).
It sounds simple, but impossible to find a easy way to do that.
After many fails, this is what I try (i remove the tab and add it with a new fragment):
void myMethod () {
getActionBar().removeTabAt(0);
tab1 = actionBar.newTab().setText("tab3");
tab1.setTabListener(new MyTabListener(fragmentTab3));
getActionBar().addTab(tab1, 0);
...
And then this awful thing to desesperatly try to update what is seen...
...
getActionBar().setSelectedNavigationItem(tab1.getPosition()+1);
getActionBar().setSelectedNavigationItem(tab1.getPosition());
}
Everything goes as wanted, except that the reselected tab1 is empty... :(
If I select with my finger tab2 then tab1 (so manually in place of programmaticaly), then tab1 appears as wanted...
So, how can I change programmaticaly the content of a tab and refresh what is seen in an actionBar?
Already a big thanks for your time!
You should depend on TabListener methods, don't do getActionBar().setSelectedNavigationItem(). There are good code samples on the Internet.
1) Google webpage # Creating Swipe Views with Tabs. Code snippet:
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
// show the given tab
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
// hide the given tab
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
// probably ignore this event
}
};
Notes: Refresh your data in onTabSelected(). You may check for tags or text in tab parameter.
2) Another good link for you # Android Fragment Tabs Example. Code snippet from the link:
public class TabListener implements ActionBar.TabListener {
private Fragment fragment;
public TabListener(Fragment fragment) {
this.fragment = fragment;
}
// When a tab is tapped, the FragmentTransaction replaces
// the content of our main layout with the specified fragment;
// that's why we declared an id for the main layout.
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.activity_main, fragment);
}
Notes: Again, refresh your data in onTabSelected(). I have to warn you that TabListener is deprecated in the new Lollipop API.
EDIT:
Sample code to set Tabs to the correct Fragments.
// Setting tab listeners.
bmwTab.setTabListener(new TabListener(bmwFragmentTab));
toyotaTab.setTabListener(new TabListener(toyotaFragmentTab));
fordTab.setTabListener(new TabListener(fordFragmentTab));
Good luck and have fun...

How to display Navigation Drawer below Viewpager tabs?

My Navigation Drawer works just fine!!
But i want to modify it such as to display drawer below viewpager tabs.
I have used Navigation Drawer by adding it into my activity and then accessed it but this time the scenario is different and want to display drawer below tabs.
Can i add Navigation Drawer in fragment layout and access it from fragment class or if its not possible / recommended then how can i achieve the same.
Please refer attached screenshot for problem understanding.
Thanks in advance.
You have two way to achieve this.
1. Method One, the sustainable
Use support.v7.Toolbar in your Layout and placing correctly your NavigationDrawer will feet your need. Moreover, it's more durable.
2. Method two: the old one
Use ActionBar Tabs see http://developer.android.com/training/implementing-navigation/lateral.html#tabs
The main part is
final ActionBar actionBar = getActionBar();
...
// Specify that tabs should be displayed in the action bar.
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// Create a tab listener that is called when the user changes tabs.
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
// show the given tab
}
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
// hide the given tab
}
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
// probably ignore this event
}
};
// Add 3 tabs, specifying the tab's text and TabListener
for (int i = 0; i < 3; i++) {
actionBar.addTab(
actionBar.newTab()
.setText("Tab " + (i + 1))
.setTabListener(tabListener));
}

Transaction between fragments only inside one ActionBar Tab

I have an app with three tabs (ActionBar Tabs), each one with one fragment at a time.
TabListener
TabsActivity
Tab1 -> ListFragment1 -> ListFragment2 -> Fragment3
Tab2 -> Tab2Fragment
Tab3 -> Tab3Fragment
The problem is when I create the FragmentTransaction (inside OnListItemClicked) from ListFragment1 to ListFragment2, the fragments inside the other tabs also change to ListFragment2.
In the end, I want to change fragments only inside on tab and preserve the state of the other tabs.
I'm already saving the state (OnSavedInstance()).
Do you know what I'm missing here?
Some of the code:
public class TabsActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tabs);
// setup Action Bar for tabs
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
// instantiate fragment for the tab
Fragment networksFragment = new NetworksFragment();
// add a new tab and set its title text and tab listener
actionBar.addTab(actionBar.newTab().setText("Tab1")
.setTabListener(new TabsListener(ListFragment1)));
// instantiate fragment for the tab
Fragment historyFragment = new HistoryFragment();
// add a new tab and set its title text and tab listener
actionBar.addTab(actionBar.newTab().setText("Tab2")
.setTabListener(new TabsListener(Tab2Fragment)));
// instantiate fragment for the tab
Fragment settingsFragment = new SettingsFragment();
// add a new tab and set its title text and tab listener
actionBar.addTab(actionBar.newTab().setText("Tab3")
.setTabListener(new TabsListener(Tab3Fragment)));
}
}
public class TabsListener implements ActionBar.TabListener {
private Fragment frag;
// Called to create an instance of the listener when adding a new tab
public TabsListener(Fragment networksFragment) {
frag = networksFragment;
}
#Override
public void onTabReselected(Tab arg0, FragmentTransaction arg1) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.add(R.id.fragment_container, frag, null);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(frag);
}
}
public class ListFragment1 extends ListFragment {
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
getListView().setItemChecked(position, true);
ListFragment2 fragment2 = ListFragment2.newInstance(position);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_container, fragment2);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
}
}
You're not missing anything (or I'm missing it too).
I searched long and hard for a way to do this "properly" but I couldn't find anything. What I ended up doing is writing my own backstack logic.
Unfortunately my employer owns my code so I can't share any of that verbatim, but here was my approach:
Create an enum with one entry for each of your tabs. Let's call it TabType.
Now create an instance variable tabStacks of type HashMap<TabType, Stack<String>>. Now you can instantiate one stack for each tab - each stack is a list of tags, as specified by Fragment.getTag(). This way you don't have to worry about storing references to Fragments and whether they're going to disappear on you when you rotate the device. Any time you need a reference to a Fragment, grab the right tag off the stack and use FragmentManager.findFragmentByTag().
Now whenever you want to push a Fragment onto a tab, generate a new tag (I used UUID.randomUUID().toString()) and use it in your call to FragmentTransaction.add(). Then push the tag on top of the stack for the currently displayed tab.
Be careful: when you want to push a new fragment on top of an old one, don't remove() the old one, since the FragmentManager will consider it gone and it will be cleaned up. Be sure to detach() it, and then attach() it later. Only use remove() when you're permanently popping a Fragment, and only use add() the first time you want to show it.
Then, you'll have to add some relatively simple logic to your TabListener. When a tab is unselected, simply peek() at its stack and detatch() the associated Fragment. When a tab is selected, peek() at the top of that stack and attach() that fragment.
Lastly, you'll have to deal with Activity lifecycle quirks (like orientation changes). Persist your Map of Stacks as well as the currently selected tab, and unpack it again in your onCreate(). (You don't get this packing and unpacking for free, but it's pretty easy to do.) Luckily your TabType enum is Serializable so it should be trivial to put into a Bundle.

Categories

Resources