all!
I have 2 fragments. First one appears at start, second one adds with button "Add", using the same container.I am trying to add fragment to the back stack with method addToBackStack, but when I click "back-button" my app hides instead of showing me the first fragment. What is wrong?
public class MainActivity extends AppCompatActivity {
FirstFragment fragment1;
SecondFragment fragment2;
FragmentTransaction fragmentTransaction;
FragmentManager fm;
Button add;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
fragment1 = new FirstFragment();
fragment2 = new SecondFragment();
add = (Button) findViewById(R.id.add);
fm = getFragmentManager();
fragmentTransaction = fm.beginTransaction();
fragmentTransaction.add(R.id.container, new FirstFragment());
fragmentTransaction.commit();
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
fragmentTransaction = fm.beginTransaction();
fragmentTransaction.replace(R.id.container, new SecondFragment());
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
}
}
addToBackStack() on fragment transaction is not enough, we have to handle the popping up of the back stack upon Back button pressed by ourselves.
#Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0 ){
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
Related
I have 3 fragment fragmentA, fragmentB, fragmentC that are added by default on the activity on create to keep it instance after that, I have another fragment fragmentX that to be added on the fragment container with backStack on Button click, the fragmentX is shown on add but when I need to show it again its not working.
public class MainActivity extends ActivityBaseClass {
private Fragment fragmentA;
private Fragment fragmentB;
private Fragment fragmentC;
private Fragment fragmentX;
#BindView(R.id.btn_show_fragmentx)
Button mBtnShowFragmentX;
#BindView(R.id.tab_layout)
TabLayout mTab;
private FragmentTransaction transaction;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
fragmentA = FragmentA.newInstance();
fragmentB = FragmentB.newInstance();
fragmentC = FragmentC.newInstance();
transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fragment_container, fragmentA, "A");
transaction.add(R.id.fragment_container, fragmentB, "B");
transaction.add(R.id.fragment_container, fragmentC, "C");
transaction.commit();
mTab.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
transaction = getSupportFragmentManager().beginTransaction();
switch (tab.getPosition()) {
case 0:
transaction.show(fragmentA);
transaction.hide(fragmentB);
transaction.hide(fragmentC);
break;
case 1:
transaction.show(fragmentB);
transaction.hide(fragmentA);
transaction.hide(fragmentC);
break;
case 2:
transaction.show(fragmentC);
transaction.hide(fragmentA);
transaction.hide(fragmentB);
break;
}
transaction.commit();
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
#OnClick(R.id.btn_show_fragmentx)
public void showFragmentX() {
if (fragmentX == null) {
fragmentX = FragmentX.newInstance();
transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.fragment_container, fragmentX, "X");
transaction.addToBackStack("X");
transaction.commit();
} else {
transaction = getSupportFragmentManager().beginTransaction();
transaction.show(fragmentX);
transaction.addToBackStack("X");
transaction.commit();
}
}
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
transaction = getSupportFragmentManager().beginTransaction();
transaction.hide(fragment);
transaction.commit();
getSupportFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
}
You fragmentX is destroyed when onBackPressed is called. You need to check for the backstack's current fragment, if it is an instance of FragmentX, then hide it (and don't pop the backstack), otherwise do your code.
ImageButton imageButton3 =(ImageButton)view.findViewById(R.id.item_two_timer_id);
imageButton3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getFragmentManager().beginTransaction()
.replace(R.id.container2_main , new TimerFragment2())
.addToBackStack(null)
.commit();
While adding fragment add a tag to identify it.get the fragment by tag and see if the fragment is present.If it is not present create a new Instance and add it.
ImageButton imageButton3 = (ImageButton) view.findViewById(R.id.item_two_timer_id);
imageButton3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TimerFragment2 timerFragment2;
timerFragment2 = (TimerFragment2) getFragmentManager().findFragmentByTag(TimerFragment2.class.getSimpleName());
if(timerFragment2==null){
timerFragment2=new TimerFragment2();
getFragmentManager().beginTransaction()
.replace(R.id.container2_main, timerFragment2,TimerFragment2.class.getSimpleName())
.addToBackStack(TimerFragment2.class.getSimpleName())
.commit();
}else {
//Dont create fragment again
}
}
});
please try this code if you are setting one fragment
private void initFragment() {
SelectTypeFragment fragment = new SelectTypeFragment();
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right); //if you want to set animation
fragmentTransaction.replace(R.id.fl_addvehicle, fragment);
fragmentTransaction.commit();
}
if you are replacing one fragment to with another.
void goToNextFragment() {
((CreateOfferActivity) this.getActivity()).setCreateOfferModel(createOfferModel);
SelectVehicleFragment fragment = new SelectVehicleFragment();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left, R.anim.enter_from_left, R.anim.exit_to_right);
fragmentTransaction.replace(R.id.fl_create_offer, fragment).
addToBackStack("select_vehicle");
fragmentTransaction.commit();
}
You can check it in Fragment but first,
You need to create an object of Fragment TimerFragment2 and check if it's visible or not in timerFragment.isVisible()
ImageButton imageButton3 =(ImageButton)view.findViewById(R.id.item_two_timer_id);
TimerFragment2 timerFragment = new TimerFragment2();
imageButton3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(!timerFragment.isVisible())
getFragmentManager().beginTransaction()
.replace(R.id.container2_main , timerFragment)
.addToBackStack(null)
.commit();
I have a Navigation drawer activity and it contains couple of Fragments. My problem is I want to call the Navigation drawer activity class in button click which should have fragment B, by default navigation drawer has fragment A.
I am posting my code here:
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity(new Intent(getApplicationContext(),Navigation.class));
FragmentTransaction tx = getSupportFragmentManager().beginTransaction();
tx.replace(R.id.content_frame, new FragmentB());
tx.commit();
finish();
}
});
Where content_frame is the area were I want to replace fragment B view..
try this approach
in your button click send extra data to check what fragment you need
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), Navigation.class);
intent.putExtra("SELECTEDVALUE", 2);//1 for fragament A use 2 for fragment B
startActivity(intent);
}
});
Now, in your oncreate() method of Navigation Activity
Bundle extras = savedInstanceState != null ? savedInstanceState : getIntent().getExtras();
int selectedValue = extras.getInt("SELECTEDVALUE");
switch (selectedValue) {
case 1:
goToFragment(new A(), false);
break;
case 2:
goToFragment(new B(), false);
break;
finally gotoFragment is...
private void goToFragment(Fragment fragment, boolean addToBackStack) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (addToBackStack) {
transaction.addToBackStack(null);
}
transaction.replace(R.id.container, fragment).commit();
}
Try below code;
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment fragment = new FragmentB();
FragmentManager fm =getActivity().getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.content_frame, fragment);
ft.commit();
}
});
Just make an instance of FragmentB like this
FragmentB fragment - new FragmentB();
and then pass it like this .
tx.replace(R.id.content_frame, fragment);
tx.commit();
now you can access all the variables and methods of fragment from your activity using instance fragment. like this fragment.methodName();
Try this code:
back.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
getActivity().getSupportFragmentManager().beginTransaction()
.add(R.id.content_frame, new FragmentB(), "fragmentB").addToBackStack(null).commit();
}
});
hope it'll solve your problem.
I am making a simple demo project using Fragments, in which i am calling SecondFragment from FirstFragment on button click.
And i called SecondFragment without any issue, but i getting view of both the Fragments SecondFragment and FirstFragment
So where i am doing mistake ?
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new FirstFragment()).commit();
}
}
public static class FirstFragment extends Fragment {
Button buttonCallSecondFragment;
public FirstFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_first, container,
false);
buttonCallSecondFragment = (Button) rootView.findViewById(R.id.button1);
buttonCallSecondFragment.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
FragmentManager fm = getFragmentManager();
SecondFragment fragment = new SecondFragment();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.container, fragment);
ft.commit();
}
});
return rootView;
}
}
public static class SecondFragment extends Fragment {
public SecondFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_second, container,
false);
return rootView;
}
}
}
You need to remove the first fragment, you can do that either by usingreplace or first calling remove then add
To be able to press the back button add the transaction to the back stack,you do that by calling addToBackStack(tag) on your fragment manager. Tag may be null.
You are adding fragment on already displaying fragment in your android app.
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.container, fragment);
ft.commit();
Do not add fragment but replace fragment when already one fragment is loaded on activity.
So for implementing that :
Please add your code in OnCreate() and add below code to your click listener :
FragmentManager fm = getFragmentManager();
SecondFragment fragment = new SecondFragment();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, fragment);
ft.addToBackStack(null);
ft.commit();
Thank you.!!
if you want to replace fragment you should call replace in place of add :
buttonCallSecondFragment = (Button) rootView.findViewById(R.id.button1);
buttonCallSecondFragment.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
FragmentManager fm = getFragmentManager();
SecondFragment fragment = new SecondFragment();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.container, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
}
});
You are adding the fragment so it will come on top of another fragment give background color to rootview of scecond fragment
you can also load that as Nested fragment
public void addFragB() {
FragmentManager childFragMan = getChildFragmentManager();
FragmentTransaction childFragTrans = childFragMan.beginTransaction();
SecondFragment 2ndfrag = new SecondFragment();
childFragTrans.add(R.id.fragA_LinearLayout, 2ndfrag);
//childFragTrans.addToBackStack("");
childFragTrans.commit();
}
No, you cannot communicate between fragments like this. You need to communicate between fragments via the container activity.
I suggest, you make a navigation method in your activity and switch/call between fragments from there.
Below is a small snippet:
In your container activity:
Fragment fragment;
public void navigateTo(Fragment newFragment,boolean addToBackStack) {
this.fragment = newFragment;
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.fragment_container, newFragment);
if(addToBackStack)
ft.addToBackStack(fragment.getClass().getSimpleName());
ft.commit();
}
If you are going from Fragment1 to Fragment2 then in your Fragment1 do the following:
((YourContainerActivity) getActivity()).navigateTo(new Fragment2(),false); //if you want to add to back stack make 2nd argument true.
private void selectItem(int position) {
selectedPosition = position;
// update the main content by replacing fragments
fragment = null;
fragmentStack = new Stack<Fragment>();
switch (position) {
case 0:
fragment = new Fragment1();
break;
case 1:
fragment = new Fragment2();
break;
}
//redirect the screen
if (fragment != null) {
fragmentManager = getSupportFragmentManager();
redirectScreen(fragment);
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(title[position]);
mDrawerLayout.closeDrawer(mDrawerList);
}
}
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();
}