2012-04-11 17 views
9

Görüntüleyici ve fragmanlarla adroid uygulaması yapıyorum. Fragmanı sayfalara dinamik olarak eklemek veya çıkarmak için bir seçenek yapmak istiyorum. Özel bir FragmentPagerAdapter vardır: I) (I notifyDataSetChanged bir NullPointerException var kaldırmak için denediğimde 0'a dışında herhangi parçasını kaldırmakparçaları görüntüleyiciye düzgün bir şekilde yerleştirin ve çıkarın

public class MyAdapter extends FragmentPagerAdapter implements TitleProvider{ 

    protected final List<PageFragment> fragments; 

    /** 
    * @param fm 
    * @param fragments 
    */ 
    public MyAdapter(FragmentManager fm, List<PageFragment> fragments) { 

     super(fm); 
     this.fragments = fragments; 
    } 

    public void addItem(PageFragment f){ 
     fragments.add(f); 
     notifyDataSetChanged(); 
    } 

    public void addItem(int pos, PageFragment f){ 
     for(int i=0;i<fragments.size();i++){ 
      if(i>=pos){ 
       getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(getFragmentTag(i))).commit(); 
      } 
     } 
     fragments.add(pos,f); 
     notifyDataSetChanged(); 
     pager.setAdapter(this); 
     pager.setCurrentItem(pos); 

    } 

    public void removeItem(int pos){ 
     getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(getFragmentTag(pos))).commit(); 
     for(int i=0;i<fragments.size();i++){ 
      if(i>pos){ 
       getSupportFragmentManager().beginTransaction().remove(getSupportFragmentManager().findFragmentByTag(getFragmentTag(i))).commit(); 
      } 
     } 
     fragments.remove(pos); 

     notifyDataSetChanged(); 
     pager.setAdapter(this); 
     if(pos<fragments.size()){ 
      pager.setCurrentItem(pos); 
     }else{ 
      pager.setCurrentItem(pos-1); 
     } 
    } 



    @Override 
    public Fragment getItem(int position) { 
     return fragments.get(position).toFragment(); 
    } 

    @Override 
    public int getCount() { 
     return fragments.size(); 
    } 

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

    private String getFragmentTag(int pos){ 
     return "android:switcher:"+R.id.pager+":"+pos; 
    } 

    public String getTitle(int position) { 
     String name = fragments.get(position).getName(); 
     if(name.equals("")) 
      return "- "+position+" -"; 
     return name; 
    } 
} 

; veya pager.setAdapter (bu) üzerinde; Eğer bildirimi açıklarsam.

Yeni bir sayfa eklemeye çalıştığımda NullPointerException da var. Yeni sayfayı listenin sonuna eklediğimde, iyi çalışıyor. Ben getFragmentTag(i-1) kullanırsanız Hatta fragments.add sonra bununla prospektüste parçaları readd çalıştı (pos, f)

for(int i=0;i<fragments.size();i++){ 
      if(i>=pos){ 
       getSupportFragmentManager().beginTransaction().add(fragments.get(i).toFragment(),getFragmentTag(i-1)).commit(); 
      } 
     } 

Ben nullpointer tekrar aldım. Sadece i kullanarak, fragmanın etiketini değiştiremediği için illegalalstateexception var. ne yanlış yapıyorum ve nasıl düzgün yapılabilir: beginTransaction().add(pager.getId,fragments.get(i).toFragment()) sayesinde

Sorum şu ... hala nullpointer mı? (Ve belki de: nedenleri NullPointerException zaman notyfyDataSetChanged() veri almak yerden)

cevap

1

Bir sigara fragmanı göre adaptör ile çalışan bir çözüm vardır. my post'a bir göz atın ve yardımcı olup olmadığına bakın.

+1

Bağlantı sadece cevaplar tavsiye edilmez. –

0

Sadece whitin a> = koşulunu kullanırsanız çalışır Benim için 0.

dışında herhangi parçasını kaldırmak removeItem en For döngüsü:

 if (i >= pos){ 
      fm.beginTransaction().remove(fragments.get(i).getFragment()).commit(); 
     } 
7

Bu, anlık hale getirildiğinde fragmanların etiketlenmesiyle problemin üstesinden geldiğim şeydi ve daha önce etiketlenmiş fragmanların çalışırken çalışırken ViewPager içindeki konumu değiştirememesidir.

java.lang.IllegalStateException: {: değiştiriciden: 2131034164: 3 4055f558 id = 0x7f050034 android}: android olduğuna: fragman MyFragment etiketini değiştirilemiyor değiştirici eklemek veya kaldırmak sayfaları, yani özel durum alma : 2131034164: 3 şimdi android: değiştirici: 2131034164: 4 Bu adaptör peşin tüm sayfaların bir listesi ile oluşturulur ve daha sonra setEnabled devre dışı bırakmak veya hangi gizler belirli sayfaları etkinleştirmek için (boolean etkin int pozisyonunu) kullanabilir

veya bu sayfaları ViewPager'da gösterir.

Tüm parçaların dahili bir listesini koruyarak, ancak ViewPager'ı görüntüleyerek ve etkinleştirilmiş parçaların konumlarını haritalayarak çalışır.

public class DynamicFragmentPagerAdapter extends FragmentPagerAdapter { 

    public final ArrayList<Fragment> screens = new ArrayList<Fragment>(); 

    private Context context; 
    private List<AtomicBoolean> flags = new ArrayList<AtomicBoolean>(); 

    public DynamicFragmentPagerAdapter(FragmentManager fm, Context context, List<Class<?>> screens) { 
     super(fm); 
     this.context = context; 

     for(Class<?> screen : screens) 
      addScreen(screen, null); 

     notifyDataSetChanged(); 
    } 

    public DynamicFragmentPagerAdapter(FragmentManager fm, Context context, Map<Class<?>, Bundle> screens) { 
     super(fm); 
     this.context = context; 

     for(Class<?> screen : screens.keySet()) 
      addScreen(screen, screens.get(screen)); 

     notifyDataSetChanged(); 
    } 

    private void addScreen(Class<?> clazz, Bundle args) { 
     screens.add(Fragment.instantiate(context, clazz.getName(), args)); 
     flags.add(new AtomicBoolean(true)); 
    } 

    public boolean isEnabled(int position) { 
     return flags.get(position).get(); 
    } 

    public void setEnabled(int position, boolean enabled) { 
     AtomicBoolean flag = flags.get(position); 
     if(flag.get() != enabled) { 
      flag.set(enabled); 
      notifyDataSetChanged(); 
     } 
    } 

    @Override 
    public int getCount() { 
     int n = 0; 
     for(AtomicBoolean flag : flags) { 
      if(flag.get()) 
       n++; 
     } 
     return n; 
    } 

    @Override 
    public Fragment getItem(int position) { 
     return screens.get(position); 
    } 

    @Override 
    public int getItemPosition(Object object) { 
     return POSITION_NONE; // To make notifyDataSetChanged() do something 
    } 

    @Override 
    public void notifyDataSetChanged() { 
     try { 
      super.notifyDataSetChanged(); 
     } catch (Exception e) { 
      Log.w("", e); 
     } 
    } 

    private List<Fragment> getEnabledScreens() { 
     List<Fragment> res = new ArrayList<Fragment>(); 
     for(int n = 0; n < screens.size(); n++) { 
      if(flags.get(n).get()) 
       res.add(screens.get(n)); 
     } 
     return res; 
    } 

    @Override 
    public Object instantiateItem(ViewGroup container, int position) { 
     // We map the requested position to the position as per our screens array list 
     Fragment fragment = getEnabledScreens().get(position); 
     int internalPosition = screens.indexOf(fragment); 
     return super.instantiateItem(container, internalPosition); 
    } 

    @Override 
    public CharSequence getPageTitle(int position) { 
     Fragment fragment = getEnabledScreens().get(position); 
     if(fragment instanceof TitledFragment) 
      return ((TitledFragment)fragment).getTitle(context); 
     return super.getPageTitle(position); 
    } 

    public static interface TitledFragment { 
     public String getTitle(Context context); 
    } 
} 
+0

Tamam çalışıyor, ancak "notifyDatasetChanged" çağrıldığında, her Fragment için yeni görünümler oluşturuyor, bu yüzden UI durumunu kaybediyorum. Bunu nasıl önleyebilirim? – WonderCsabo

İlgili konular