简体   繁体   English

如何使用fragmentPagerAdapter在ViewPager中替换另一个片段

[英]How to replace a fragment from another in a ViewPager with fragmentPagerAdapter

After a lot of research and several attempts, I still can not solve my problem. 经过大量研究和几次尝试,我仍然无法解决我的问题。 I would like to replace a fragment in a view pager that has a fragmentPagerAdapter 我想替换具有fragmentPagerAdapter的视图分页器中的一个片段

In summary I have 8 pages (fragments) in my pageview I would replace certain page with a new page but I can not win 总而言之,我的综合浏览量中有8页(片段),我会用新页面替换某些页面,但我赢不了

My Activity 我的活动

    public class AfficherOngletsCategories  extends FragmentActivity implements
 TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener   {

    private ProgressDialog pDialog;
    private static final String READ_CATEGORIES_URL = "http://192.168.1.30/GCR2000/SelectCategories.php";
    private static final String READ_SOUS_CATEGORIES_URL = "http://192.168.1.30/GCR2000/SelectSousCategories.php";


private static final String TAG_NOM = "nom";
private static final String TAG_CATEGORIES_ID = "categorie_id";
private static final String TAG_SOUS_CATEGORIES_ID = "sousCategorie_id";



private Categorie catObjet = new Categorie();
private  ArrayList<HashMap<String,String>> ListCat = null;

private SousCategorie SousCatObjet = new SousCategorie();
private ArrayList<HashMap<String,String>> ListSousCat;
private TabHost mTabHost;
private ViewPager mViewPager;
private HashMap<String, TabInfo> mapTabInfo = new HashMap<String,  n   

    AfficherOngletsCategories.TabInfo>();
    private PagerAdapter mPagerAdapter;
     Boolean flag = false;
   Bundle test;
    /**
     * Maintains extrinsic info of a tab's construct
     */
        private class TabInfo {
        private String tag;
        private Class<?> clss;
        private Bundle args;
        private Fragment fragment;

            TabInfo(String tag, Class<?> clazz, Bundle args) {
            this.tag = tag;
            this.clss = clazz;
            this.args = args;
        }

    }

/**
 * A simple factory that returns dummy views to the Tabhost
 */
class TabFactory implements TabContentFactory {

    private final Context mContext;

    /**
     * @param context
     */
    public TabFactory(Context context) {
        mContext = context;
    }

    /**
     * (non-Javadoc)
     * 
     * @see android.widget.TabHost.TabContentFactory#createTabContent(java.lang.String)
     */
    public View createTabContent(String tag) {
        View v = new View(mContext);
        v.setMinimumWidth(0);
        v.setMinimumHeight(0);
        return v;
    }

}

/**
 * (non-Javadoc)
 * 
 * @see android.support.v4.app.FragmentActivity#onCreate(android.os.Bundle)
 */
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Inflate the layout
    setContentView(R.layout.activity_main1);
    flag = false;
    LoadCategories lc= new LoadCategories();
    lc.execute();
    //Thread t = new Thread(new LoadCategories2());

//  t.start();
        //Attend la fin AsynTask  
        try {
            lc.get();

        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //Lancer après AsynTask
        UpdateOnglet(savedInstanceState);

}



/**
 * (non-Javadoc)
 * 
 * @see android.support.v4.app.FragmentActivity#onSaveInstanceState(android.os.Bundle)
 * 
 */
protected void onSaveInstanceState(Bundle outState) {
    outState.putString("tab", mTabHost.getCurrentTabTag()); // save the tab selected
    //outState.putSerializable("listCat", ListCat); 
    //outState.putSerializable("listSousCat", ListSousCat); 
    // selected
    super.onSaveInstanceState(outState);
}

/*
 * (non-Javadoc)
 * 
 * @see android.app.Activity#onRestoreInstanceState(android.os.Bundle)
 */
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    if (savedInstanceState != null) {
        this.mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab")); // set the tab as per the saved state
        //ListCat = (ArrayList<HashMap<String, String>>) savedInstanceState.getSerializable("listCat"); 
        //ListSousCat = (ArrayList<HashMap<String, String>>) savedInstanceState.getSerializable("listSousCat");
    }
    super.onRestoreInstanceState(savedInstanceState);
}


 public void updateJSONdata() {
        //Récupere la liste des catégories
        ListCat = catObjet.updateJSONOnedata(READ_CATEGORIES_URL, TAG_CATEGORIES_ID, TAG_NOM);
        //Récupere la liste des sous-catégories
        ListSousCat = SousCatObjet.updateJSONOnedata(READ_SOUS_CATEGORIES_URL, TAG_CATEGORIES_ID, TAG_NOM, TAG_SOUS_CATEGORIES_ID);


    }


 public void UpdateOnglet(Bundle args){


     mTabHost = (TabHost) findViewById(android.R.id.tabhost);
     mTabHost.setup();
     TabInfo tabInfo = null;
     Class<?> mfragment =null;
     Bundle objetbunble = null;
     List<Fragment> fragments = new Vector<Fragment>();
     String catName = null;

     //Boucle les categories
       for ( int i = 0; ListCat.size() > i; i++){

                //Affectation de la categorie dans l'onglet
                TabSpec ts = mTabHost.newTabSpec(ListCat.get(i).get(TAG_NOM).toString()).setIndicator(ListCat.get(i).get(TAG_NOM).toString());
                Boolean flag = true;

                //Boucle des sous-categorie 
                for(int j = 0; ListSousCat.size() > j; j++){
                    //compare  primary key id avec la foreing key pour déterminer si le fragment associé a l'onglet sera une liste ou un gridlayout
                        if (ListCat.get(i).get(TAG_CATEGORIES_ID).toString().equals(ListSousCat.get(j).get(TAG_CATEGORIES_ID).toString())){

                            //Affectation du fragment a l'onglet
                            mfragment = AfficherSousCategories.class;
                            catName = ListCat.get(i).get(TAG_NOM).toString();
                            objetbunble = new Bundle();
                            //Fragment test = null;
                            objetbunble.putString("sCsousCatId", ListSousCat.get(j).get(TAG_SOUS_CATEGORIES_ID).toString());
                            objetbunble.putString("sousCatId", ListSousCat.get(j).get(TAG_CATEGORIES_ID).toString());
                            objetbunble.putString("catId",ListCat.get(i).get(TAG_CATEGORIES_ID));
                            objetbunble.putBoolean("flag", flag);
                            objetbunble.putString("tag", ListCat.get(i).get(TAG_NOM).toString());
                            //args = objetbunble;
                            //  fragments.setArguments(objetbunble);

                             break;

                        }else{

                            //Affectation du fragment a l'onglet
                            mfragment = AfficherListElem.class;

                            catName = ListCat.get(i).get(TAG_NOM).toString();
                            //Créer le bundle pour envoyer variable url caatégorie au fragment AfficherListElem
                            objetbunble = new Bundle();
                           //Renvoie l'id de la categorie
                            objetbunble.putString("catId", ListCat.get(i).get(TAG_CATEGORIES_ID));
                            objetbunble.putString("tag", ListCat.get(i).get(TAG_NOM).toString());
                            //args = objetbunble;


                        }//End if
                }//End for ListSousCat



                    //  mTabHost.addTab(ts, mfragment, objetbunble);

                    //Ajouter le fragment dans le tab
                    AfficherOngletsCategories.AddTab(this, this.mTabHost, ts,
                            (tabInfo = new TabInfo(catName, mfragment, args) ) );
                    //Ajouter tag dans map
                    this.mapTabInfo.put(tabInfo.tag, tabInfo);

                    //Ajouter à liste de fragment pour l'adapter
                    fragments.add(Fragment.instantiate(this, mfragment.getName()));
                    //répérer la position
                    //objetbunble.putInt("fragId", fragments.get(i).getId());

                    //set le bunble dans le frag
                    fragments.get(i).setArguments(objetbunble);
       }//End for listCat

                   mTabHost.setOnTabChangedListener(this);

                   //Création de l'adapter
                   this.mPagerAdapter = new PagerAdapter(super.getSupportFragmentManager(), fragments);
                   //this.mPagerAdapter.add(fragments);
                   //mPagerAdapter.notifyDataSetChanged();


                    this.mViewPager = (ViewPager) super.findViewById(R.id.tabviewpager2);
                    this.mViewPager.setAdapter(this.mPagerAdapter);
                    this.mViewPager.setOnPageChangeListener(this);

                   /*Forcer le scrool horizontal
                   TabWidget tw = (TabWidget) findViewById(android.R.id.tabs);
                   LinearLayout ll = (LinearLayout) tw.getParent();
                   HorizontalScrollView hs = new HorizontalScrollView(this);
                   hs.setLayoutParams(new FrameLayout.LayoutParams(
                       FrameLayout.LayoutParams.MATCH_PARENT,
                       FrameLayout.LayoutParams.WRAP_CONTENT));
                   ll.addView(hs, 0);
                   ll.removeView(tw);
                   hs.addView(tw);
                   hs.setHorizontalScrollBarEnabled(false);*/
 }


/**
 * Add Tab content to the Tabhost
 * 
 * @param activity
 * @param tabHost
 * @param tabSpec
 * @param clss
 * @param args
 */
private static void AddTab(AfficherOngletsCategories activity,
        TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo) {
    // Attach a Tab view factory to the spec
    tabSpec.setContent(activity.new TabFactory(activity));
    tabHost.addTab(tabSpec);
}

/**
 * (non-Javadoc)
 * 
 * @see android.widget.TabHost.OnTabChangeListener#onTabChanged(java.lang.String)
 */
public void onTabChanged(String tag) {
    // TabInfo newTab = this.mapTabInfo.get(tag);
    int pos = this.mTabHost.getCurrentTab();
    this.mViewPager.setCurrentItem(pos);

}

/*
 * (non-Javadoc)
 * 
 * @see
 * android.support.v4.view.ViewPager.OnPageChangeListener#onPageScrolled
 * (int, float, int)
 */
int x = 0;
@Override
public void onPageScrolled(int position, float positionOffset,
        int positionOffsetPixels) {
    // TODO Auto-generated method stub
    x = position;

}

/*
 * (non-Javadoc)
 * 
 * @see
 * android.support.v4.view.ViewPager.OnPageChangeListener#onPageSelected
 * (int)
 */
@Override
public void onPageSelected(int position) {
    // TODO Auto-generated method stub
    this.mTabHost.setCurrentTab(position);

    //Faire suivre les onglets avec la pageview
    HorizontalScrollView hv = (HorizontalScrollView)findViewById(R.id.scrool);
    TabWidget tw = (TabWidget)findViewById(android.R.id.tabs);
    int ntabs = ListCat.size();
    int taille = ((tw.getWidth() / ntabs)-(tw.getWidth() / (ntabs*4)));
    if (x < position)hv.scrollBy(taille, 0);
    else hv.scrollBy(-taille, 0);


}

/*
 * (non-Javadoc)
 * 
 * @see android.support.v4.view.ViewPager.OnPageChangeListener#
 * onPageScrollStateChanged(int)
 */
@Override
public void onPageScrollStateChanged(int state) {
    // TODO Auto-generated method stub

}


//exemple thread : new thread = new (new updateJSONdata()).start();
public class LoadCategories2 implements Runnable {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        updateJSONdata();
        flag = true;
    }

}

public class LoadCategories extends AsyncTask<Void, Void, Boolean> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(AfficherOngletsCategories.this);
        pDialog.setMessage("Loading Comments...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    @Override
    protected Boolean doInBackground(Void... arg0) {

            updateJSONdata();
        return null;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);
        pDialog.dismiss();






    }
}

} }

My pageAdapter 我的pageAdapter

     /**
     * The <code>PagerAdapter</code> serves the fragments when paging.
     */
      public class PagerAdapter extends FragmentPagerAdapter {
    FragmentTransaction transaction;
    private List<Fragment> fragments;
    private  Fragment mFragmentAtPos0 ;

    /**
     * @param fm
     * @param fragments
     */


    public PagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;

    }
    public void add(List<Fragment> fragments){
     for (int i = 0; fragments.size() > i; i++){


            transaction  = fragments.get(i).getFragmentManager().beginTransaction();


            //mPagerAdapter.getItem(poss).d
            //AfficherSousCategories

            transaction.add(R.id.pagercontent, fragments.get(i));
            //transaction.hide(AfficherSousCategories.this);
            //transaction.show(list);
            //getActivity().
            //transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
            //transaction.remove(arg0)
            transaction.addToBackStack(null);

            transaction.commit();
            }
    }
    /* (non-Javadoc)
     * @see android.support.v4.app.FragmentPagerAdapter#getItem(int)
     */
    @Override
    public Fragment getItem(int position) {
        Log.i("getitem", this.fragments.get(position) + " "+position);

            return this.fragments.get(position);
    }



    /* (non-Javadoc)
     * @see android.support.v4.view.PagerAdapter#getCount()
     */
    @Override
    public int getCount() {
        return this.fragments.size();
    }


    public int getItemPosition(Object object) {
           return POSITION_NONE;
        }
}

Here is the piece I want to replace, made ​​in this fragment create buttons by sub-categories that exist for the selected category. 这是我要替换的片段,在此片段中由针对所选类别存在的子类别创建按钮。 Once the user clicking on a category in this fragment must be replaced by another I used one before and I fragmentTabHost replace the fragment in fragmentLayout realContent and all worked perfectly but since I wanted to use the pager view, I can not lie out more. 一旦用户单击该片段中的一个类别必须替换为另一个,我就使用了一个片段片段,然后我fragmentTabHost替换了fragmentLayout realContent中的片段,并且一切正常,但是由于我想使用分页器视图,因此我无法再进行更多设置了。 In viewpager, I must necessarily replace the fragment that exists in the fragmentAdapter, but I do not understand how. 在viewpager中,我必须必须替换fragmentAdapter中存在的片段,但是我不知道如何。

     public class AfficherSousCategories extends Fragment {
    private ProgressDialog pDialog;

    // testing on Emulator:
    public  String urlSousCat = "http://192.168.1.30/GCR2000/ListSousCat.php";
    public  String urlListSousCat = "http://192.168.1.30/GCR2000/ListElemSousCat.php";

    //private static final String TAG_SUCCESS = "success";
    //private static final String TAG_TITLE = "title";
     Intent monIntent;
     Button btn;
    //Type d'envoie JSON
    private static final String TAG_POSTS = "posts";
    // Balise JSON :
    private static final String TAG_ELMENT_ID = "elment_id";
    private static final String TAG_NOM = "nom";
    private static final String TAG_DESCRIPTION = "description";
    private static final String TAG_PRIX = "prix";
    public String TAG = "sousCat";
    private ViewPager mViewPager;
    private PagerAdapter mPagerAdapter;
    //public static final String TAG = "sousCat";
    String sousCatId;
    String sousCategorie_id;
    String catId;
    String url;
    android.support.v7.widget.GridLayout buttonContainer;
    public ArrayList<HashMap<String, String>> nSousCat;
    private ArrayList<HashMap<String,String>> ListSousCat;
    Boolean flag = false;
    AfficherListElem list;
    //String tag;
    FragmentTransaction transaction;
    int poss;
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {

            View view = inflater.inflate(R.layout.grid_sous_categories, container, false);
            buttonContainer =             (android.support.v7.widget.GridLayout)view.findViewById(R.id.buttonContainer);   

                mViewPager = (ViewPager) getActivity().findViewById(R.id.tabviewpager2);

            return view;
        }


        public void onStart(){
            super.onStart();
                //transaction.add(R.id.realtabcontent, list);
            if(list !=null){
            //  mViewPager.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, 0, 1));

                 transaction = getFragmentManager().beginTransaction();

                transaction.show(AfficherSousCategories.this);
                transaction.commit();
            }
        }

        public void onStop(){
            super.onStop();
                //transaction.add(R.id.realtabcontent, list);
            if(list !=null){
            //  mViewPager.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, 0, 1));

                 transaction = getFragmentManager().beginTransaction();

                transaction.hide(list);
                transaction.commit();
            }
        }

    @Override
    public void onResume() {

        // TODO Auto-generated method stub
        super.onResume();
          //Objet Bindle qui récupérer les données envoyé de l'activity AfficherongletsCatgories
            Bundle objetbunble  = getArguments();

            catId = objetbunble.getString("catId");
            sousCatId = objetbunble.getString("sousCatId"); 
           TAG = objetbunble.getString("tag"); 
            flag = objetbunble.getBoolean("flag");
           poss = objetbunble.getInt("poss");
            new LoadElements().execute();

    }


    public void updateJSONdata() {

            SousCategorie sc = new SousCategorie();
            //La list des éléments parser nElemList = reçois un ArrayList<HashMap<String, String>> avec l'url en paramatre  
            nSousCat = sc.updateListElem(urlSousCat, catId);


    }


    /**
     * Inserts the parsed data into the listview.
     */
    private void updateList() {

             float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 175, getResources().getDisplayMetrics());

             for (int i = 0; nSousCat.size() > i; i++){
                 final String nomSouCat = nSousCat.get(i).get("nom").toString();
                 btn = new Button(getActivity());
                 btn.setText(nomSouCat);
                 // sousCategorie_id = nSousCat.get(i).get("souscategorie_id").toString();
                 btn.setId(Integer.parseInt(nSousCat.get(i).get("souscategorie_id").toString()));
                 btn.setHeight((int) pixels);
                 btn.setWidth((int) pixels);


                 btn.setOnClickListener(new View.OnClickListener() {
                     public void onClick(View v) {
                         // Perform action on click   


                        // monIntent = new Intent(getActivity(), AfficherListElem.class);
                         Bundle objetbunble = new Bundle();

                         for (int i = 0; nSousCat.size() > i; i++){
                             if (v.getId() == Integer.parseInt(nSousCat.get(i).get("souscategorie_id").toString())){
                                 objetbunble.putString("sousCatId", nSousCat.get(i).get("souscategorie_id").toString()); 
                                 Log.i("index dans if for", nSousCat.get(i).get("souscategorie_id").toString());
                                 break;

                             }

                         }
                         objetbunble.putBoolean("flag", flag);

                         objetbunble.putString("catId", catId);

                         objetbunble.putString("tag", nomSouCat);





                         //Remplacer view pager
                        // List<Fragment> fragments = new Vector<Fragment>();
                         //fragments.add(Fragment.instantiate(getActivity(), AfficherListElem.class.getName()));
                         //fragments.get(0).setArguments(objetbunble);

                        // mPagerAdapter.getItemPosition(object);

                       //  mPagerAdapter = new PagerAdapter(
                        //       getActivity().getSupportFragmentManager(), fragments);
                            //
                        //  mViewPager = (ViewPager)getActivity().findViewById(R.id.tabviewpager2);
                            //mViewPager.setAdapter(mPagerAdapter);
                         /*
                         FragmentManager manager = getFragmentManager();
                         FragmentTransaction transaction = manager.beginTransaction();
                         transaction.replace(R.id.tabviewpager2, list.newInstance(flag, catId, nomSouCat));
                         transaction.addToBackStack(null);
                         transaction.commit();
                         */
                                             list = new AfficherListElem();
                            list.setArguments(objetbunble);
                            transaction  = getFragmentManager().beginTransaction();
                                                transaction.replace(R.id.tabviewpager2, list);  //le  probleme et ici car je ne sais pas quel R.id utilisé ou je mis prend mal
                                                transaction.addToBackStack(TAG);
                            transaction.commit();

                            //mViewPager.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, 0, 0));
                            //mPagerAdapter.getItem(poss).d
                            //AfficherSousCategories
                            //mViewPager.setAdapter(mPagerAdapter);



                            //transaction.hide(AfficherSousCategories.this);
                            //transaction.show(list);
                            //getActivity().
                            //transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
                            //transaction.remove(arg0)

                            //mPagerAdapter.notifyDataSetChanged();
                            //AfficherSousCategories.this.getView().setVisibility(AfficherSousCategories.this.getView().GONE);
                            //list.getView().setVisibility(list.getView().VISIBLE);
                     }
                 });


                 buttonContainer.addView(btn);
             }//Bouble for      

    }



    public class LoadElements extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(getActivity());
            pDialog.setMessage("Loading Comments...");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        @Override
        protected Boolean doInBackground(Void... arg0) {
            updateJSONdata();
            return null;

        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            pDialog.dismiss();
            updateList();
        }
    }

   }

My Layout 我的版式

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >


     <include 
         android:id="@+id/top"
         layout="@layout/barre_info"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="5dp"
         android:layout_alignParentTop="true"
         android:layout_weight="10"
        />
         <!--  -->






   <TabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/top"
        >
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            >
                <HorizontalScrollView
                    android:id="@+id/scrool"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fillViewport="true"
                android:scrollbars="none">
        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal" />
            </HorizontalScrollView>

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="0"/>

            <android.support.v4.view.ViewPager
                android:id="@+id/tabviewpager2"
                android:layout_width="fill_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                />
           <FrameLayout
                android:id="@+id/pagercontent"
                android:layout_width="fill_parent"
                android:layout_height="0dp"
                android:layout_weight="1">


           </FrameLayout>
        </LinearLayout>
    </TabHost>


    <include 
        android:id="@+id/bottom"
        layout="@layout/boutons_user_standard"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
            android:layout_marginBottom="5dp"
            android:layout_alignParentBottom="true"
            android:layout_weight="10"/>
         <!--  -->



   </RelativeLayout>

I thank in advance all those who take the time to read my post 我预先感谢所有花时间阅读我的帖子的人

I do not have time to fully understand your code but here is my code in case you can use it: 我没有时间完全理解您的代码,但是如果您可以使用它,这是我的代码:

FragmentStatePagerAdapter (usage explained below): FragmentStatePagerAdapter(用法说明如下):

public class DisplayPagerAdapter extends FragmentStatePagerAdapter  {

    private static final String TAG = "DisplayPagerAdapter";

    SparseArray<DisplayFragment> registeredFragments = new SparseArray<DisplayFragment>();

    private final Context context;
    private final DisplayCoreModule display;
    private final FragmentManager fm;

    private boolean isAddOrRemoving;

    public DisplayPagerAdapter(Context context, FragmentManager fm,
            DisplayCoreModule display) {
        super(fm);
        this.context = context;
        this.display = display;
        this.fm = fm;

        Log.d(TAG, "pages " + display.getPagesCount());
    }


    public void notifySizeChangingDataSetChange() {
        isAddOrRemoving = true;
        notifyDataSetChanged();
        isAddOrRemoving = false;
    }

    @Override
    public int getCount() {
        int count = (display != null && display.getPagesCount() > 0) ? display
                .getPagesCount() : 1;
        return count;
    }

    @Override
    public int getItemPosition(Object object) {
        DisplayFragment frag = (DisplayFragment) object;
        if (!display.containsPageId(frag.getPageId())) {
            // this will update the 'no information' page with id -1
            return POSITION_NONE;
        }
        if (isAddOrRemoving) {
            // recreate all for simplicity
            return POSITION_NONE;
        }
        return POSITION_UNCHANGED;
    }

    @Override
    public Fragment getItem(int position) {
        Log.d(TAG, "getItem " + position);
        return DisplayFragment.newInstance(position);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        if (display != null && display.getPagesCount() > 0) {
            return context.getString(R.string.page) + " " + (position + 1);
        } else {
            return super.getPageTitle(position);
        }
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Log.d(TAG, "instantiateItem " + position);
        DisplayFragment fragment = (DisplayFragment) super.instantiateItem(
                container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Log.d(TAG, "destroyItem " + position);
        registeredFragments.remove(position);
        super.destroyItem(container, position, object);
    }

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }

    public SparseArray<DisplayFragment> getRegisteredFragments() {
        return registeredFragments;
    }

}

The pages is generated based on information from DisplayCoreModule . 这些页面是基于DisplayCoreModule信息生成的。 This essentially maps page positions to the information that is to be displayed on each DisplayFragment, which is also why getItem() only need to pass the position to the new DisplayFragment in order to show the correct info. 这实际上将页面位置映射到要在每个DisplayFragment上显示的信息,这也是为什么getItem()只需要将该位置传递给新的DisplayFragment即可显示正确的信息。

I would imagine that it would be possible to have an external class manage which fragments should be displayed in each position. 我可以想象,可以有一个外部类来管理应该在每个位置显示哪些片段。 The important part is that it is handled 'external' to the PagerAdapter. 重要的是它是在PagerAdapter的“外部”处理的。

The code around getRegisteredFragment() is only used as a handle to the currently visible fragment (that is surely added to Activity and not null), though it can in theory also be used to fetch the cached fragments surrounding the visible fragment. 尽管在理论上也可以使用getRegisteredFragment()周围的代码作为当前可见片段的句柄(肯定会添加到Activity而不是null),但是它在理论上也可以用于获取可见片段周围的缓存片段。 Note that FragmentStatePagerAdapter only adds a few fragments and not all, this can be changed using mViewPager.setOffscreenPageLimit() 请注意,FragmentStatePagerAdapter仅添加一些片段,而不是全部,可以使用mViewPager.setOffscreenPageLimit()进行更改。

Add/remove fragments 添加/删除片段

Ok, now recall the DisplayCoreModule . 好的,现在回想起DisplayCoreModule This class keeps the current state of my data. 此类保留数据的当前状态。 Now, whenever that data changes, I send a callback to the Activity holding my ViewPager. 现在,每当数据更改时,我都会将一个回调发送给持有ViewPager的Activity。 These callbacks looks like this: 这些回调如下所示:

/* 
 * Get the currently visible DisplayFragment in the ViewPager
 * 
 * @see com.turios.activities.listeners.TuriosUICallback#getSelectedDisplayFragment()
 */
@Override
public DisplayFragment getSelectedDisplayFragment() {
    return (DisplayFragment) mDisplayPagerAdapter
            .getRegisteredFragment(mViewPager.getCurrentItem());
}


/* 
 * Makes the current DisplayFragment refresh it's information
 * 
 * @see com.turios.activities.listeners.TuriosUICallback#refreshDisplayFragment()
 */
@Override
public void refreshDisplayFragment() {
    DisplayFragment displayFragment = getSelectedDisplayFragment();
    if (displayFragment != null) {
        displayFragment.refreshScreen();
    }
}

/* 
 * A page has been deleted in DisplayCoreModule
 * Inform the Viewpager by calling notifySizeChangingDataSetChange
 * 
 * @see com.turios.activities.listeners.TuriosUICallback#pageDeleted(int)
 */
@Override
public void pageDeleted(int page) {
    mDisplayPagerAdapter.notifySizeChangingDataSetChange();

    deferInvalidation();

    if (display.getPagesCount() == 0) {
        locationService.stopLoactionUpdates();
        wakeScreen.screenRelease();
    }

}

/* 
 * A page has been added 
 * Inform the Viewpager by calling notifySizeChangingDataSetChange
 * 
 * @see com.turios.activities.listeners.TuriosUICallback#addPage(int)
 */
@Override
public void addPage(final int page) {
    tintBackground();

    mDisplayPagerAdapter.notifyDataSetChanged();

    if (mViewPager.getCurrentItem() == page)
        return;

    // http://stackoverflow.com/questions/13585396/viewpager-re-instantiates-items-out-of-order-after-screen-rotation
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            mViewPager.setCurrentItem(page);
        }
    }, ANIMATION_TINTBACKGROUND);

}

/*
 * New information has been added to a page
 * Tint screen to catch attention and scroll to the newly updated DisplayFragment
 *  
 * @see com.turios.activities.listeners.TuriosUICallback#pageUpdated(int, java.util.List)
 */
@Override
public void pageUpdated(final int page, final List<String> entries) {
    tintBackground();

    // http://stackoverflow.com/questions/13585396/viewpager-re-instantiates-items-out-of-order-after-screen-rotation
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            if (!(mViewPager.getCurrentItem() == page)) {
                mViewPager.setCurrentItem(page);
            } else {
                invalidateOptionsMenu();
            }

            DisplayFragment displayFrag = (com.turios.activities.fragments.DisplayFragment) mDisplayPagerAdapter
                    .getRegisteredFragment(page);
            if (displayFrag != null) {
                displayFrag.appendEntries(entries);
            }

        }
    }, ANIMATION_TINTBACKGROUND);

}

So whenever the 'Model' (DisplayCoreModule) data changes with addition or removal of pages, the only thing I have to do in order to update the 'Display' (ViewPager), is to call notifySizeChangingDataSetChange . 因此,每当“模型”(DisplayCoreModule)数据随着页面的添加或删除而发生变化时,我唯一要做的就是更新“显示”(ViewPager)的事情就是调用notifySizeChangingDataSetChange

The reason addPage simply calls notifyDataSetChanged is that I always add new pages to the tail of the ViewPager. addPage仅仅调用notifyDataSetChanged的原因是,我总是将新页面添加到ViewPager的尾部。 Thus, I do not want to have the ViewPager recreate all the fragments as it is not necessary here. 因此,我不想让ViewPager重新创建所有片段,因为这里没有必要。

  • notifySizeChangingDataSetChange makes the ViewPager recreate all fragments, allowing to change the order, which is needed when adding or deleting fragments that is not the tail. notifySizeChangingDataSetChange使ViewPager重新创建所有片段,从而允许更改顺序,添加或删除不是尾部的片段时需要此顺序。
  • notifyDataSetChanged uses POSITION_UNCHANGED for getItem, which has a way less performance impact when called. notifyDataSetChanged使用POSITION_UNCHANGED作为getItem,调用时对性能的影响较小。 But with the limitation of being unable to change the order of the fragments. 但是受限于无法改变片段的顺序。

This architecture might not suit your situation but it works for me. 这种体系结构可能不适合您的情况,但对我有用。

Happy coding and good luck :) 编码愉快,祝您好运:)

The adapter calls getItemId(int position) to check if the data backing the fragment at position has changed. 适配器调用getItemId(int position)来检查支持该position的片段的数据是否已更改。 The default implementation returns the position. 默认实现返回位置。 If you override this method in your adapter to return different value for the updated data the adapter knows that the old Fragment is no longer valid. 如果您在适配器中覆盖此方法以为更新的数据返回不同的值,则适配器会知道旧的Fragment不再有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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