aggiungi e rimuovi dinamicamente la vista in viewpager


161

(Ho trovato una soluzione - consulta il mio post nella sezione Risposta di seguito).

Nella mia app, l'utente inizierà con una singola visualizzazione dei suoi dati. Vorrei aggiungere un ViewPager e consentire all'utente di aggiungere più visualizzazioni come desiderato. Come faccio a fare questo? (Non voglio usare FragmentPagerAdapter.)

Ho letto innumerevoli post e panoramiche ma mi manca ancora qualcosa. Ecco cosa penso di capire:

MainActivity crea un ViewPager e 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);      
}

Utilizzare un PagerAdapter per fornire i set di vista. Per questo sembra che ho bisogno di metodi per aggiungere e rimuovere viste, qualcosa del genere; ovviamente è necessario altro per dire che le cose di ViewPager sono cambiate e come mostrare le modifiche:

class MainPagerAdapter extends PagerAdapter
{
  // This holds all the currently displayable views, in order from left to right.
  private ArrayList<View> views = new ArrayList<View>();

  public void addView (View v, int position)
  {
    views.add (position, v);
  }

  public void removeView (int position)
  {
    views.remove (position);
  }
}

Inoltre, devo implementare i seguenti metodi vitali. Mi sono perso qui: cosa li chiama e cosa dovrebbero fare (ok, getCount è ovvio)?

  public object instantiateItem (ViewGroup pager, int position);
  public void destroyItem (ViewGroup, int, Object);
  public int getCount ();
  public boolean isViewFromObject (View, Object);
  • A cosa servono i parametri di ViewGroup - il gruppo contenitore non è lo stesso ViewPager?
  • Cosa fa isViewFromObject: in che modo un oggetto viene associato a una vista?
  • Devo chiamare startUpdate e finishUdate quando aggiungo o rimuovo le viste?

Grazie.

Risposte:


277

Dopo aver capito quali metodi ViewPager sono chiamati da ViewPager e quali sono per altri scopi, ho trovato una soluzione. Lo presento qui poiché vedo che molte persone hanno lottato con questo e non ho visto altre risposte pertinenti.

Innanzitutto, ecco il mio adattatore; si spera che i commenti all'interno del codice siano sufficienti:

public class MainPagerAdapter extends PagerAdapter
{
  // This holds all the currently displayable views, in order from left to right.
  private ArrayList<View> views = new ArrayList<View>();

  //-----------------------------------------------------------------------------
  // 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.
}

Ed ecco alcuni frammenti di codice che mostrano come utilizzare l'adattatore.

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);
  }
}

Infine, è possibile utilizzare quanto segue per il activity_main.xmllayout:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

</android.support.v4.view.ViewPager>

grazie per il post .. Ho già fatto questa cosa ma ho una domanda che è: come cancellare il valore getCount?
Akarsh M

30
dopo di pagerAdapter.addView (v0, 0); aggiungere la seguente riga pagerAdapter.notifyDataSetChanged ();
David Toledo,

7
Quindi, in realtà, il trucco principale è rimuovere l'adattatore e ripristinarlo di nuovo ... geniale!
TacB0sS,

6
questo sembra promettente, qualcuno potrebbe dirmi qual è il modo di inizializzare il gonfiatore prima che venga utilizzato in questa linea FrameLayout v0 = (FrameLayout) inflater.inflate (R.layout.one_of_my_page_layouts, null);
Jeremy,

2
dovrebbe chiamare pagerAdapter.notifyDatasethanged (); dopo aver chiamato aggiungi vista all'adattatore per cercapersone.
Jayant Arora,

5

Stavo cercando una soluzione semplice per rimuovere dinamicamente le viste dal viewpager (senza frammenti). Pertanto, se disponi di alcune informazioni a cui appartengono le tue pagine, puoi impostarle su Visualizza come tag. Proprio così (codice adattatore):

@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;
}

Devi solo rimuovere le tue informazioni da mMessages e quindi chiamare il notifyDataSetChanged()tuo adattatore. Cattive notizie non c'è animazione in questo caso.


2

Ci sono alcune discussioni su questo argomento

Anche se lo vediamo spesso, l'utilizzo POSITION_NONEnon sembra essere la strada da percorrere in quanto è molto inefficiente dal punto di vista della memoria.

Qui in questa domanda, dovremmo considerare l'utilizzo dell'approccio di Alvaro :

... è un setTag()metodo per instantiateItem()creare un'istanza di una nuova vista. Quindi, invece di utilizzare notifyDataSetChanged(), è possibile utilizzare findViewWithTag()per trovare la vista che si desidera aggiornare.

Ecco una risposta SO con codice basato su questa idea


2

Ho fatto un programma simile. spero che questo ti possa aiutare. Nella sua prima attività è possibile selezionare quattro dati della griglia. Nella prossima attività, c'è un cercapersone di visualizzazione che contiene due pagine obbligatorie e ci saranno altre 4 pagine, che saranno visibili corrispondenti ai dati della griglia selezionati.

Di seguito è la MainActivity di attività principale

    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<String> frags = new ArrayList<String>();
    ArrayList<FragmentArray> fragmentArray = new ArrayList<FragmentArray>();
    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);
            }
        });
    }
}

Qui TabFragment1, TabFragment2 ecc. Sono frammenti da visualizzare sul viewpager. E non sto mostrando i layout poiché non rientrano nell'ambito di questo progetto.

MainActivity intende 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<String > selectedPort = new ArrayList<String>();

        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<String> values;

    public PagerAdapter(FragmentManager fm, int NumOfTabs, List<String> 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();
    }
}

Layout per main2activity acticity_main2.xml

    <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/main_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fitsSystemWindows="true">

        <android.support.design.widget.AppBarLayout
            android:id="@+id/MyAppbar"
            android:layout_width="match_parent"
            android:layout_height="256dp"
            android:fitsSystemWindows="true">

            <android.support.design.widget.CollapsingToolbarLayout
                android:id="@+id/collapse_toolbar"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                app:layout_scrollFlags="scroll|exitUntilCollapsed"
                android:background="@color/material_deep_teal_500"
                android:fitsSystemWindows="true">

                <ImageView
                    android:id="@+id/bgheader"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scaleType="centerCrop"
                    android:fitsSystemWindows="true"
                    android:background="@drawable/screen"
                    app:layout_collapseMode="pin" />

                <android.support.v7.widget.Toolbar
                    android:id="@+id/MyToolbar"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    app:layout_collapseMode="parallax" />





            </android.support.design.widget.CollapsingToolbarLayout>

        </android.support.design.widget.AppBarLayout>

        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:id="@+id/nested"
            android:layout_height="match_parent"
            android:layout_gravity="fill_vertical"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <android.support.design.widget.TabLayout
            android:id="@+id/tab_layout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/MyToolbar"
            android:background="?attr/colorPrimary"
            android:elevation="6dp"
            android:minHeight="?attr/actionBarSize"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>


        <android.support.v4.view.ViewPager
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/view_pager"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

        </android.support.v4.view.ViewPager>
    </LinearLayout>


        </android.support.v4.widget.NestedScrollView>

    </android.support.design.widget.CoordinatorLayout>

Mainactivity layout
activity_main.xml

        <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.example.jeffy.viewpagerapp.MainActivity"
    tools:showIn="@layout/activity_main">


<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <GridView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/gridView1"
        android:numColumns="2"
        android:gravity="center"
        android:columnWidth="100dp"
        android:stretchMode="columnWidth"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

    </GridView>

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="SAVE"
        android:id="@+id/button" />

</LinearLayout>




</RelativeLayout>

Spero che questo possa aiutare qualcuno ... Fai clic sul pulsante per favore se questo ti ha aiutato


Grazie. Ho anche avuto problemi con la vista di scorrimento nidificata e ora ho risolto anche.
Filip Luchianenco,

2

Ecco una soluzione alternativa a questa domanda. Il mio adattatore:

    private class PagerAdapter extends FragmentPagerAdapter implements 
                    ViewPager.OnPageChangeListener, TabListener {

    private List<Fragment> mFragments = new ArrayList<Fragment>();
    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);
    }
}

Codice da rimuovere e aggiungere in modo dinamico

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

pagerAdapter.addPage(pass your fragment);

Dopo il consiglio di Peri Hartman, ha iniziato a funzionare dopo aver impostato l'adattatore ViewPager null do e reinserito l'adattatore dopo aver rimosso le viste. Prima di questo, la pagina 0 non mostrava i contenuti della sua lista.

Grazie.


1
La sua non funziona !!!! Prova a scrivere il codice completo, che sarebbe utile per le persone in cerca di soluzione.
ManishSB,

1

Ho creato una libreria PagerAdapters personalizzata per modificare dinamicamente gli elementi in PagerAdapters.

Puoi modificare gli elementi in modo dinamico come segue usando questa libreria.

@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<String> {

    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 libreria Thils supporta anche le pagine create da Fragments.


0

Per rimuoverlo puoi usarlo direttamente:

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

fragment è il frammento che vuoi rimuovere.


-1

Trovo una buona soluzione per questo problema, questa soluzione può farlo funzionare e non è necessario ricreare i frammenti.
Il mio punto chiave è:

  1. imposta ViewPager ogni volta che elimini o aggiungi Tab (Frammento).
  2. Sostituisci il metodo getItemId, restituisce un ID specifico anziché la posizione.

Codice sorgente

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 z8888q@gmail.com 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<Tab> 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<Tab> 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<Tab> tabs;

        public SectionsPagerAdapter(ArrayList<Tab> 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;
            }
        }
    }
}

Il codice è nel mio Github Gist .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.