插入和删除碎片进入viewpager正确 [英] insert and remove fragments into viewpager properly

查看:258
本文介绍了插入和删除碎片进入viewpager正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在做一个的Adroid应用程序viewpager和片段。我想打一个选项,添加或删除片段页面寻呼机动态。我有一个自定义FragmentPagerAdapter:

I'm making an adroid application with viewpager and fragments. I want to make an option to add or remove fragment pages to the pager dynamically. I have a custom 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;
    }
}

我可以删除任何片段,除了0。当我尝试将其删除我得到一个NullPointerException异常的notifyDataSetChanged();或在pager.setAdapter(本);如果我注释掉的通知。

I can remove any fragment except the 0. when I try to remove it I got a NullPointerException on the notifyDataSetChanged(); or on the pager.setAdapter(this); if i comment out the notify.

我也得到一个NullPointerException异常,当我尝试插入新的页面。当我新的页面添加到列表中它的正常工作的结束。 我甚至尝试了fragments.add后,重新进行添加与该插入片段(POS,F)

I also got a NullPointerException when I try to insert a new page. When I add the new page to the end of the list it's working fine. I even tried to readd the fragments in the insert with this after the 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();
            }
        }

如果我用 getFragmentTag(I-1)我空指针再次得到。仅仅用我IllegalStateException异常,因为不能修改片段的标签。随着的BeginTransaction()。增加(pager.getId,fragments.get(我).toFragment())它仍然是空指针......

if I use getFragmentTag(i-1) I got nullpointer again. With using just i I got illegalstateexception because can not modify fragment's tag. With beginTransaction().add(pager.getId,fragments.get(i).toFragment()) it is still nullpointer...

我的问题是:我在做什么错了,怎么能做得好? (也许是:从那里 notyfyDataSetChanged()获取数据时导致NullPointerException异常)

My question is: what am I doing wrong, and how can it be done properly? (and maybe: from where notyfyDataSetChanged() get the data when causes nullpointerexception?)

推荐答案

这是我用来解决问题与碎片被标记实例化时,事实上,previously标记的片段无法在ViewPager当在改变位置尝试添加或删除页面,即得到了异常:

This is what I used to get around the problem with fragments being tagged when instantiated and the fact that previously tagged fragments cannot change position within the ViewPager when trying to add or remove pages, i.e. getting the exception:

java.lang.IllegalStateException:不能改变片段的标签   MyFragment {4055f558 ID = 0x7f050034机器人:切换:2131034164:3}:是   机器人:开关:2131034164:3现在安卓切换:2131034164:4

java.lang.IllegalStateException: Can't change tag of fragment MyFragment{4055f558 id=0x7f050034 android:switcher:2131034164:3}: was android:switcher:2131034164:3 now android:switcher:2131034164:4

该适配器与前期所有页面的列表,创建,然后你可以使用的setEnabled(INT位置,布尔启用)禁用或启用某些网页,它可以隐藏或显示这些网页中的ViewPager。

This adapter is created with a list of all pages upfront and you can then use setEnabled(int position, boolean enabled) to disable or enable certain pages which hides or shows these pages in the ViewPager.

它的工作原理维护所有片段的内部名单,但暴露于ViewPager并启用映射片段的位置而已。<​​/ P>

It works by maintaining an internal list of all fragments but exposing to the ViewPager and mapping the positions of enabled fragments only.

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

这篇关于插入和删除碎片进入viewpager正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆