agregar y eliminar dinámicamente la vista a viewpager

(Descubrí una solución; consulte mi publicación en la sección de respuestas a continuación).

En mi aplicación, el usuario comenzará con una sola vista de sus datos. Me gustaría agregar ViewPager y permitir que el usuario agregue más vistas según lo deseado. ¿Cómo hago esto? (No quiero usar FragmentPagerAdapter).

He leído innumerables publicaciones y resúmenes, pero aún me falta algo. Esto es lo que creo que entiendo:

MainActivity crea un ViewPager y un PagerAdapter:

ViewPager pager = null; MainPagerAdapter adapter = null; public void onCreate (Bundle savedInstanceState) { super.onCreate (savedInstanceState); pager = new ViewPager (this); setContentView (pager); adapter = new MainPagerAdapter(); pager.setAdapter (adapter); View v0 = code_to_create_initial_view(); adapter.add (v0, 0); } 

Use un Adaptador de paginación para proporcionar los conjuntos de vista. Para esto, parece que necesito métodos para agregar y eliminar vistas, algo como esto; obviamente se necesita más para decirle a ViewPager que las cosas han cambiado y cómo mostrar el cambio:

 class MainPagerAdapter extends PagerAdapter { // This holds all the currently displayable views, in order from left to right. private ArrayList views = new ArrayList(); public void addView (View v, int position) { views.add (position, v); } public void removeView (int position) { views.remove (position); } } 

Además, necesito implementar los siguientes métodos vituales. Estoy perdido aquí, lo que los llama y lo que se supone que deben hacer (¿vale, getCount es obvio)?

  public object instantiateItem (ViewGroup pager, int position); public void destroyItem (ViewGroup, int, Object); public int getCount (); public boolean isViewFromObject (View, Object); 
  • ¿Para qué son los parámetros de ViewGroup? ¿No es el grupo contenedor el ViewPager en sí mismo?
  • ¿Qué hace isViewFromObject do – cómo se asocia un objeto con una vista en primer lugar?
  • ¿Debo llamar a startUpdate y finishUdate cuando agregue o elimine las vistas?

Gracias.

Después de averiguar qué métodos de ViewPager son llamados por ViewPager y cuáles son para otros fines, se me ocurrió una solución. Lo presento aquí porque veo que muchas personas han tenido problemas con esto y no vi ninguna otra respuesta relevante.

Primero, aquí está mi adaptador; con suerte los comentarios dentro del código son suficientes:

 public class MainPagerAdapter extends PagerAdapter { // This holds all the currently displayable views, in order from left to right. private ArrayList views = new ArrayList(); //----------------------------------------------------------------------------- // Used by ViewPager. "Object" represents the page; tell the ViewPager where the // page should be displayed, from left-to-right. If the page no longer exists, // return POSITION_NONE. @Override public int getItemPosition (Object object) { int index = views.indexOf (object); if (index == -1) return POSITION_NONE; else return index; } //----------------------------------------------------------------------------- // Used by ViewPager. Called when ViewPager needs a page to display; it is our job // to add the page to the container, which is normally the ViewPager itself. Since // all our pages are persistent, we simply retrieve it from our "views" ArrayList. @Override public Object instantiateItem (ViewGroup container, int position) { View v = views.get (position); container.addView (v); return v; } //----------------------------------------------------------------------------- // Used by ViewPager. Called when ViewPager no longer needs a page to display; it // is our job to remove the page from the container, which is normally the // ViewPager itself. Since all our pages are persistent, we do nothing to the // contents of our "views" ArrayList. @Override public void destroyItem (ViewGroup container, int position, Object object) { container.removeView (views.get (position)); } //----------------------------------------------------------------------------- // Used by ViewPager; can be used by app as well. // Returns the total number of pages that the ViewPage can display. This must // never be 0. @Override public int getCount () { return views.size(); } //----------------------------------------------------------------------------- // Used by ViewPager. @Override public boolean isViewFromObject (View view, Object object) { return view == object; } //----------------------------------------------------------------------------- // Add "view" to right end of "views". // Returns the position of the new view. // The app should call this to add pages; not used by ViewPager. public int addView (View v) { return addView (v, views.size()); } //----------------------------------------------------------------------------- // Add "view" at "position" to "views". // Returns position of new view. // The app should call this to add pages; not used by ViewPager. public int addView (View v, int position) { views.add (position, v); return position; } //----------------------------------------------------------------------------- // Removes "view" from "views". // Retuns position of removed view. // The app should call this to remove pages; not used by ViewPager. public int removeView (ViewPager pager, View v) { return removeView (pager, views.indexOf (v)); } //----------------------------------------------------------------------------- // Removes the "view" at "position" from "views". // Retuns position of removed view. // The app should call this to remove pages; not used by ViewPager. public int removeView (ViewPager pager, int position) { // ViewPager doesn't have a delete method; the closest is to set the adapter // again. When doing so, it deletes all its views. Then we can delete the view // from from the adapter and finally set the adapter to the pager again. Note // that we set the adapter to null before removing the view from "views" - that's // because while ViewPager deletes all its views, it will call destroyItem which // will in turn cause a null pointer ref. pager.setAdapter (null); views.remove (position); pager.setAdapter (this); return position; } //----------------------------------------------------------------------------- // Returns the "view" at "position". // The app should call this to retrieve a view; not used by ViewPager. public View getView (int position) { return views.get (position); } // Other relevant methods: // finishUpdate - called by the ViewPager - we don't care about what pages the // pager is displaying so we don't use this method. } 

Y aquí hay algunos recortes de código que muestran cómo usar el adaptador.

 class MainActivity extends Activity { private ViewPager pager = null; private MainPagerAdapter pagerAdapter = null; //----------------------------------------------------------------------------- @Override public void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView (R.layout.main_activity); ... do other initialization, such as create an ActionBar ... pagerAdapter = new MainPagerAdapter(); pager = (ViewPager) findViewById (R.id.view_pager); pager.setAdapter (pagerAdapter); // Create an initial view to display; must be a subclass of FrameLayout. LayoutInflater inflater = context.getLayoutInflater(); FrameLayout v0 = (FrameLayout) inflater.inflate (R.layout.one_of_my_page_layouts, null); pagerAdapter.addView (v0, 0); pagerAdapter.notifyDataSetChanged(); } //----------------------------------------------------------------------------- // Here's what the app should do to add a view to the ViewPager. public void addView (View newPage) { int pageIndex = pagerAdapter.addView (newPage); // You might want to make "newPage" the currently displayed page: pager.setCurrentItem (pageIndex, true); } //----------------------------------------------------------------------------- // Here's what the app should do to remove a view from the ViewPager. public void removeView (View defunctPage) { int pageIndex = pagerAdapter.removeView (pager, defunctPage); // You might want to choose what page to display, if the current page was "defunctPage". if (pageIndex == pagerAdapter.getCount()) pageIndex--; pager.setCurrentItem (pageIndex); } //----------------------------------------------------------------------------- // Here's what the app should do to get the currently displayed page. public View getCurrentPage () { return pagerAdapter.getView (pager.getCurrentItem()); } //----------------------------------------------------------------------------- // Here's what the app should do to set the currently displayed page. "pageToShow" must // currently be in the adapter, or this will crash. public void setCurrentPage (View pageToShow) { pager.setCurrentItem (pagerAdapter.getItemPosition (pageToShow), true); } } 

Finalmente, puede usar lo siguiente para su diseño activity_main.xml :

    

Estaba buscando una solución simple para eliminar vistas de viewpager (sin fragmentos) de forma dinámica. Por lo tanto, si tiene alguna información a la que pertenecen sus páginas, puede configurarla como Ver como etiqueta. Así como así (código de adaptador):

 @Override public Object instantiateItem(ViewGroup collection, int position) { ImageView iv = new ImageView(mContext); MediaMessage msg = mMessages.get(position); ... iv.setTag(media); return iv; } @Override public int getItemPosition (Object object) { View o = (View) object; int index = mMessages.indexOf(o.getTag()); if (index == -1) return POSITION_NONE; else return index; } 

Solo necesita eliminar su información de mMessages, y luego llamar a notifyDataSetChanged() para su adaptador. Malas noticias, no hay animación en este caso.

Hay bastantes discusiones sobre este tema

  • ViewPager PagerAdapter no actualiza la vista
  • ¿Actualiza ViewPager dinámicamente?
  • Eliminar fragmentos de FragmentStatePagerAdapter

Aunque lo vemos a menudo, usar POSITION_NONE no parece ser el camino a seguir, ya que es muy ineficiente en cuanto a la memoria.

Aquí en esta pregunta, debemos considerar usar el enfoque de Alvaro :

… es para el método setTag() en instantiateItem() al crear una nueva vista. Luego, en lugar de usar notifyDataSetChanged() , puede usar findViewWithTag() para encontrar la vista que desea actualizar.

Aquí hay una respuesta SO con código basado en esta idea

Hice un progtwig similar. Espero que esto lo ayude. En su primera actividad, se pueden seleccionar cuatro datos de cuadrícula. En la siguiente actividad, hay un buscapersonas que contiene dos páginas obligatorias. Y 4 páginas más estarán allí, que serán visibles correspondientes a los datos de la cuadrícula seleccionados.

A continuación se muestra la actividad principal de MainActivity

  package com.example.jeffy.viewpagerapp; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.os.Bundle; import android.os.Parcel; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.widget.AdapterView; import android.widget.Button; import android.widget.GridView; import java.lang.reflect.Array; import java.util.ArrayList; public class MainActivity extends AppCompatActivity { SharedPreferences pref; SharedPreferences.Editor editor; GridView gridView; Button button; private static final String DATABASE_NAME = "dbForTest.db"; private static final int DATABASE_VERSION = 1; private static final String TABLE_NAME = "diary"; private static final String TITLE = "id"; private static final String BODY = "content"; DBHelper dbHelper = new DBHelper(this); ArrayList frags = new ArrayList(); ArrayList fragmentArray = new ArrayList(); String[] selectedData; Boolean port1=false,port2=false,port3=false,port4=false; int Iport1=1,Iport2=1,Iport3=1,Iport4=1,location; // This Data show in grid ( Used by adapter ) CustomGridAdapter customGridAdapter = new CustomGridAdapter(MainActivity.this,GRID_DATA); static final String[ ] GRID_DATA = new String[] { "1" , "2", "3" , "4" }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); frags.add("TabFragment3"); frags.add("TabFragment4"); frags.add("TabFragment5"); frags.add("TabFragment6"); dbHelper = new DBHelper(this); dbHelper.insertContact(1,0); dbHelper.insertContact(2,0); dbHelper.insertContact(3,0); dbHelper.insertContact(4,0); final Bundle selected = new Bundle(); button = (Button) findViewById(R.id.button); pref = getApplicationContext().getSharedPreferences("MyPref", MODE_PRIVATE); editor = pref.edit(); gridView = (GridView) findViewById(R.id.gridView1); gridView.setAdapter(customGridAdapter); gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { //view.findViewById(R.id.grid_item_image).setVisibility(View.VISIBLE); location = position + 1; if (position == 0) { Iport1++; Iport1 = Iport1 % 2; if (Iport1 % 2 == 1) { //dbHelper.updateContact(1,1); view.findViewById(R.id.grid_item_image).setVisibility(View.VISIBLE); dbHelper.updateContact(1,1); } else { //dbHelper.updateContact(1,0); view.findViewById(R.id.grid_item_image).setVisibility(View.INVISIBLE); dbHelper.updateContact(1, 0); } } if (position == 1) { Iport2++; Iport1 = Iport1 % 2; if (Iport2 % 2 == 1) { //dbHelper.updateContact(2,1); view.findViewById(R.id.grid_item_image).setVisibility(View.VISIBLE); dbHelper.updateContact(2, 1); } else { //dbHelper.updateContact(2,0); view.findViewById(R.id.grid_item_image).setVisibility(View.INVISIBLE); dbHelper.updateContact(2,0); } } if (position == 2) { Iport3++; Iport3 = Iport3 % 2; if (Iport3 % 2 == 1) { //dbHelper.updateContact(3,1); view.findViewById(R.id.grid_item_image).setVisibility(View.VISIBLE); dbHelper.updateContact(3, 1); } else { //dbHelper.updateContact(3,0); view.findViewById(R.id.grid_item_image).setVisibility(View.INVISIBLE); dbHelper.updateContact(3, 0); } } if (position == 3) { Iport4++; Iport4 = Iport4 % 2; if (Iport4 % 2 == 1) { //dbHelper.updateContact(4,1); view.findViewById(R.id.grid_item_image).setVisibility(View.VISIBLE); dbHelper.updateContact(4, 1); } else { //dbHelper.updateContact(4,0); view.findViewById(R.id.grid_item_image).setVisibility(View.INVISIBLE); dbHelper.updateContact(4,0); } } } }); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { editor.putInt("port1", Iport1); editor.putInt("port2", Iport2); editor.putInt("port3", Iport3); editor.putInt("port4", Iport4); Intent i = new Intent(MainActivity.this,Main2Activity.class); if(Iport1==1) i.putExtra("3","TabFragment3"); else i.putExtra("3", ""); if(Iport2==1) i.putExtra("4","TabFragment4"); else i.putExtra("4",""); if(Iport3==1) i.putExtra("5", "TabFragment5"); else i.putExtra("5",""); if(Iport4==1) i.putExtra("6", "TabFragment6"); else i.putExtra("6",""); dbHelper.updateContact(0, Iport1); dbHelper.updateContact(1, Iport2); dbHelper.updateContact(2, Iport3); dbHelper.updateContact(3, Iport4); startActivity(i); } }); } } 

Aquí TabFragment1, TabFragment2, etc. son fragmentos que se mostrarán en el viewpager. Y no mostraré los diseños ya que están fuera del scope de este proyecto.

MainActivity intentará Main2Activity Main2Activity

  package com.example.jeffy.viewpagerapp; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.support.design.widget.CollapsingToolbarLayout; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.design.widget.TabLayout; import android.support.v4.view.ViewPager; import android.support.v4.widget.NestedScrollView; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.TextUtils; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.FrameLayout; import java.util.ArrayList; public class Main2Activity extends AppCompatActivity { private ViewPager pager = null; private PagerAdapter pagerAdapter = null; DBHelper dbHelper; Cursor rs; int port1,port2,port3,port4; //----------------------------------------------------------------------------- @Override public void onCreate (Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); Toolbar toolbar = (Toolbar) findViewById(R.id.MyToolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); CollapsingToolbarLayout collapsingToolbar = (CollapsingToolbarLayout) findViewById(R.id.collapse_toolbar); NestedScrollView scrollView = (NestedScrollView) findViewById (R.id.nested); scrollView.setFillViewport (true); ArrayList selectedPort = new ArrayList(); Intent intent = getIntent(); String Tab3 = intent.getStringExtra("3"); String Tab4 = intent.getStringExtra("4"); String Tab5 = intent.getStringExtra("5"); String Tab6 = intent.getStringExtra("6"); TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout); tabLayout.addTab(tabLayout.newTab().setText("View")); tabLayout.addTab(tabLayout.newTab().setText("All")); selectedPort.add("TabFragment1"); selectedPort.add("TabFragment2"); if(Tab3!=null && !TextUtils.isEmpty(Tab3)) selectedPort.add(Tab3); if(Tab4!=null && !TextUtils.isEmpty(Tab4)) selectedPort.add(Tab4); if(Tab5!=null && !TextUtils.isEmpty(Tab5)) selectedPort.add(Tab5); if(Tab6!=null && !TextUtils.isEmpty(Tab6)) selectedPort.add(Tab6); dbHelper = new DBHelper(this); // rs=dbHelper.getData(1); // port1 = rs.getInt(rs.getColumnIndex("id")); // // rs=dbHelper.getData(2); // port2 = rs.getInt(rs.getColumnIndex("id")); // // rs=dbHelper.getData(3); // port3 = rs.getInt(rs.getColumnIndex("id")); // // rs=dbHelper.getData(4); // port4 = rs.getInt(rs.getColumnIndex("id")); Log.i(">>>>>>>>>>>>>>", "port 1" + port1 + "port 2" + port2 + "port 3" + port3 + "port 4" + port4); if(Tab3!=null && !TextUtils.isEmpty(Tab3)) tabLayout.addTab(tabLayout.newTab().setText("Tab 0")); if(Tab3!=null && !TextUtils.isEmpty(Tab4)) tabLayout.addTab(tabLayout.newTab().setText("Tab 1")); if(Tab3!=null && !TextUtils.isEmpty(Tab5)) tabLayout.addTab(tabLayout.newTab().setText("Tab 2")); if(Tab3!=null && !TextUtils.isEmpty(Tab6)) tabLayout.addTab(tabLayout.newTab().setText("Tab 3")); tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); final ViewPager viewPager = (ViewPager) findViewById(R.id.view_pager); final PagerAdapter adapter = new PagerAdapter (getSupportFragmentManager(), tabLayout.getTabCount(), selectedPort); viewPager.setAdapter(adapter); viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { viewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { } }); // setContentView(R.layout.activity_main2); // Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); // setSupportActionBar(toolbar); // TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout); // tabLayout.addTab(tabLayout.newTab().setText("View")); // tabLayout.addTab(tabLayout.newTab().setText("All")); // tabLayout.addTab(tabLayout.newTab().setText("Tab 0")); // tabLayout.addTab(tabLayout.newTab().setText("Tab 1")); // tabLayout.addTab(tabLayout.newTab().setText("Tab 2")); // tabLayout.addTab(tabLayout.newTab().setText("Tab 3")); // tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); } } 

ViewPagerAdapter Viewpageradapter.class

 package com.example.jeffy.viewpagerapp; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.view.ViewPager; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; /** * Created by Jeffy on 25-01-2016. */ public class PagerAdapter extends FragmentStatePagerAdapter { int mNumOfTabs; List values; public PagerAdapter(FragmentManager fm, int NumOfTabs, List Port) { super(fm); this.mNumOfTabs = NumOfTabs; this.values= Port; } @Override public Fragment getItem(int position) { String fragmentName = values.get(position); Class clazz = null; Object fragment = null; try { clazz = Class.forName("com.example.jeffy.viewpagerapp."+fragmentName); } catch (ClassNotFoundException e) { e.printStackTrace(); } try { fragment = clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return (Fragment) fragment; } @Override public int getCount() { return values.size(); } } 

Diseño para main2activity acticity_main2.xml

                 Mainactivity layout activity_main.xml         

Espero que esto ayude a alguien … Haz clic en el botón por favor si esto te ayudó

Creé una biblioteca de PagerAdapters personalizada para cambiar los elementos en PagerAdapters de forma dinámica.

Puede cambiar los elementos dinámicamente como los siguientes utilizando esta biblioteca.

 @Override protected void onCreate(Bundle savedInstanceState) { /** ... **/ adapter = new MyStatePagerAdapter(getSupportFragmentManager() , new String[]{"1", "2", "3"}); ((ViewPager)findViewById(R.id.view_pager)).setAdapter(adapter); adapter.add("4"); adapter.remove(0); } class MyPagerAdapter extends ArrayViewPagerAdapter { public MyPagerAdapter(String[] data) { super(data); } @Override public View getView(LayoutInflater inflater, ViewGroup container, String item, int position) { View v = inflater.inflate(R.layout.item_page, container, false); ((TextView) v.findViewById(R.id.item_txt)).setText(item); return v; } } 

La biblioteca Thils también admite páginas creadas por Fragments.

Aquí hay una solución alternativa a esta pregunta. Mi adaptador:

  private class PagerAdapter extends FragmentPagerAdapter implements ViewPager.OnPageChangeListener, TabListener { private List mFragments = new ArrayList(); private ViewPager mPager; private ActionBar mActionBar; private Fragment mPrimaryItem; public PagerAdapter(FragmentManager fm, ViewPager vp, ActionBar ab) { super(fm); mPager = vp; mPager.setAdapter(this); mPager.setOnPageChangeListener(this); mActionBar = ab; } public void addTab(PartListFragment frag) { mFragments.add(frag); mActionBar.addTab(mActionBar.newTab().setTabListener(this). setText(frag.getPartCategory())); } @Override public Fragment getItem(int position) { return mFragments.get(position); } @Override public int getCount() { return mFragments.size(); } /** (non-Javadoc) * @see android.support.v4.app.FragmentStatePagerAdapter#setPrimaryItem(android.view.ViewGroup, int, java.lang.Object) */ @Override public void setPrimaryItem(ViewGroup container, int position, Object object) { super.setPrimaryItem(container, position, object); mPrimaryItem = (Fragment) object; } /** (non-Javadoc) * @see android.support.v4.view.PagerAdapter#getItemPosition(java.lang.Object) */ @Override public int getItemPosition(Object object) { if (object == mPrimaryItem) { return POSITION_UNCHANGED; } return POSITION_NONE; } @Override public void onTabSelected(Tab tab, FragmentTransaction ft) { mPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(Tab tab, FragmentTransaction ft) { } @Override public void onTabReselected(Tab tab, FragmentTransaction ft) { } @Override public void onPageScrollStateChanged(int arg0) { } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageSelected(int position) { mActionBar.setSelectedNavigationItem(position); } /** * This method removes the pages from ViewPager */ public void removePages() { mActionBar.removeAllTabs(); //call to ViewPage to remove the pages vp.removeAllViews(); mFragments.clear(); //make this to update the pager vp.setAdapter(null); vp.setAdapter(pagerAdapter); } } 

Código para eliminar y agregar dinámicamente

 //remove the pages. basically call to method removeAllViews from `ViewPager` pagerAdapter.removePages(); pagerAdapter.addPage(pass your fragment); 

Después del consejo de Peri Hartman, comenzó a funcionar después de configurar nulo el adaptador ViewPager y poner el adaptador de nuevo después de eliminar las vistas. Antes de esto, la página 0 no muestra su contenido de lista.

Gracias.

Para eliminar, puede usar esto directamente:

 getSupportFragmentManager().beginTransaction().remove(fragment). commitAllowingStateLoss(); 

fragment es el fragmento que desea eliminar.

Encuentro una buena solución para este problema, esta solución puede hacer que funcione y no es necesario recrear Fragmentos.
Mi punto clave es:

  1. configure ViewPager cada vez que elimine o agregue Tab (Fragment).
  2. Anule el método getItemId, devuelva una identificación específica en lugar de la posición.

Código fuente

 package com.zq.testviewpager; import android.support.annotation.Nullable; import android.support.design.widget.TabLayout; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; 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.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.ArrayList; import java.util.Arrays; /** * Created by [email protected] on 2017/5/31. * Implement dynamic delete or add tab(TAB_C in this test code). */ public class MainActivity extends AppCompatActivity { private static final int TAB_A = 1001; private static final int TAB_B = 1002; private static final int TAB_C = 1003; private static final int TAB_D = 1004; private static final int TAB_E = 1005; private Tab[] tabsArray = new Tab[]{new Tab(TAB_A, "A"),new Tab(TAB_B, "B"),new Tab(TAB_C, "C"),new Tab(TAB_D, "D"),new Tab(TAB_E, "E")}; private ArrayList mTabs = new ArrayList<>(Arrays.asList(tabsArray)); private Tab[] tabsArray2 = new Tab[]{new Tab(TAB_A, "A"),new Tab(TAB_B, "B"),new Tab(TAB_D, "D"),new Tab(TAB_E, "E")}; private ArrayList mTabs2 = new ArrayList<>(Arrays.asList(tabsArray2)); /** * The {@link android.support.v4.view.PagerAdapter} that will provide * fragments for each of the sections. We use a * {@link FragmentPagerAdapter} derivative, which will keep every * loaded fragment in memory. If this becomes too memory intensive, it * may be best to switch to a * {@link android.support.v4.app.FragmentStatePagerAdapter}. */ private SectionsPagerAdapter mSectionsPagerAdapter; /** * The {@link ViewPager} that will host the section contents. */ private ViewPager mViewPager; private TabLayout tabLayout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); // Create the adapter that will return a fragment for each of the three // primary sections of the activity. mSectionsPagerAdapter = new SectionsPagerAdapter(mTabs, getSupportFragmentManager()); // Set up the ViewPager with the sections adapter. mViewPager = (ViewPager) findViewById(R.id.container); mViewPager.setAdapter(mSectionsPagerAdapter); tabLayout = (TabLayout) findViewById(R.id.tabs); tabLayout.setupWithViewPager(mViewPager); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; }else if (id == R.id.action_delete) { int currentItemPosition = mViewPager.getCurrentItem(); Tab currentTab = mTabs.get(currentItemPosition); if(currentTab.id == TAB_C){ currentTab = mTabs.get(currentItemPosition == 0 ? currentItemPosition +1 : currentItemPosition - 1); } mSectionsPagerAdapter = new SectionsPagerAdapter(mTabs2, getSupportFragmentManager()); mViewPager.setAdapter(mSectionsPagerAdapter); tabLayout.setupWithViewPager(mViewPager); mViewPager.setCurrentItem(mTabs2.indexOf(currentTab), false); return true; }else if (id == R.id.action_add) { int currentItemPosition = mViewPager.getCurrentItem(); Tab currentTab = mTabs2.get(currentItemPosition); mSectionsPagerAdapter = new SectionsPagerAdapter(mTabs, getSupportFragmentManager()); mViewPager.setAdapter(mSectionsPagerAdapter); tabLayout.setupWithViewPager(mViewPager); mViewPager.setCurrentItem(mTabs.indexOf(currentTab), false); return true; }else return super.onOptionsItemSelected(item); } /** * A placeholder fragment containing a simple view. */ public static class PlaceholderFragment extends Fragment { /** * The fragment argument representing the section number for this * fragment. */ private static final String ARG_SECTION_NUMBER = "section_number"; public PlaceholderFragment() { } /** * Returns a new instance of this fragment for the given section * number. */ public static PlaceholderFragment newInstance(int sectionNumber) { PlaceholderFragment fragment = new PlaceholderFragment(); Bundle args = new Bundle(); args.putInt(ARG_SECTION_NUMBER, sectionNumber); fragment.setArguments(args); return fragment; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.e("TestViewPager", "onCreate"+getArguments().getInt(ARG_SECTION_NUMBER)); } @Override public void onDestroy() { super.onDestroy(); Log.e("TestViewPager", "onDestroy"+getArguments().getInt(ARG_SECTION_NUMBER)); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); TextView textView = (TextView) rootView.findViewById(R.id.section_label); textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER))); return rootView; } } /** * A {@link FragmentPagerAdapter} that returns a fragment corresponding to * one of the sections/tabs/pages. */ public class SectionsPagerAdapter extends FragmentPagerAdapter { ArrayList tabs; public SectionsPagerAdapter(ArrayList tabs, FragmentManager fm) { super(fm); this.tabs = tabs; } @Override public Fragment getItem(int position) { // getItem is called to instantiate the fragment for the given page. // Return a PlaceholderFragment (defined as a static inner class below). return PlaceholderFragment.newInstance(tabs.get(position).id); } @Override public int getCount() { return tabs.size(); } @Override public long getItemId(int position) { return tabs.get(position).id; } @Override public CharSequence getPageTitle(int position) { return tabs.get(position).title; } } private static class Tab { String title; public int id; Tab(int id, String title){ this.id = id; this.title = title; } @Override public boolean equals(Object obj) { if(obj instanceof Tab){ return ((Tab)obj).id == id; }else{ return false; } } } } 

El código está en mi Github Gist .

    Intereting Posts