简体   繁体   中英

Replace a fragment above another fragment when dialog is clicked (viewpager)

I am trying to open a fragment, when a dialog is clicked inside another fragment. I am using ActionBarSherlock with Tab. My fragment is attached in the view pager. I have almost done the job. But I can't replace a new fragment inside a view pager. I got an error. I read the thread here . The solution isn't clear.

Error:

10-18 21:34:40.379: E/AndroidRuntime(19618): FATAL EXCEPTION: main 10-18 21:34:40.379: E/AndroidRuntime(19618): java.lang.IllegalArgumentException: No view found for id 0x7f040032 (com.example.actionbartestwithsherlock:id/pager) for fragment AllContactsFragment{41fd4ba0 #0 id=0x7f040032} 10-18 21:34:40.379: E/AndroidRuntime(19618): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:903)

I have three fragment associates with pager named FragmentTab1,FragmentTab2 & FragmentTab3.

My MainActivity & FragmentAdapter looks like below:

  public class MainActivity extends SherlockFragmentActivity {

    ActionBar.Tab Tab1, Tab2, Tab3, Tab4;
    private Context context = this;
    // view pager
    // Declare Variables
    ActionBar actionBar;
    ViewPager mPager;
    Tab tab;
    FragmentAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // set application in portrait mode
        ActivityHelper.initialize(this);

        actionBar = getSupportActionBar();
        actionBar.setDisplayShowHomeEnabled(true);
        actionBar.setDisplayShowTitleEnabled(true);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        // Locate ViewPager in activity_main.xml
        mPager = (ViewPager) findViewById(R.id.pager);
        // add an adapter to pager
        mPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(),
                mPager, actionBar));

        addActionBarTabs();
    }

    private void addActionBarTabs() {

        String[] tabs = { "Tab 1", "Tab 2", "Tab 3" };
        for (String tabTitle : tabs) {
            ActionBar.Tab tab = actionBar.newTab().setText(tabTitle)
                    .setTabListener(tabListener);
            actionBar.addTab(tab);
        }
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    }

    private ActionBar.TabListener tabListener = new ActionBar.TabListener() {
        @Override
        public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
            mPager.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
        }

        @Override
        public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
        }
    };

class FragmentAdapter extends FragmentPagerAdapter implements
            ViewPager.OnPageChangeListener {

        private ViewPager mViewPager;
        final int TOTAL_PAGES = 3;

        public FragmentAdapter(FragmentManager fm, ViewPager pager,
                ActionBar actionBar) {
            super(fm);
            this.mViewPager = pager;
            this.mViewPager.setOnPageChangeListener(this);
        }

        @Override
        public Fragment getItem(int position) {
            switch (position) {
            case 0:
                return FragmentTab1.newInstance();
            case 1:
                return FragmentTab2.newInstance();
            case 2:
                return FragmentTab3.newInstance();
            default:
                throw new IllegalArgumentException(
                        "The item position should be less or equal to:"
                                + TOTAL_PAGES);
            }
        }

        @Override
        public int getCount() {
            return TOTAL_PAGES;
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {

        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {

        }

        @Override
        public void onPageSelected(int position) {
            actionBar.setSelectedNavigationItem(position);
        }
    }
}

Now, Inside my first tab FragmentTab1 , I open a customized dialog when a button clicks. I want to replace new fragment AllContactsFragment in FragmentTab1 when the dialog options are selected.

FragmentTab1 fragment class:

public class FragmentTab1 extends SherlockFragment implements OnClickListener {

Button btnTest;
ViewPager pager;
LinearLayout layoutBlockNumbers;
LinearLayout layoutContact, layoutCallLog, layoutSMSLog, layoutManually;
Context context;
CustomizedDialog dialog;
private static final int CONTACT_PICKER_RESULT = 1001;
private static final String DEBUG_TAG = "Contact List";
private static final double RESULT_OK = -1;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragmenttab1, container,
            false);

    layoutBlockNumbers = (LinearLayout) rootView
            .findViewById(R.id.layoutAddBlockNumbers);
    layoutBlockNumbers.setOnClickListener(this);
    return rootView;

}

@Override
public void onClick(View v) {

    if (v == layoutCallLog) {

        dialog.dismiss();
        // want to replace new fragment at position 0 in pager
        // problem is here ??? how to open new fragmnet
        Fragment allContactsFragment = AllContactsFragment.newInstance();
        FragmentTransaction transaction = getChildFragmentManager()
                .beginTransaction();
        transaction.addToBackStack(null);
        transaction.replace(R.id.pager, allContactsFragment).commit();

    }

    if (v == layoutBlockNumbers) {
        // open a dialog
        showDialog();
    } else if (v == layoutContact) {
        openContactList();
        dialog.dismiss();
    } else if (v == layoutSMSLog) {
    }
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    setUserVisibleHint(true);
}

// open a dialog
private void showDialog() {
    dialog = new CustomizedDialog(getActivity());
    dialog.setContentView(R.layout.dialog_add_number_type);
    dialog.setTitle("Add Black List Number");

    //initialize all linear layouts in dialog
    layoutCallLog = (LinearLayout) dialog.findViewById(R.id.layoutCallLog);
    layoutContact = (LinearLayout) dialog.findViewById(R.id.layoutContact);
    layoutSMSLog = (LinearLayout) dialog.findViewById(R.id.layoutSMSLog);
    layoutManually = (LinearLayout) dialog
            .findViewById(R.id.layoutManually);

    // add listener to several linear layout
    layoutContact.setOnClickListener(this);
    layoutCallLog.setOnClickListener(this);
    layoutSMSLog.setOnClickListener(this);
    layoutManually.setOnClickListener(this);

    dialog.show();
}

public static Fragment newInstance() {
    Fragment f = new FragmentTab1();
    return f;
} 
}

activity_main.xml looks like below :

   <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    </android.support.v4.view.ViewPager>

</RelativeLayout>

Can anybody can help me to solve this issue? Sorry for the massive code.

I'm not sure you can do things the way you want to. A ViewPager is not set up the same way a normal container/fragment set up would be. In a ViewPager you're not using fragment transactions to add fragments but rather an adapter that loads instances of fragments from a backing list.

Replacing the fragment would then work as follows:

(1) Create an instance of the fragment you want to add (2) Add that fragment to the list that is backing your PagerAdapter (3) Display the new fragment (4) Remove the old one

The problem with implementing this in your current project is the set up of your adapter. Currently you are using a switch statment that can only return a fixed number of fragments. Your adapter should be set up something like this.

class MyPageAdapter extends FragmentPagerAdapter{
    private List<Fragment> fragments  
    public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) { 
        super(fm); 
        this.fragments = fragments; 
    } 

    @Override  
    public Fragment getItem(int position) { 
        return this.fragments.get(position);   
    }   

    @Override   
    public int getCount() {     
        return this.fragments.size(); 
    } 
}

Then you can just add a method to your adapter class to add or remove new fragments. If you know the index of the fragment you want to replace accomplishing this should be pretty easy. All you have to do is create a new instance of the contacts fragment, add it to your array or list. This Post explains how a ViewPager handles the adding/removing of new content and how to ensure your new fragment is displayed.

After I read this post I solved the answer.

I just add an ID android:id="@+id/fragmentTabLayout1 to top layout of my fragmenttab1.xml . Then call new fragment as usual:

    Fragment allContactsFragment = AllContactsFragment.newInstance();
        FragmentTransaction transaction = getChildFragmentManager()
                .beginTransaction();
        transaction.addToBackStack(null);
        // use this id to replace new fragment
        transaction.replace(R.id.fragmentTabLayout1, allContactsFragment).commit();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM