[英]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.