2012-04-11 10 views
9

私はビューページとフラグメントでアイドロアプリケーションを作っています。フラグメントページをページャに動的に追加または削除するオプションを作成したいと思います。私は、カスタムFragmentPagerAdapterを持っている:フラグメントを適切にビューポートに挿入して削除してください

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

私はnotifyDataSetChanged(上のNullPointerExceptionを得、それを削除しようとすると、私は0以外の任意の断片を削除することができます)。またはpager.setAdapter(this);私が通知をコメントアウトする場合。

新しいページを挿入しようとすると、NullPointerExceptionも発生します。新しいページをリストの最後に追加すると、うまくいきます。私はgetFragmentTag(i-1)を使用している場合 私もfragments.addた後、これにインサート内の断片を再度追加しようとした(POSは、f)は

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

私がnullpointer再び得ました。 iを使用すると、フラグメントのタグを変更できないため、不正な例外が発生しました。 beginTransaction().add(pager.getId,fragments.get(i).toFragment())で、それはまだnullpointerです...

私の質問は何ですか:私は間違っていますか、それは適切に行うことができますか? (そして、おそらく:notyfyDataSetChanged()が原因でnullpointerexceptionが発生する場合は、データを取得しますか?

答えて

1

私は非フラグメントベースのアダプターで動作するソリューションを持っています。 my postを見て、役立つかどうかを見てください。

+1

リンクのみの回答はおすすめしません。 –

0

私はちょうどwhitin> =条件を使用している場合、それは動作します私にとっては0

以外の任意の断片を削除することができremoveItemのforループ:

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

これは、私がインスタンス化されたときにフラグメントがタグ付けされているという問題を回避するために使用したものです。以前にタグ付けされたフラグメントは、しようとするとViewPager内の位置を変更できません

java.lang.IllegalStateException::{:スイッチャー:2131034164:3 4055f558 ID = 0x7f050034アンドロイド}: アンドロイドた:フラグメント MyFragmentのタグを変更することはできませんスイッチャー追加または削除ページは、つまり例外を取得します3今アンドロイド:::2131034164スイッチャー:2131034164:4

このアダプターは、先行するすべてのページのリストを作成し、あなたがしている皮革特定のページを無効にしたり有効にするためには、setEnabled(int型の位置、ブール有効)を使用することができますViewPagerでこれらのページを表示します。

これは、すべてのフラグメントの内部リストを維持し、ViewPagerに公開し、有効なフラグメントの位置のみをマッピングすることによって機能します。

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

それは正常に動作しますが、 'notifyDatasetChanged'が呼び出されると、' Fragment'ごとに新しいビューが作成されるので、UIの状態が緩くなります。どうすればこれを防ぐことができますか? – WonderCsabo

関連する問題