2012-04-11 5 views
9

뷰 페이지와 프래그먼트로 adroid 애플리케이션을 만들고 있습니다. 프래그먼트 페이지를 페이저에 동적으로 추가하거나 제거하는 옵션을 만들고 싶습니다. 나는 사용자 정의 FragmentPagerAdapter이 : 나는) (필자는 notifyDataSetChanged에 NullPointerException이있어이를 제거하려고 할 때이 0을 제외한 모든 조각을 제거 할 수 있습니다뷰 파인더에 조각을 올바르게 삽입하고 조각을 제거하십시오.

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

을; 또는 pager.setAdapter (this); 내가 그 통보를 논평하면.

새 페이지를 삽입하려고하면 NullPointerException도 발생합니다. 새 페이지를 목록 끝에 추가하면 정상적으로 작동합니다. I는 getFragmentTag(i-1) 사용할 경우 I 심지어 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(); 
      } 
     } 

I는 nullpointer 다시 얻었다. i을 사용하면 조각의 태그를 수정할 수 없기 때문에 illegalstateexception을 얻었습니다. beginTransaction().add(pager.getId,fragments.get(i).toFragment())은 여전히 ​​nullpointer입니다 ...

내 질문은 : 무엇을 잘못하고 있으며 어떻게 제대로 할 수 있습니까? (그리고 아마도 : notyfyDataSetChanged()은 nullpointerexception이 발생했을 때 데이터를 얻습니다.)

답변

1

비 프래그먼트 기반 어댑터에서 작동하는 솔루션이 있습니다. my post을보고 도움이되는지 확인하십시오.

+1

링크 만 대답하는 것은 좋지 않습니다. –

0

난 그냥 whitin A> = 조건을 사용하는 경우 작동 나를 위해 0

제외한 모든 조각을 제거 할 수 있습니다 removeItem의에 대한 루프 :

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

이것은 인스턴스화 될 때 프래그먼트의 태그가 붙은 문제를 해결하기 위해 사용했던 것입니다. 이전 태그 된 프래그먼트는 시도 할 때 ViewPager 내의 위치를 ​​변경할 수 없습니다.

java.lang.IllegalStateException : {: 스위처 : 2131034164 : 3 4055f558 ID = 0x7f050034 안드로이드} : 안드로이드이었다 조각 MyFragment의 태그를 변경할 수 없습니다 스위처 추가 또는 제거 페이지, 즉 예외를 받고 : 2131034164 : 3 지금 안드로이드 : 스위처 : 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

관련 문제