I am trying to add fragments to the backstack but it is not working, I keep getting a: java.lang.IllegalStateException: This FragmentTransaction is not allowed to be added to the back stack.
I am using actionbar sherlock and in my main activity, i listen for the tabs
private class MyTabListener implements ActionBar.TabListener{
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft){
//to hide keyboard
final InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(myView.getWindowToken(), 0);
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
if(tab.equals(tabData))
{
ft.setCustomAnimations(R.anim.animation_fragment_out, R.anim.animation_fragment_switch);
ft.replace(android.R.id.content, dataFrag);
imm.hideSoftInputFromWindow(myView.getWindowToken(), 0);
//ft.setTransition(R.anim.animation_fragment_switch);
curTab = tabData;
ft.addToBackStack(null);
//ft.commit();
//ft.commit();
}
else if(tab.equals(tabComp))//new competition
{
ft.setCustomAnimations(R.anim.animation_fragment_out, R.anim.animation_fragment_switch);
ft.replace(android.R.id.content, teamsFrag);
//ft.setTransition(R.anim.animation_fragment_switch);
//ft.commit();
actionBar.removeTab(tabData);
actionBar.removeTab(tabComp);
actionBar.addTab(tabMatches);
actionBar.addTab(tabRed);
actionBar.addTab(tabBlue);
curTab = tabComp;
ft.addToBackStack(null);
}
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft){
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft){
}
}
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();
}
}
How can I attach existing fragment, when change back tab in ActionBar.NAVIGATION_MODE_TABS?
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.detach(fragment);
}
}
You can verify if your fragment was loaded previously in the fragment stack. Also could store all your used fragments to reuse it
public void setFragment(Fragment fragmentInstance) {
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
Fragment oldFragmentInstance = fragmentManager
.findFragmentById(R.id.curr_fragment);
boolean onlyAttach = false;
List<Fragment> prevFragments = getSupportFragmentManager()
.getFragments();
for (Fragment fragment : prevFragments) {
if (fragment == null) {
continue;
}
if (fragment.getClass().equals(fragmentInstance.getClass())) {
onlyAttach = true;
fragmentInstance = fragment;
break;
}
}
fragmentTransaction.detach(oldFragmentInstance);
if (onlyAttach) {
fragmentTransaction.attach(fragmentInstance);
} else {
fragmentTransaction.replace(R.id.curr_fragment,
fragmentInstance);
fragmentTransaction.addToBackStack(null);
}
try {
fragmentTransaction.commit();
}
}
Hope this helps
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 have 3 actionbar tabs home:video:purchase by default home will be selected.I can switch between different tabs where i'm able to replace the fragments.I have a gridview in home fragment on click of any grid cell i'm using the below piece of code to navigate to purchase tab,i'm able to replace the home fragment with purchase fragment but how can change the actionbar tab from home tab to purchase tab?????
FragmentTransaction ft = parentActivity
.getFragmentManager()
.beginTransaction();
ft.replace(R.id.mainLayout,new purchase());
ft.commit();
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (fragment != null) {
ft.setCustomAnimations(R.animator.fragmentanimatorleft,
R.animator.fragmentanimatorright);
ft.replace(R.id.mainLayout, fragment);
// isSettingClicked = false;
}
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
if (fragment != null) {
try {
ft.remove(fragment);
} catch (Exception e) {
// TODO: handle exception
}
}
}
class MyTabsListener implements ActionBar.TabListener {
public Fragment fragment;
public MyTabsListener(Fragment fragment) {
this.fragment = fragment;
}
public void onTabReselected(Tab tab, FragmentTransaction ft) {
Toast.makeText(DashboardFragmentActivity.appContext, "Reselected!", Toast.LENGTH_LONG).show();
}
public void onTabSelected(Tab tab, FragmentTransaction ft) {
ft.replace(R.id.fragment_container, fragment);
}
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
ft.remove(fragment);
}
Is it possible instead to change Fragment to FragmentActivity? How would you implement this, I'm confuse about those two.
Fragments are always used in FragmentActivities, so you cannot replace a Fragment with a FragmentActivity, because nested activities are deprecated.
And you always have an option to use getActivity(); in the Fragments to get the parent Activity, so for whatever reason you wanted to replace Fragment with FragmentActivity it can be achieved with just Fragment.