0

我正在使用带有抽屉布局的活动,我需要在不同的片段之间切换。这些片段之一是使用带有 FragmentStateViewPagerAdapter 的 ViewPager,我需要使用它来实现不同 PreferenceFragment 之间的滑动视图行为。一开始一切正常:我启动应用程序,第一个片段正确显示(不使用 ViewPager 的片段)。即使使用滑动抽屉移动到第二个片段(ViewPager 的片段)也可以。但是,如果我回到第一个 Fragment 并尝试再次打开第二个 Fragment,我得到的只是一个空白屏幕!它仍然在操作栏中显示选项卡,并且 ViewPager 仍在工作,但片段只是......空白。此外,滑动页面我可以注意到第二个 Fragment 仍然是空白的,而第三个和以下的正确加载。这样做之后,我还注意到向后滑动也会使两个不可见的页面正确加载。我没有得到任何异常,除此之外,一切似乎都以正确的方式工作。有谁知道可能导致此问题的原因?我遵循了 Android 开发者教程,包括 DrawerLayout 和 ViewPager。

这是我的代码:

主要活动:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        homeFragment = new HomeFragment();
        swypeFragment = new SwypeTabsPreferences();


        mTitle = mDrawerTitle = getTitle();
        mSections = getResources().getStringArray(R.array.sections_array);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        //set a custom shadow that overlays the main content when the drawer opens
        mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
        //set up the drawer's list view with items and click listener
        mDrawerList.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item,
                mSections));
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        //Enable ActionBar app icon to behave as action to toggle nav drawer
        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);

        //ActionBarDrawerToggle ties together the proper interactions between
        //the sliding drawer and the action bar app icon
        mDrawerToggle = new ActionBarDrawerToggle(
                this,                   /* host activity */
                mDrawerLayout,          /* DrawerLayout Object */
                R.drawable.ic_drawer,   /* nav Drawer image to replace 'Up' caret */
                R.string.drawer_open,   /* "open drawer" description for accessibility */
                R.string.drawer_close   /* "close drawer description for accessibility */
                ) {
            public void onDrawerClosed(View view) {
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu(); //creates call to onPrepareOptionsMenu()
            }

            public void onDrawerOpened(View drawerView) {
                getActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu(); //Creates call to onPrepareOptionsMenu()
            }
        };
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        if (savedInstanceState == null) {
            selectItem(0);
        }



    }
    public void onDestroy() {
        super.onDestroy();
        Log.d("DEBUG", "In Method: onDestroy()");
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return super.onCreateOptionsMenu(menu);
    }

    /*Called whenever we call invalidateOptionsMenu() */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        //If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //The action bar home/up action open or close the drawer.
        //ActionBarDrawerToggle will take care of this.
        if (mDrawerToggle.onOptionsItemSelected(item)) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onResume() {
       super.onResume();
    }


    private class DrawerItemClickListener implements ListView.OnItemClickListener {

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            selectItem(position);
        }
    }

    // Swaps fragments in the main content view
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private void selectItem(int position) {
        //update the main content by replacing fragments
        if (position == 0) {
        //Fragment fragment = new HomeFragment();
        //fragment.setRetainInstance(true);

        FragmentManager fragmentManager = getFragmentManager();
        FragmentTransaction trans = fragmentManager.beginTransaction();
        if (null ==fragmentManager.findFragmentByTag("home")) {
            trans.replace(R.id.content_frame, homeFragment, "home");
        }
        trans.commit();
        //update selected item and title, then close the drawer
        mDrawerList.setItemChecked(position, true);
        setTitle(mSections[position]);
        mDrawerLayout.closeDrawer(mDrawerList);
        }
        else if (position == 1) {
            //Fragment fragment = new SwypeTabsPreferences();
            //fragment.setRetainInstance(true);

            FragmentManager fragmentManager = getFragmentManager();
            FragmentTransaction trans = fragmentManager.beginTransaction();
            if (null ==fragmentManager.findFragmentByTag("swype")) {
                trans.replace(R.id.content_frame, swypeFragment, "swype");
            }
            trans.commit();

            //update selected item and title, then close the drawer
            mDrawerList.setItemChecked(position, true);
            setTitle(mSections[position]);
            mDrawerLayout.closeDrawer(mDrawerList);
        }
    else if (position == 2) {
         //TO BE DONE
       }
    }

    @Override
    public void setTitle(CharSequence title) {
        mTitle = title;
        getActionBar().setTitle(mTitle);
    }

    /**
     * When using the ActionBarDrawerToggle, you must call it during onPostCreate()
     * and onConfigurationChanged()
     */
    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        //Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        //Pass any configuration change to the drawer toggle
        mDrawerToggle.onConfigurationChanged(newConfig);
    }
}

使用 ViewPager 的片段:

public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            this.context = getActivity();
            this.setRetainInstance(true);



                //pager.setOffscreenPageLimit(6);
            //Specify that the Home/up button should not be enabled, since there is no hierarchical parent
            //actionBar.setHomeButtonEnabled(true)
        }

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

        }
        @Override
        public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
            //When the given tab is selected, switch to the corresponding page in the ViewPager
            pager.setCurrentItem(tab.getPosition());
        }

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

        /*private class MyPageAdapter extends FragmentStatePagerAdapter {
            private final String[] TITLES = context.getResources().getStringArray(R.array.settings_titles);
            private ArrayList<Fragment> fragments;

            public MyPageAdapter(FragmentManager fm, ArrayList<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();
            }

            @Override
            public CharSequence getPageTitle(int position) {
                return TITLES[position % NUM_ITEMS] ;
            }

            @Override
            public int getItemPosition(Object object) {
                return POSITION_NONE;
            }
        }*/
        public abstract class MyPageAdapter extends FragmentStatePagerAdapter {

            private SparseArray<WeakReference<Fragment>> mPageReferenceMap = new SparseArray<WeakReference<Fragment>>(0);
            private List<String> mTabTitles;

            public abstract Fragment initFragment(int position);

            public MyPageAdapter(FragmentManager fm, List<String> tabTitles) {
                super(fm);
                mTabTitles = tabTitles;
            }

            @Override
            public Object instantiateItem(ViewGroup viewGroup, int position) {

                mPageReferenceMap.put(Integer.valueOf(position), new WeakReference<Fragment>(initFragment(position)));
                return super.instantiateItem(viewGroup, position);
            }

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

            @Override
            public CharSequence getPageTitle(int position) {
                return mTabTitles.get(position);
            }

            @Override
            public void startUpdate(ViewGroup container) {}

            @Override
            public Fragment getItem(int pos) {
                Fragment f;
                switch (pos) {
                case 0:
                    f = new FirstPreferencesFragment();
                    mPageReferenceMap.put(pos, new WeakReference<Fragment>(f));
                    return f;
                case 1:
                    f = new SecondPreferencesFragment();
                    mPageReferenceMap.put(pos, new WeakReference<Fragment>(f));
                    return f;
                case 2:
                    f = new ThirdPreferencesFragment();
                    mPageReferenceMap.put(pos, new WeakReference<Fragment>(f));
                    return f;
                case 3:
                    f = new FourthPreferencesFragment();
                    mPageReferenceMap.put(pos, new WeakReference<Fragment>(f));
                    return f;
                case 4:
                    f = new FifthPreferencesFragment();
                    mPageReferenceMap.put(pos, new WeakReference<Fragment>(f));
                    return f;
                case 5:
                    f = new SixthPreferencesFragment();
                    mPageReferenceMap.put(pos, new WeakReference<Fragment>(f));
                    return f;
                case 6:
                    f = new SeventhPreferencesFragment();
                    mPageReferenceMap.put(pos, new WeakReference<Fragment>(f));
                    return f;
                default:
                    return null;
                }

            }

            @Override
            public void destroyItem(ViewGroup container, int position, Object object) {
                super.destroyItem(container, position, object);
                mPageReferenceMap.remove(position);
            }

            public Fragment getFragment(int key) {
                WeakReference<Fragment> weakReference = mPageReferenceMap.get(key);
                if (null != weakReference) {
                    return (Fragment) weakReference.get();
                }
                else {
                    return null;
                }
            }

            @Override
            public int getItemPosition(Object object) {
                if (object instanceof FirstPreferencesFragment) {
                    return 0;
                }
                else if (object instanceof SecondPreferencesFragment) {
                    return 1;
                }
                else if (object instanceof ThirdPreferencesFragment) {
                    return 2;
                }
                else if (object instanceof FourthPreferencesFragment) {
                    return 3;
                }
                else if (object instanceof FifthPreferencesFragment) {
                    return 4;
                }
                else if (object instanceof SixthPreferencesFragment) {
                    return 5;
                }
                else if (object instanceof SeventhModePreferencesFragment) {
                    return 6;
                }
                else
                    return POSITION_NONE;
            }
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.pager_layout, container, false);

            return rootView;
        }

        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
            if (savedInstanceState == null) {
                //this.mPagerTitleStrip = (PagerTitleStrip) getActivity().findViewById(R.id.pager_title_strip);
                actionBar = getActivity().getActionBar();
                pager = (ViewPager) getActivity().findViewById(R.id.viewpager);


                setAdapter();
                pager.setAdapter(pageAdapter);

            }
            else {
                int index = pager.getCurrentItem();
                MyPageAdapter adapter = ((MyPageAdapter) pager.getAdapter());
                Fragment f = adapter.getFragment(index);
                getFragmentManager().beginTransaction().replace(pager.getId(), f).commit();
            }
            //Specify that tabs should be displayed in the action bar.
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


            pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
                @Override
                public void onPageSelected(int position) {
                    //When swiping between different app sections, select the corresponding tab.
                    //We can also use ActionBar.Tab#select() to do this if we have a reference to the tab
                    actionBar.setSelectedNavigationItem(position);
                }
            });

            //For each of the sections in the app, add a tab to the action bar.
            for (int i = 0; i < pageAdapter.getCount(); i++) {
                //Create a tab with text corresponding to the page title defined by the adapter.
                //Also specify this activity object, which implements the TabListener interface, as the listener for when this tab is selected.
                actionBar.addTab(actionBar.newTab().setText(pageAdapter.getPageTitle(i)).setTabListener(this));
            }

        }

        @Override
        public void onPause() {
            actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
            super.onPause();
        }

        private void setAdapter() {
            if (pageAdapter == null)
                pageAdapter = new MyPageAdapter(getFragmentManager(), Arrays.asList(context.getResources().getStringArray(R.array.settings_titles))) {

                @Override
                public Fragment initFragment(int position) {

                    Fragment fragment;
                    if (position == 0) {
                        fragment = Fragment.instantiate(getActivity(), FirstPreferencesFragment.class.getName());

                    }
                    else if (position == 1) {
                        fragment = Fragment.instantiate(getActivity(), SecondPreferencesFragment.class.getName());
                    }
                    else if (position == 2) {
                        fragment = Fragment.instantiate(context, ThirdPreferencesFragment.class.getName());
                    }
                    else if (position == 3) {
                        fragment = Fragment.instantiate(context, FourthPreferencesFragment.class.getName());
                    }
                    else if (position == 4) {
                        fragment = Fragment.instantiate(context, FifthPreferencesFragment.class.getName());
                    }
                    else if (position == 5) {
                        fragment = Fragment.instantiate(context, SixthPreferencesFragment.class.getName());
                    }
                    else if (position == 6) {
                        fragment = Fragment.instantiate(context, SeventhPreferencesFragment.class.getName());
                    }
                    else
                        fragment = null;
                    return fragment;
                }
            };

            Handler handler = new Handler();
            handler.post(new Runnable() {
                @Override
                public void run() {

                    pager.setVisibility(View.VISIBLE);
                    //mPagerTitleStrip.setVisibility(View.VISIBLE);
                    pageAdapter.notifyDataSetChanged();
                }
            });
        }

我在用着:

android.support.v4.app.ViewPager,

android.support.v13.app.FragmentStatePagerAdapter

4

2 回答 2

3

请尝试使用 new MyPageAdapter(get* Child *FragmentManager()

于 2013-10-16T01:25:34.517 回答
0

上面 user2884639 的答案在我的情况下有效,换句话说 getChildFragmentManager() 是使用导航抽屉多次创建新实例时空白片段的解决方案。

与 OP 的区别在于我使用的是 FragmentPagerAdapter,而不是 FragmentStatePagerAdapter。我的代码如下所示:

托管 ViewPager 的片段:

package com.shemanigans.mime;

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.astuetz.PagerSlidingTabStrip;

public class FragmentLongTermDCA extends Fragment {
    /**
     * The fragment argument representing the section number for this
     * fragment.
     */
    private static final String ARG_SECTION_NUMBER = "section_number";
    private MyAdapter adapterViewPager;
    private ViewPager vpPager;
    private PagerSlidingTabStrip tabs;
    private OnPageChangeListener mPageChangeListener;

    private static DCAfragment dcaFrag;
    private static AnalysisFragment analysisFrag;
    private static ActivityFragment activityFrag;

    //private boolean freqSweepOn = false;

    /**
     * Returns a new instance of this fragment for the given section
     * number.
     */
    public static FragmentLongTermDCA newInstance(int sectionNumber) {
        FragmentLongTermDCA fragment = new FragmentLongTermDCA();
        Bundle args = new Bundle();
        args.putInt(ARG_SECTION_NUMBER, sectionNumber);
        fragment.setArguments(args);
        return fragment;
    }

    public FragmentLongTermDCA() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_longterm_dca, container, false);
        mPageChangeListener = new OnPageChangeListener() {
            // This method will be invoked when a new page becomes selected.
            @Override
            public void onPageSelected(int position) {
                switch(position) {
                case 0:
                    break;
                case 1:
                    /*dcaFrag.bioimpedancePlot.setVisibility(View.GONE);
                    dcaFrag.startButton.setVisibility(View.GONE);
                    dcaFrag.startButtonBar.setVisibility(View.GONE);*/
                    break;
                case 2:
                    //analysisFrag.setupFragment(freqSweepOn);
                    break;
                }
            }
            // This method will be invoked when the current page is scrolled
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // Code goes here
            }
            // Called when the scroll state changes: 
            // SCROLL_STATE_IDLE, SCROLL_STATE_DRAGGING, SCROLL_STATE_SETTLING
            @Override
            public void onPageScrollStateChanged(int state) {
                // Code goes here
            }
        };
        InitializeViewComponents(rootView);
        return rootView;        
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);

        ((LongTerm) activity).onSectionAttached(
                getArguments().getInt(ARG_SECTION_NUMBER));
    }

    private void InitializeViewComponents(View rootView) {      
        vpPager = (ViewPager) rootView.findViewById(R.id.vpPager);
        tabs = (PagerSlidingTabStrip) rootView.findViewById(R.id.tabs);
        adapterViewPager = new MyAdapter(getChildFragmentManager()); // SOLTION TO PROBLEM
        vpPager.setAdapter(adapterViewPager);
        tabs.setViewPager(vpPager);
        tabs.setOnPageChangeListener(mPageChangeListener);
        tabs.setTextColor(getResources().getColor(R.color.appbasetheme_color));
        tabs.setIndicatorColor(getResources().getColor(R.color.appbasetheme_color));
        dcaFrag  = DCAfragment.newInstance(4);
        analysisFrag  = AnalysisFragment.newInstance(4);
        activityFrag  = ActivityFragment.newInstance(4);
        vpPager.setCurrentItem(1);
    }

    public static class MyAdapter extends FragmentPagerAdapter {
        private static int NUM_ITEMS = 3;

        public MyAdapter(FragmentManager fragmentManager) {
            super(fragmentManager);
        }

        // Returns total number of pages
        @Override
        public int getCount() {
            return NUM_ITEMS;
        }

        // Returns the fragment to display for that page
        @Override
        public Fragment getItem(int position) {
            switch (position) {
            case 0: // Fragment # 0 - This will show FirstFragment different title
                return activityFrag;
            case 1: // Fragment # 0 - This will show FirstFragment
                return dcaFrag;
            case 2: // Fragment # 1 - This will show SecondFragment
                return analysisFrag;
            default:
                return DCAfragment.newInstance(1);          
            }
        }

        // Returns the page title for the top indicator
        @Override
        public CharSequence getPageTitle(int position) {
            switch (position) {
            case 0: 
                return "Activity";
            case 1:
                return "Raw Data";
            case 2: 
                return "Analysis";
            default:
                return "Page " + position;
            }
        }

    }

}

托管上述片段的托管活动中的 OnNavigationDrawerItemSelected 方法:

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by updating the fragment BioimpFragment
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    switch (position) {
    // Depending on the item selected in the list, add unique tags / identifiers.
    case 0:
        fragmentTransaction
        .replace(R.id.container, BioimpFragment.newInstance(position + 1), LIVE_DATA_TAG);          
        break;
    case 1:
        fragmentTransaction
        .replace(R.id.container, BioimpFragment.newInstance(position + 1), PAST_HOUR_TAG);          
        break;
    case 2:
        fragmentTransaction
        .replace(R.id.container, BioimpFragment.newInstance(position + 1), PAST_DAY_TAG);           
        break;
    case 3:
        fragmentTransaction
        .replace(R.id.container, FragmentLongTermDCA.newInstance(position + 1), EXPORT_DATA_TAG);           
        break;
    case 4:
        fragmentTransaction
        .replace(R.id.container, BioimpFragment.newInstance(position + 1), SCAN_TAG);           
        break;
    }
    fragmentTransaction.commit();
}
于 2015-02-11T21:16:48.957 回答