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.
Related
I have a Activity with four buttons at the bottom like tabs. By pressing any button a new Fragment is displayed in the FrameLayout above these buttons like we do in TabActivity. See My Problem here .Now i think i should find a way to hide and show those fragments. Kindly tell me how can i show and hide a fragment without reloading it again.
Main Purpose of showing hiding a fragment is to maintain its current state. In one of my fragment i have an AsyncTask whenever i switch between fragment it call that AsynTask again.
// to show fragment when it is hidden
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction()
.show(fragment1)
.commit();
// to hide fragment
FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction()
.hide(fragment1)
.commit();
you can't pass by some view like
declare 4 frameLayout
private FrameLayout fragment1;
private FrameLayout fragment2;
private FrameLayout fragment3;
private FrameLayout fragment4;
and
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment1, Fragment1.newInstance());
ft.replace(R.id.fragment2, Fragment2.newInstance());
ft.replace(R.id.fragment3, Fragment3.newInstance());
ft.replace(R.id.fragment4, Fragment4.newInstance());
ft.commit();
and play with visible or gone ? like
fragment1.setVisibility(View.Visible);
fragment2.setVisibility(View.gone);
fragment3.setVisibility(View.gone);
fragment4.setVisibility(View.gone);
and by the way : works for me ->
public class Activity extends ActionBarActivity {
private FrameLayout fragment1;
private FrameLayout fragment2;
private Button bt1;
private Button bt2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frg_test_frg);
fragment1 = (FrameLayout) findViewById(R.id.fragment1);
fragment2 = (FrameLayout) findViewById(R.id.fragment2);
bt1 = (Button) findViewById(R.id.button);
bt2 = (Button) findViewById(R.id.button2);
bt1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fragment1.setVisibility(View.VISIBLE);
fragment2.setVisibility(View.GONE);
}
});
bt2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fragment1.setVisibility(View.GONE);
fragment2.setVisibility(View.VISIBLE);
}
});
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.fragment1, new Fragment1());
ft.replace(R.id.fragment2, new Fragment2());
ft.commit();
}
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();
I'm pretty new to Fragments API and here's my question: let's say I have an Activity and an ActionBar with tabs. Suppose I want to start messaging application from my application and usually it will start as a new Activity. Is it possible to add the messaging Activity as a new tab to my Activity? How can I achieve this effect? Thanks in advance.
Inside your onCreate method do the following
Context context = getApplicationContext();
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 MsgTabsListener(PlayerFragment, context));
StationsTab.setTabListener(new MsgTabsListener(StationsFragment, context));
actionbar.addTab(PlayerTab);
actionbar.addTab(StationsTab);
Then add the class MsgTabListener and do the following
class MsgTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public Context context;
public MsgTabsListener(Fragment fragment, Context context) {
this.fragment = fragment;
this.context = context;
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
//Start a new activity here with respect to your main context.
context.StartActivity(new Intent(....));
}
#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);
}
If you are looking for good Fragements API tutorial then Lars Vogel has very nice explanations.
http://www.vogella.com/articles/Android/article.html#fragments_tutorial
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!:)