My current Android application has two Fragments:-
ListFragment
Detailfragment
My Layout XML resembles:-
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_anchorGravity="bottom"
app:layout_behavior="#string/appbar_scrolling_view_behavior">
</FrameLayout>
I display the ListFragment first as follows:-
final FragmentManager fragmentManager = getFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(containerId, mListFragment, LIST_FRAGMENT_TAG);
if (mLandscape) {
} else {
fragmentTransaction.addToBackStack(LIST_FRAGMENT_TAG);
}
fragmentTransaction.commit();
When the user clicks on a List item, I want to hide the List so that I keep the current list position etc.. and display the detailFragment.
Heres the code I use to perform this UI change:-
mDetailFragment = new DetailFragment();
final Bundle fragmentArguments = new Bundle();
fragmentArguments.putString(ITEM_KEY, item.getKey());
mDetailFragment.setArguments(fragmentArguments);
final FragmentManager fragmentManager = getFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (mLandscape) {
fragmentTransaction.replace(containerId, mDetailFragment, DETAIL_FRAGMENT_TAG);
} else {
fragmentTransaction.hide(mListFragment);
fragmentTransaction.add(containerId, mDetailFragment, DETAIL_FRAGMENT_TAG);
}
fragmentTransaction.commit();
The above code all works fine and I can transition between the List and Detail Fragments successfully.
The issue I have is that when the user presses the BACK BUTTON on the detail Fragment to return to the ListFragment they return to a blank screen.
I have this code in my Activity to remove the detail fragment and show the hidden List fragment:-
#Override
public void onBackPressed() {
if (mLandscape) {
} else {
if (mListFragment.isHidden()) {
final FragmentManager fragmentManager = getFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.remove(mDetailFragment);
fragmentTransaction.show(mListFragment);
fragmentTransaction.commit();
}
}
super.onBackPressed();
}
Why is fragmentTransaction.show(mListFragment); not showing the hidden ListFragment?
NOTE: So that I always rebuild my ui completely on orientation changes I have passed a null bundle to super.onCreate(savedInstanceStateNull);
private final Bundle savedInstanceStateNull = null;
private boolean mLandscape = false;
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceStateNull);
setContentView(R.layout.activity_article_list);
mLandscape = getResources().getBoolean(R.bool.landscape);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
manageFragments();
}
Heres how I fixed this issue:-
First remove my overriden onBackPressed()
Change display ListFragment to this:-
final FragmentManager fragmentManager = getFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(containerId, mListFragment, LIST_FRAGMENT_TAG);
fragmentTransaction.commit();
Change display detailFragment to this:-
mDetailFragment = new DetailFragment();
final Bundle fragmentArguments = new Bundle();
fragmentArguments.putString(ITEM_KEY, item.getKey());
mDetailFragment.setArguments(fragmentArguments);
final FragmentManager fragmentManager = getFragmentManager();
final FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (mLandscape) {
fragmentTransaction.replace(containerId, mDetailFragment, DETAIL_FRAGMENT_TAG);
} else {
fragmentTransaction.hide(mListFragment);
fragmentTransaction.add(containerId, mDetailFragment, DETAIL_FRAGMENT_TAG);
fragmentTransaction.addToBackStack(DETAIL_FRAGMENT_TAG);
}
fragmentTransaction.commit();
Related
I'm using a navigation bottom with 5 fragments.
Each fragment makes HTTP call and downloads content, but while replacing the fragment the view is destroyed and downloads it again.
In my search I found out that I should use setOffscreenPageLimit this method
but I don't use viewpager.
How could I implement something like that?
Instead of replacing fragments, add fragments to the fragment manager and show/hide them.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_page);
addFragmentsToManager();
}
private void addFragmentsToManager() {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.fade_in, R.anim.fade_out);
fragmentTransaction.add(R.id.flContent, tripFragment,
tripFragment.getClass().getSimpleName());
fragmentTransaction.add(R.id.flContent, notificationFragment,
notificationFragment.getClass().getSimpleName());
fragmentTransaction.add(R.id.flContent, searchFragment,
searchFragment.getClass().getSimpleName());
fragmentTransaction.add(R.id.flContent, profileFragment,
profileFragment.getClass().getSimpleName());
fragmentTransaction.hide(tripFragment);
fragmentTransaction.hide(notificationFragment);
fragmentTransaction.hide(searchFragment);
fragmentTransaction.hide(profileFragment);
fragmentTransaction.commit();
}
private void changeTab(int position) {
Fragment fragment;
switch (position) {
fragment = .....// get framgnet from position
}
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.anim.fade_in,
R.anim.fade_out);
fragmentTransaction.hide(prvFragment);
fragmentTransaction.show(fragment).commit();
prvFragment = fragment;
}
I am trying to attach a Fragment to my MainActivity programmatically by using the following code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MainFragment fragment = new MainFragment();
fragmentTransaction.add(R.id.activity_main,fragment);
fragmentTransaction.commit();
}
it gives me an error: cannot resolve add method
The application can be found here
Replace your code:
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
MainFragment fragment = new MainFragment();
fragmentTransaction.add(R.id.activity_main,fragment);
fragmentTransaction.commit();
By this:
Fragment fragment = new MainFragment();
getSupportFragmentManager.begintransaction.replace(R.id.container,fragment).commit;
first of all your take framelayout in activity_main.after that
fragmentTransaction.add(R.id.framelayout_id,fragment);
than its working fine
Make a function like that
public void openFragment(Fragment fragment) {
FragmentManager manager = getSupportFragmentManager();
manager.beginTransaction().replace(R.id.fragmentContainer, fragment).commit();
}
and call this in your onCreate Method
openFragment(new yourFragment());
In your beginTransaction().replace method you have to pass the view from which you want to replace your fragment with
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 two Fragments - FragmentA and FragmentB.
I try to show FragmentB from FragmentA.
FragmentB fragmentB = new FragmentB();
MainActivity activity = (MainActivity) getActivity();
int fragmentContainer = activity.getFragmentContainer();
FragmentTransaction fragmentTransaction = activity.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(fragmentContainer, fragmentB);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
MainActivity
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
fragmentA = new FragmentA(getSupportFragmentManager());
//...
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.add(FRAGMENT_CONTAINER,fragmentA);
fragmentTransaction.commit();
}
FragmentB is showed, but when i click on back button i have a next situation - FragmentB was dismissed, but FragmentA not showed.
Why this happens and what i need to edit to get a correct result?
getActivity().getChildFragmentManager().beginTransaction();
use this it may be works inside fragmentB
Thanks to New Developer for provided link.
All that we need it's just add a
#Override
public void onBackPressed(){
if (getSupportFragmentManager().getBackStackEntryCount() == 1){
finish();
}
else {
super.onBackPressed();
}
}
and
private void replaceFragment (Fragment fragment){
String backStateName = fragment.getClass().getName();
String fragmentTag = backStateName;
FragmentManager manager = getSupportFragmentManager();
boolean fragmentPopped = manager.popBackStackImmediate (backStateName, 0);
if (!fragmentPopped && manager.findFragmentByTag(fragmentTag) == null){ //fragment not in back stack, create it.
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.content_frame, fragment, fragmentTag);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(backStateName);
ft.commit();
}
}
and manage fragments in activity.
So if we need a swap fragments just call :
replaceFragment(new MySwappingFragment());
I am new to android working first time on fragment.I am creating an app in which I want to add a fragment on frame layout.I am able to do this but now what I want is to remove the same fragment which i added by that same button click I tried but couldn't. here is my code.
public void onClick(View v) {
android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
if(v.getId() == R.id.clickme){
if(getSupportFragmentManager().findFragmentById(R.layout.fragment_one) != null){
// getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentById(R.layout.fragment_one)).commit();
Fragment fragment = new FragmenOne();
fragmentManager.beginTransaction().remove(fragment).commit();
}else{
Fragment fragment = new FragmenOne();
// android.support.v4.app.FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.my_frame, fragment)
.commit();
}
}
}
You need to do in this manner
Fragment f = fragmentManager.findFragmentById(R.id.my_frame);
if(f instanceof FragmenOne) {
FragmenOne oneFragment = (FragmenOne) f;
FragmentTransaction trans = manager.beginTransaction();
trans.remove(oneFragment);
trans.commit();
fragmentManager.popBackStack();
}else{
Fragment fragment = new FragmenOne();
fragmentManager.beginTransaction()
.replace(R.id.my_frame, fragment)
.commit();
}