2012-12-01 19 views
130

(I zorientowali się rozwiązanie. - patrz mój post w sekcji odpowiedzi poniżej)dynamicznie dodawać i usuwać widok na viewpager

W mojej aplikacji, użytkownik zacznie z jednym widoku swoich danych. Chciałbym dodać ViewPager i zezwolić użytkownikowi na dodanie kolejnych widoków według potrzeb. Jak mam to zrobic? (Nie chcę używać FragmentPagerAdapter.)

Czytałem niezliczone posty i przeglądy, ale nadal czegoś brakuje. Oto, co myślę, że rozumiem:

główną działalność tworzy ViewPager i 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);  
} 

Użyj PagerAdapter dostarczyć zestawy widzenia. Do tego wydaje mi się, że potrzebuję metod dodawania i usuwania widoków, czegoś takiego; oczywiście bardziej jest potrzebne, aby powiedzieć rzeczy ViewPager zmieniła i jak pokazać zmiany:

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

Ponadto, muszę wdrożyć następujące metody Vitual. Zgubiłem się tutaj - co je nazywa i co mają robić (ok, getCount jest oczywisty)?

public object instantiateItem (ViewGroup pager, int position); 
    public void destroyItem (ViewGroup, int, Object); 
    public int getCount(); 
    public boolean isViewFromObject (View, Object); 
  • Jakie są ViewGroup params dla - nie zawierający grupa sama ViewPager?
  • Co robi zadanie isViewFromObject - w jaki sposób obiekt zostaje skojarzony z widokiem w pierwszej kolejności?
  • Czy powinienem wywoływać funkcję startUpdate i finishUdate podczas dodawania lub usuwania widoków?

Dzięki.

Odpowiedz

235

Po ustaleniu, które metody ViewPager są wywoływane przez ViewPager i które są do innych celów, wymyśliłem rozwiązanie. Przedstawiam to tutaj, ponieważ widzę, że wiele osób borykało się z tym problemem i nie widziałem żadnych innych istotnych odpowiedzi.

Po pierwsze, oto mój adapter; mam nadzieję, że komentarze w kodzie są wystarczające:

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

A oto kilka wycinków kodu pokazujących, jak korzystać z adaptera.

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

Wreszcie, można użyć następujących dla układu activity_main.xml:

<?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> 
+0

dzięki za post .. Już zrobiłem to, ale mam zapytanie: Jak wyczyścić wartość getCount? –

+0

getCount() odzwierciedla liczbę fragmentów. Tak więc, jeśli usuniesz wszystkie fragmenty, getCount() zwróci 0. –

+26

po pagerAdapter.addView (v0, 0); dodaj następujący wiersz pagerAdapter.notifyDataSetChanged(); –

2

Oto alternatywne rozwiązanie na to pytanie. Mój adapter:

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

Kod usunąć i dodać dynamicznie

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

pagerAdapter.addPage(pass your fragment); 

Po radą Peri Hartman, zaczęło działać po tym, jak ustawić zerowy zrobić adapter ViewPager i ponownie umieścić zasilacz po usunięte widoki . Wcześniej strona 0 nie wyświetlała zawartości listy.

Dzięki.

+1

To nie działa !!!! Spróbuj napisać pełny kod, który byłby pomocny dla osób szukających rozwiązania. – ManishSB

5

Szukałem prostego rozwiązania, aby dynamicznie usuwać widoki z viewpager (bez fragmentów). Tak więc, jeśli masz jakieś informacje, do których należą twoje strony, możesz ustawić je jako Wyświetl jako tag. Podobnie jak ten (kod adaptera):

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

Trzeba tylko usunąć swoje dane z mMessages, a następnie zadzwonić notifyDataSetChanged() dla adaptera. Złe wieści nie ma w tym przypadku animacji.

2

Istnieje sporo dyskusji wokół tego tematu

Mimo to widzimy często, używając POSITION_NONE nie wydaje się być droga idź jako jest bardzo nieefektywna pod względem pamięci.

Tu, w tej kwestii, należy rozważyć użycie Alvaro's approach:

... jest setTag() metody w instantiateItem() przy uruchamianiu nowego widoku. Zamiast tego, zamiast używać notifyDataSetChanged(), możesz użyć findViewWithTag(), aby znaleźć widok, który chcesz zaktualizować.

Oto SO answer with code na podstawie tego pomysłu

2

Zrobiłem podobny program. mam nadzieję, że to ci pomoże. W swojej pierwszej aktywności można wybrać cztery dane siatki. Przy następnej czynności znajduje się pager widoku, który zawiera dwie obowiązkowe strony. Będzie tam też 4 kolejne strony, które będą widoczne zgodnie z wybranymi danymi siatki.

Poniżej znajduje się mainactivty główną działalność

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

Tutaj TabFragment1, TabFragment2 itp to fragment ma być wyświetlany na viewpager.And ja nie pokazując układów, ponieważ są one poza zakres tego projektu.

główną działalność będzie zamiarem 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 dla 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> 

Mam nadzieję, że to pomogłoby komuś ... Kliknij przycisk w górę, jeśli to pomogło

+0

Dzięki. Miałem także problemy z zagnieżdżonym przewijaniem i teraz to naprawiłem. – FilipLuch

2

Utworzyłem custom PagerAdapters library, aby dynamicznie zmieniać pozycje w PagerAdapters.

Możesz zmieniać elementy dynamicznie jak na poniższej liście, używając tej biblioteki.

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

Biblioteka Thils obsługuje również strony utworzone przez Fragments.

0

Aby usunąć ten można wykorzystać bezpośrednio:

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

fragment jest fragment, który chcesz usunąć.

0

Znajduję dobre rozwiązanie dla tego problemu, to rozwiązanie może sprawić, że będzie działać i nie będzie potrzeby ponownego tworzenia Fragmentów.
Moje kluczowym punktem jest:

  1. setup ViewPager za każdym razem usunąć lub dodać Tab (Fragment).
  2. Zastępuje metodę getItemId, zwraca konkretny identyfikator zamiast pozycji.

kod źródłowy

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

Code jest moim Github Gist.

Powiązane problemy