i have the following activity which produced 3 tabs, and put fragment in each one of them.
public class ClientActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_client);
ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab tabA = bar.newTab().setCustomView(R.layout.tab_a_layout);
ActionBar.Tab tabB = bar.newTab().setCustomView(R.layout.tab_b_layout);
ActionBar.Tab tabC = bar.newTab().setCustomView(R.layout.tab_c_layout);
Fragment fragmentA = new firstTab();
Fragment fragmentB = new secondTab();
Fragment fragmentC = new thirdTab();
tabA.setTabListener(new MyTabsListener(fragmentA));
tabB.setTabListener(new MyTabsListener(fragmentB));
tabC.setTabListener(new MyTabsListener(fragmentC));
bar.addTab(tabA);
bar.addTab(tabB);
bar.addTab(tabC);
}
protected class MyTabsListener implements ActionBar.TabListener {
private Fragment fragment;
public MyTabsListener(Fragment fragment)
{
this.fragment = fragment;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft)
{
ft.add(R.id.fragment_place, fragment, null);
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
}
}
in the first fragment (tabA) i have listview and listener which replacing the fragment on click.
when i am clicking on the second tab (after selecting line on the listview on tabA), the listener adding the tab instead of replacing it.
it happens because the TabUnsellected is removing the wrong fragment (it was first_tab, but replaced to test_tab on the listview selecting row).
how can i use the remove option on the ft on TabUnselected to remove the CURRENT fragment on the tab, assuming i have always 1 fragment on each tab?
Thanks
Fixed it by changing from ft.add to ft.replace on the TabSelected:
ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragment_place, fragment);
ft.commit();
Related
I want to create an activity that can display any number of tabs, without creating an activity for each tab.
Is it possible?
The only way I saw creating tabs included creating an activity for each one.
You can try as follows ,
Extend your activity from ActionBarActivity and add required number of tabs programmatically ,
ActionBar.TabListener tabListener;
mactionBar = getActionBar();
mactionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
tabListener=new ActionBar.TabListener() {
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
displayTabs(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
displayTabs(tab.getPosition());
}
};
mactionBar.addTab(mactionBar.newTab().setText(<any text>).setTabListener(tabListener));
//call the same method for required number of tabs
Call the same fragment for each tab click
private void displayTabs(int position)
{
Fragment fragment = null;
switch (position) {
case 0:
fragment = new YourFragment();
break;
case 1:
fragment = new YourFragment();
break;
// same for required numder of cases
default:
break;
}
if (fragment != null)
{
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().replace(<container id>, fragment).commit();
}
}
I put some tabs in the action bar with the following code. Everything looks fine. There are 5 tabs here. I coded each tab to open a new layout. But the problem is only the first tab works fine. Second tab opens the fifth layout and third, fouth, fifth tabs are not working. When I remove the fifth tab, then second tab opens the fourth layout and, other buttons are not woking, I couldn't silve this problem. Please help me. Thank you!
Here is my codings,
main class file;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
android.app.ActionBar actionbar = getActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_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
}
};
ActionBar.Tab baby = actionbar.newTab().setText("Baby")
.setTabListener(tabListener);
ActionBar.Tab books = actionbar.newTab().setText("Books")
.setTabListener(tabListener);
ActionBar.Tab electronics = actionbar.newTab().setText("Electronics")
.setTabListener(tabListener);
ActionBar.Tab health = actionbar.newTab().setText("Health and Beauty")
.setTabListener(tabListener);
ActionBar.Tab sports = actionbar.newTab().setText("Sports")
.setTabListener(tabListener);
Fragment babyFragment = new Baby();
Fragment booksFragment = new Books();
Fragment electronicsFragment = new Electronics();
Fragment healthFragment = new Health();
//Fragment sportsFragment = new Sports();
baby.setTabListener(new MyTabsListener(babyFragment));
books.setTabListener(new MyTabsListener(booksFragment));
books.setTabListener(new MyTabsListener(electronicsFragment));
books.setTabListener(new MyTabsListener(healthFragment));
//books.setTabListener(new MyTabsListener(sportsFragment));
actionbar.addTab(baby);
actionbar.addTab(books);
actionbar.addTab(electronics);
actionbar.addTab(health);
actionbar.addTab(sports);
}
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
}
every other other java file looks like this;
public class Baby extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.baby, container, false);
}
}
main xml file;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_gravity="center">
<LinearLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</LinearLayout>
</LinearLayout>
Pleease help me to solve this problem.
The error seems to be here:
baby.setTabListener(new MyTabsListener(babyFragment)); // OK
books.setTabListener(new MyTabsListener(booksFragment)); // OK
books.setTabListener(new MyTabsListener(electronicsFragment)); // !!
books.setTabListener(new MyTabsListener(healthFragment)); // !!
You are setting the different listeners to the same tab (that's why the "books" shows the "health" fragment, and the others do nothing).
How do I switch fragments inside a tab?
My application contains three fragments, AFragment, BFragment, and CFragment. These fragments, in turn, correspond to their own layout files: AFragment contains a Button, and BFragment and CFragment have TextView. There is a fourth layout file named activity_main.
Now, I have four classes, MainActivity, AFragment, BFragment and CFragment. The classes AFragment, BFragment, CFragment only the typical contain OnCreateView on each of them.
MainActivity contains this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
appContext = getApplicationContext();
//ActionBar
ActionBar actionbar = getActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab PlayerTab = actionbar.newTab().setText("Fragment A");
ActionBar.Tab StationsTab = actionbar.newTab().setText("Fragment B");
Fragment PlayerFragment = new AFragment();
Fragment StationsFragment = new BFragment();
PlayerTab.setTabListener(new MyTabsListener(PlayerFragment));
StationsTab.setTabListener(new MyTabsListener(StationsFragment));
actionbar.addTab(PlayerTab);
actionbar.addTab(StationsTab);
And then the TabListener:
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
Toast.makeText(MainActivity.appContext, "Reselected!", Toast.LENGTH_LONG).show();
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
}
As you can see, activity_main.xml only contains a LinearLayout with an id 'fragment_container' for tabs AFragment and BFragment. Now I want it in such a way that clicking a button in AFragment switches the entire AFragment to CFragment. How can I achieve this? Thank you.
(EDIT) I did the following but my app crashed on start. What did I do wrong?
I added the following on my MainActivity.java, just below the ActionBar sequence:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
appContext = getApplicationContext();
//ActionBar
....
....
....
Button mButton = (Button) findViewById(R.id.button1);
mButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
CFragment fragment = new CFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
}
});
get a fragment transaction using the (support) fragment manager of your activity.
replace AFragment by CFragment as you did in onTabSelected
commit your transaction.
Also, please note :
don't keep references on your fragment, you actually prevent garbage collection from occuring. You should create your fragments once, not every time. In TabSelected, check if the fragment is known by the fragment manager (using findFragmentByTag). If not, create it. If it is, just re-replace it.
share your listener, you don't need one by tab.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
how to Keep Tabhost when start other activity
I am trying to launch new activity from "tab1", but the activity opens on whole screen. I need to open the new activity in the tab which fired the intent .
Use this code for actionbar and set activity in fragment in tab.
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
appContext = getApplicationContext();
//ActionBar
ActionBar actionbar = getActionBar();
actionbar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.Tab PlayerTab = actionbar.newTab().setText("Fragment A");
ActionBar.Tab StationsTab = actionbar.newTab().setText("Fragment B");
Fragment PlayerFragment = new AFragment();
Fragment StationsFragment = new BFragment();
PlayerTab.setTabListener(new MyTabsListener(PlayerFragment));
StationsTab.setTabListener(new MyTabsListener(StationsFragment));
actionbar.addTab(PlayerTab);
actionbar.addTab(StationsTab);
and put this class for tab.
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
Toast.makeText(StartActivity.appContext, "Reselected!", Toast.LENGTH_LONG).show();
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
Hope its useful for you.
thanks..
You can implement it in two ways, either:
Set contents of Tabs as ActivityGroup not activity, and change view of ActivityGroup according to navigation.
TabGroupActivity - startChildActivity - not working
But ActivityGroup is deprecated, so I would suggest to use second method.
Use fragments to Implement TabBar.
http://android.codeandmagic.org/2011/07/android-tabs-with-fragments/
I am wondering if this can be done. Basically I have a layout with 2 fragments in it that I use for most of my tabs but on 2 of the tabs I want to add a couple more fragments to display more things. Is it possible to change the content view to a different layout when changing tabs?
If that cant be done I thought about creating a layout with all the fragment parts that I would need and just changing the layouts of the fragments so the ones I dont use wont "show". I dont mean using FragmentTransaction.hide() because I want the fragments to fill the screen when others are not used. Would that be a bad idea or is there an easier way to do what I want?
here is my code for the activity and tabs
public class Tabs extends Activity{
long deleteID;
#Override
public void onCreate(Bundle create){
super.onCreate(create);
setContentView(R.layout.main_layout);
createTabs();
ActionBar bar = getActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.setDisplayHomeAsUpEnabled(true);
if(create != null){
bar.setSelectedNavigationItem(create.getInt("Home",0));
}
}
I also add tabs a whatnot but thats not important
this is the actionbar subclass
private class TabListener implements ActionBar.TabListener{
TabContent mFragment;
public TabListener(TabContent fragment) {
mFragment = fragment;
}
#Override
public void onTabReselected(Tab tab, android.app.FragmentTransaction ft) {
}
#Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
ListFragment newListFragment = new BowlersListFragment();
Fragment newFragment = new BowlerEntryFrag();
ft = getFragmentManager().beginTransaction();
ft.replace(R.id.frameOne, newListFragment);
ft.replace(R.id.frameTwo, newFragment);
ft.addToBackStack(null);
ft.commit();
}
#Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
if(ft != null){
ft.remove(mFragment);
}
}
}
}
I tried doing Activity.setContentView(r.layout.newView) but that won't work
I had similar problem, so implemented it like this. I have a mainActivity that holds and creates the tabs. That activity uses a layout with one fragment container, main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:orientation="vertical" >
<LinearLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
In my activity I have the following code for creating the tabs and fragments:
historyTab = actionbar.newTab().setText("History");
historyTab.setTabListener(new MyTabsListener(new HistoryFragment()));
actionbar.addTab(historyTab);
My tabListener looks something like this:
private class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
private boolean isFragmentAdded = false;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabSelected(Tab tab, android.app.FragmentTransaction ft) {
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xaction = fragMgr.beginTransaction();
if (fragment instanceof HistoryFragment) {
fragment = new HistoryFragment();
xaction.add(R.id.fragment_container, fragment);
} else if (fragment instanceof .. some other fragment..) {
fragment = new .. some other fragment();
xaction.add(R.id.fragment_container, fragment);
}
}
xaction.commit();
}
#Override
public void onTabUnselected(Tab tab, android.app.FragmentTransaction ft) {
FragmentManager fragMgr = getSupportFragmentManager();
FragmentTransaction xaction;
xaction = fragMgr.beginTransaction();
Fragment fragment = fragMgr.findFragmentById(R.id.fragment_container);
xaction.remove(fragment);
xaction.commit();
}
}
The layout for the History fragment in my example, can be anything, even a layout that contains two fragments, or as much you need. Just be careful, and in onCreateview method in the fragment, use this:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
if (view == null) { // this line is very important!
view = inflater.inflate(R.layout.history_fragment_layout, container, false);
listView = (ListView) view.findViewById(R.id.historyList);
}
return view;
}
Hope that helps!:)