【问题标题】:Replacing a fragment in another fragment in a ViewPager在 ViewPager 中替换另一个片段中的片段
【发布时间】:2013-10-14 17:42:34
【问题描述】:

我对 Android 编程完全陌生,我很难让它工作(我很接近,但我错过了一些重要的东西)。

我有一个名为 PatientPagerActivity 的活动,它通过患者信息片段进行分页。在每个 PatientFragment 中,我都有一个按钮,单击时,除了提供患者信息外,还会提供一些杂项信息。所以我打算在 PatientPagerActivity 中做的是将 PatientFragment 替换为 PatientWithMiscFragment (其中包含患者信息和杂项部分)。

activity_pager.xml 文件:

<android.support.v4.view.ViewPager 
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:id="@+id/viewPager"
  android:layout_width="match_parent"
  android:layout_height="match_parent" />

PatientPagerActivity 文件:

public class PatientPagerActivity extends FragmentActivity
implements PatientPagerActivityCallbacks {
private ViewPager mViewPager;
private List<Patient> mQuizProblemList;

private int mCurrentIndex;
private List<PatientFragment> mPatientFragmentList;
private List<PatientWithMiscFragment> mPatientWithMiscFragmentList;

private static final String EMPTY_TEXT = "";


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_pager);

    mViewPager = (ViewPager) findViewById(R.id.viewPager);

    mPatientList = 
               PatientManager.getInstance(this).getPatients();

    FragmentManager fm = getSupportFragmentManager();
    mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) {
        @Override
        public int getCount() {
            return mPatientList.size();
        }

        @Override
        public Fragment getItem(int location) {
            Patient patient = mPatientList.get(location);
            PatientFragment fragment = 
                                    PatientFragment.newInstance(patient);
            PatientWithMiscFragment miscFragment = 
                                    PatientWithMiscFragment.newInstance(patient);

            if(mPatientFragmentList== null) {
                mPatientFragmentList = 
                                          new ArrayList<PatientFragment>();
            }
            mPatientFragmentist.add(fragment);

            if(mPatientWithMiscFragmentList == null) {
                mPatientWithMiscFragmentList = 
                                       new ArrayList<PatientWithMiscFragment>();
            }
            mPatientWithMiscFragmentList.add(miscFragment);

            return fragment;
        }
    });

    mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageSelected(int counter) {
            setTitle("Patient: " + (counter + 1));
            mCurrentIndex = counter;
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
            hideMiscInformation();
        }
    });

    long patientID =
                   getIntent().getLongExtra(PatientFragment.EXTRA_PATIENT_ID, -1);
    for(int counter = 0; counter < mPatientList.size(); counter++) {
        if(mPatientList.get(counter).getPatient().getID() == patientID) {
            mViewPager.setCurrentItem(counter);
            setTitle("Patient: " + (counter + 1));
            mCurrentIndex = counter;
            break;
        }
    }
}

@Override
public void onMiscSelected() {
    if(findViewById(R.id.viewPager) != null) {
        FragmentManager fm  = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();

                    //Find the current PatientInformation
        Fragment oldFragment = mPatientFragmentList.get(mCurrentIndex);
        //And Remove it 
        if(oldFragment != null) {
            ft.remove(oldFragment);
            ft.commit();
        }
                    //Notify the adapter that data set has changed.
        notifyAdapterDataSetChanged();

        ft = fm.beginTransaction();
                    //Replace it with the corresponding fragment that also has misc
        ft.add(R.id.viewPager,
                           mPatientWithMiscFragmentList.get(mCurrentIndex));
        ft.commit();    
        notifyAdapterDataSetChanged();
    }
}

public void hideMiscInformation() {
    if(findViewById(R.id.viewPager) != null) {
        FragmentManager fm  = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();

        //Remove the misc information
        Fragment oldMiscFragment =
                         fm.findFragmentById(R.id.viewPager);           
        if(oldMiscFragment != null) {
            ft.remove(oldMiscFragment);
            ft.commit();
        }
                    //Replace it with ONLY the patient information.
                    ft = fm.beginTransaction();
        ft.add(R.id.viewPager, mPatientFragmentList.get(mCurrentIndex));
        ft.commit();
        notifyAdapterDataSetChanged();
    }
}
    :
    :
}

当用户对杂项信息感兴趣时,PagerActivity 会发生回调,onMiscSelected() 会将 PatientFragment 替换为 PatientWithMiscFragment。但是,就我而言,这并没有发生。

请帮我确定我哪里出错了。

谢谢!

【问题讨论】:

    标签: android android-viewpager fragment fragmentstatepageradapter


    【解决方案1】:

    正如其他帖子中所记录的,当您处理 FragmentStatePageAdapter 时,您需要注意以下事项: 1. 用新片段替换旧片段后,通过调用 FragmentStatePageAdapter.notifyDataSetChanged() 通知适配器底层数据已更改。 2. 您需要覆盖 getItemPosition()。在这种方法中,如果位于特定位置的片段没有发生变化,如果返回 POSITION_NONE,则会得到不正确的结果。

    修改后的代码如下:

    public class PatientPagerActivity extends FragmentActivity implements PatientPagerActivityCallbacks {
        private ViewPager mViewPager;
        private List<Patient> mPatientList;
    
        private int mCurrentIndex;
        private List<PatientFragment> mPatientFragmentList;
        private List<PatientWithMiscFragment> mPatientWithMiscFragmentList;
    
        private static final String EMPTY_TEXT = "";
    
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_pager);
    
            mViewPager = (ViewPager) findViewById(R.id.viewPager);
    
            mPatientList = 
                    PatientManager.getInstance(this).getPatients();
    
            FragmentManager fm = getSupportFragmentManager();
            mViewPager.setAdapter(new FragmentStatePagerAdapter(fm) {
                @Override
                public int getCount() {
                    return mPatientList.size();
                }
    
                @Override
                public Fragment getItem(int location) {
                    Patient patient = mPatientList.get(location);
                    PatientFragment fragment = 
                            PatientFragment.newInstance(patient);
                    PatientWithMiscFragment miscFragment = 
                            PatientWithMiscFragment.newInstance(patient);
    
                    if(mPatientFragmentList== null) {
                        mPatientFragmentList = 
                                new ArrayList<PatientFragment>();
                    }
                    mPatientFragmentist.add(location, fragment);
    
                    if(mPatientWithMiscFragmentList == null) {
                        mPatientWithMiscFragmentList = 
                                new ArrayList<PatientWithMiscFragment>();
                    }
                    mPatientWithMiscFragmentList.add(location, miscFragment);
    
                    return fragment;
                }
                @Override
                public int getItemPosition(Object object) {
                    PatientFragment fragment = (PatientFragment) object;
                    if(mPatientFragmentList.get(mCurrentIndex).getCurrentPatient() != null && 
                        fragment.getCurrentPatient().getID().
                            equals(mPatientFragmentList.get(
                            mCurrentIndex).getCurrentPatient().getID())) {
                        return POSITION_NONE;
                    } else if(mPatientFragmentList.get(mCurrentIndex).getCurrentPatient() == null) {
                        return POSITION_NONE;
                    } else {
                        return POSITION_UNCHANGED;
                    }
    
                }
            });
    
            mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
                @Override
                public void onPageSelected(int counter) {
                    setTitle("Patient: " + (counter + 1));
                    mCurrentIndex = counter;
                }
    
                @Override
                public void onPageScrolled(int arg0, float arg1, int arg2) {
                }
    
                @Override
                public void onPageScrollStateChanged(int arg0) {
                    hideMiscInformation();
                }
            });
    
            long patientID =
                    getIntent().getLongExtra(PatientFragment.EXTRA_PATIENT_ID, -1);
            for(int counter = 0; counter < mPatientList.size(); counter++) {
                if(mPatientList.get(counter).getPatient().getID() == patientID) {
                    mViewPager.setCurrentItem(counter);
                    setTitle("Patient: " + (counter + 1));
                    mCurrentIndex = counter;
                    break;
                }
            }
        }
    
        @Override
        public void onMiscSelected() {
            if(findViewById(R.id.viewPager) != null) {
                FragmentManager fm  = getSupportFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
    
                //Find the current PatientInformation
                Fragment oldFragment = mPatientFragmentList.get(mCurrentIndex);
                //And Remove it 
                if(oldFragment != null) {
                    ft.remove(oldFragment);
                    ft.commit();
                }
    
    
                ft = fm.beginTransaction();
                //Replace it with the corresponding fragment that also has misc
                ft.add(R.id.viewPager,
                        mPatientWithMiscFragmentList.get(mCurrentIndex));
                ft.commit();    
                notifyAdapterDataSetChanged();
            }
        }
    
        public void hideMiscInformation() {
            if(findViewById(R.id.viewPager) != null) {
                FragmentManager fm  = getSupportFragmentManager();
                FragmentTransaction ft = fm.beginTransaction();
    
                //Remove the misc information
                Fragment oldMiscFragment =
                        fm.findFragmentById(R.id.viewPager);           
                if(oldMiscFragment != null) {
                    ft.remove(oldMiscFragment);
                    ft.commit();
                }
                //Replace it with ONLY the patient information.
                ft = fm.beginTransaction();
                ft.add(R.id.viewPager, mPatientFragmentList.get(mCurrentIndex));
                ft.commit();
                notifyAdapterDataSetChanged();
            }
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      您可以使用简单的“FrameLayout”来使用您的片段对其进行充气。所以最新的片段将替换之前的片段。

      here 是一个例子

      祝你好运!

      【讨论】:

      • Reiksiel,您是否建议将此作为 viewpager xml:schemas.android.com/apk/res/android" android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent">
      • 这个框架布局是如何使用的。我可能错了,但我认为 FragmentStatePageAdapter 管理所有片段。这些片段由 getItem(int location) 返回。
      • 对不起,我不清楚。获取 sample 以查看 FrameLayout 的运行情况。这种布局是每个孩子添加的最简单的布局,就像一个重叠的堆栈一样,您可以使用此行为在运行时添加片段。我对 FragmentStatePageAdapter 一无所知,抱歉,我只是向您展示我使用的解决方案。如果你不明白这个例子,我会帮助你好吗?祝你好运
      • 谢谢瑞克希尔。我相信 FragmentStatePageAdapter 的工作方式略有不同,但如果我遇到抽屉问题,您的解决方案将对我有所帮助。我让我的东西工作。我将在当天晚些时候发布解决方案。
      猜你喜欢
      • 2011-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多