Fragments: Remove all fragments in a view

后端 未结 5 678
终归单人心
终归单人心 2020-12-16 17:25

The scenario I am faced with, is in my application I have a single pane and dual pane style layout. Rather than individually handle every single navigation

相关标签:
5条回答
  • 2020-12-16 17:52

    This is more or less how I have handled this. Have all your fragments implement an interface something like:

    public interface NamedFragment{
    
        public FragmentName getFragmentName();
    
    }
    

    Make an enum corresponding to your fragments:

    public enum FragmentName{
    
        SOME_FRAGMENT,
        SOME_OTHER_FRAGMENT;
    
    }
    

    Then in your fragment switching activity:

    // Get the manager and transaction separately so you can use both: 
        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction ft = fragmentManager.beginTransaction();
    
    // Get a reference to the fragment(s) currently in the container(s)
        Fragment currentFragment = fragmentManager.findFragmentById(position);
    
        FragmentName cFragmentName =
                ((NamedFragment) currentFragment).getFragmentName();
        Fragment nextFragment =
                Fragment.instantiate(this, some_new_fragment_string);
        FragmentName nFragmentName =
                ((NamedFragment) nextFragment).getFragmentName();
    // Compare the "names"
        if(cFragmentName != nFragmentName){
            ft.replace(position, nextFragment);
        }
    

    You'll have to change things around a little to fit your particulars.

    0 讨论(0)
  • 2020-12-16 17:55

    The typical mechanism is to use FragmentManager.findFragmentByTag() . You use this and add tags to your fragments (or the alternative for id's). This way you can determine what fragments are currently being managed. Then, once you have a handle to a present fragment (findFragmentByTag returns non-null), you can use FragmentManager.beginTransaction() to start a FragmentTransaction and remove / add the necessary fragments. Working in this way will allow you to avoid the 're-adding' process for the fragment you want to keep.

    What I'd probably do is have code like so: (warning psuedo code)

    Fragment pane1 = FragmentManager.findFragmentByTag("myFragmentPane1");
    Fragment pane2 = FragmentManager.findFragmentByTag("myFragmentPane2");
    
    setupScreen(pane1, pane2);
    

    You should also consider sub-classes of your class instead of having 'everything in one class'. You have a fairly obvious case of Martin Fowler's Replace Conditional with Subclass. Otherwise, I fear this is going to be incredibly hard to manager when you add another screen.

    0 讨论(0)
  • 2020-12-16 17:56

    Turns out FragmentTransaction.replace() is the correct operation and should work correctly. It only does not work when using ActionBarSherlock and SherlockFragmentActivity so I can only assume it is a bug in this compatibility library.

    I have confirmed this through using the code below to implement the desired behaviour through Android on API11+, the android compatibility library, and ActionBarSherlock. It only breaks in the last instance.

    package com.test.test;
    
    import com.actionbarsherlock.app.SherlockFragmentActivity;
    
    import android.os.Bundle;
    import android.content.Context;
    import android.graphics.Color;
    import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;
    import android.view.Gravity;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.ViewGroup;
    import android.widget.Button;
    import android.widget.FrameLayout;
    import android.widget.LinearLayout;
    import android.widget.LinearLayout.LayoutParams;
    import android.widget.TextView;
    
    public class MainActivity extends SherlockFragmentActivity {
      // Consistent fragment instance
        myFragment myFrag = null;
    
        // Views
        FrameLayout fl = null;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            LinearLayout ll = new LinearLayout(this);
            ll.setOrientation(LinearLayout.VERTICAL);
    
            Button b = new Button(this);
            b.setText("Repeat");
            b.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    // Reattach the same fragment
                    getSupportFragmentManager().beginTransaction().replace(fl.getId(), myFrag).commit();
    
                }
            });
    
            fl = new FrameLayout(this);
            fl.setId(200);
            fl.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
    
            myFrag = new myFragment();
            getSupportFragmentManager().beginTransaction().add(fl.getId(), myFrag).commit();
    
            ll.addView(b);
            ll.addView(fl);
    
            setContentView(ll);
        }
    
        public static class myFragment extends Fragment {
    
            @Override
            public View onCreateView(LayoutInflater inflater, ViewGroup container,
                    Bundle savedInstanceState) {
                TextView tv = new TextView(getActivity());
                tv.setText("My fragment");
                tv.setGravity(Gravity.CENTER);
                tv.setBackgroundColor(Color.RED);
    
                return tv;
            }
        }
    
    }
    
    0 讨论(0)
  • 2020-12-16 18:05

    If you use android.support.v4.app.Fragment you can do this:

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    if (fragments != null) {
        for (Fragment fragment : fragments) {
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        }
    }
    
    0 讨论(0)
  • 2020-12-16 18:09

    None of the other answers were really working for me. Here's what I did:

    List<Fragment> al = getSupportFragmentManager().getFragments();
    if (al == null) {
       // code that handles no existing fragments
       return;
    }
    
    for (Fragment frag : al)
    {
       // To save any of the fragments, add this check.
       // A tag can be added as a third parameter to the fragment when you commit it
       if (frag == null || frag.getTag().equals("<tag-name>")) {
          continue;
       }
    
       getSupportFragmentManager().beginTransaction().remove(frag).commit(); 
    }
    

    or, if you're forced to use it (but not recommended):

    .commitAllowingStateLoss();
    

    Also, if you're removing all fragments from the view multiple times, you might consider checking if the current frag is null or isDetached() or isRemoving() or you might get NullPointerExceptions.

    Update: The documentation for getSupportFragmentManger().getFragments() is apparently hidden now, but still works just fine in my code. Here's the screenshot of the documentation:

    enter image description here

    Having said that, since it is hidden, they no longer want this method used, so see my update below.

    Update 8-4-15: If you're not using the support library for fragments, there is unfortunately no getFragments() available, but there are still a couple, more inconvenient, options.

    1. Give each fragment a tag or id upon creation, and iterate through them to process each fragment as desired.
    2. Create a listener using onAttachListener so each time a new fragment is attached to the activity, you can store that fragment, and then iterate through that data structure to process each fragment as desired.

    When not using the getSupportFragmentManager(), to process a transaction you will need to use getFragmentManager() instead.

    0 讨论(0)
提交回复
热议问题