【问题标题】:ViewPager - In the fragment pages create a new fragmentViewPager - 在片段页面中创建一个新片段
【发布时间】:2017-09-03 13:37:15
【问题描述】:

我有一个ViewPager 活动。 ViewPager 也有一个 TabLayout 和 3 个选项卡:FragmentAFragmentBFragmentC,每个对应于要在 ViewPager 中显示的 3 个页面之一。在FragmentB 里面虽然我会有一个按钮。我现在需要能够单击此按钮并创建一个新片段FragmentD,它将取代FragmentB。这个新片段需要有一个带有后退箭头的操作栏,以便它可以返回到FragmentB。在所有这些过程中,选项卡仍应显示FragmentB 是活动选项卡。我已经研究过嵌套片段,但我无法让它工作。我还尝试从我的片段创建对我的 viewpager 活动的引用,并使用我的新片段的位置调用 getItem 方法,但这不起作用。这是我现在的代码。这是一个创建ViewPager 的活动。在ViewPager3 内部创建了片段,同时还创建了TabLayout

public class MyActivity extends AppCompatActivity {

    ViewPager viewPager;
    PagerAdapter pagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my);

        // Get the ViewPager and set it's PagerAdapter so that it can display items
        viewPager = (ViewPager) findViewById(R.id.viewpager);
        pagerAdapter = new PagerAdapter(getSupportFragmentManager(), MyActivity.this);
        viewPager.setAdapter(pagerAdapter);

        viewPager.setOffscreenPageLimit(3);

        // Give the TabLayout the ViewPager
        TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);
        tabLayout.setupWithViewPager(viewPager);

        // Iterate over all tabs and set the custom view
        for (int i = 0; i < tabLayout.getTabCount(); i++) {
            TabLayout.Tab tab = tabLayout.getTabAt(i);
            tab.setCustomView(pagerAdapter.getTabView(i));
        }
    }

    class PagerAdapter extends FragmentPagerAdapter {

        String tabTitles[] = new String[] { "FragmentA", "FragmentB", "FragmentC", };
        public Fragment[] fragments = new Fragment[tabTitles.length];
        Context context;

        public PagerAdapter(FragmentManager fm, Context context) {
            super(fm);
            this.context = context;
        }

        @Override
        public int getCount() {
            return tabTitles.length;
        }

        @Override
        public Fragment getItem(int position) {

            switch (position) {
                case 0:
                    return new MyFragmentA();
                case 1:
                    return new MyFragmentB(); //Inside of fragment B I will have a button. If that button is clicked this fragment needs to be replaced with a new fragment temporarliy, FRAGMENTD, which will have an anctionbar to be able to go back to fragment B. The tabs should show that the user is technically still in FragmentB tab. 
                case 2:
                    return new MyFragmentC();
            }

            return null;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            // Generate title based on item position
            return tabTitles[position];
        }

        public View getTabView(int position) {
            View tab = LayoutInflater.from(MyActivity.this).inflate(R.layout.custom_tab, null);
            TextView tv = (TextView) tab.findViewById(R.id.custom_text);
            tv.setText(tabTitles[position]);
            return tab;
        }

        //This populates your Fragment reference array:
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
            fragments[position]  = createdFragment;
            return createdFragment;
        }
    }


}

【问题讨论】:

  • 您每次都返回片段的新实例,只需将其存储在列表中并以适当的位置返回
  • @Nas 抱歉,我不确定你的意思?所以我创建了 3 个片段,例如 new MyFragmentC()。您是说在此处创建第 4 个片段并将其放入案例 3 中,如案例 3: return MyFragmentD() 吗?如果是这样,我如何从 MyFragmentB 获取这个新片段并使其成为“子”,以便我可以导航回来?

标签: android android-layout android-fragments android-viewpager material-design


【解决方案1】:

我认为这是有目的的?

public Fragment[] fragments = new Fragment[tabTitles.length];

您只分配它,但从不使用它的元素。


您可以像这样使用它来懒惰地创建片段

@Override
public Fragment getItem(int position) {
    Fragment f = fragments[position];

    if (f == null) {
        switch (position) {
            case 0:
                f = new MyFragmentA();
                break;
            case 1:
                f = new MyFragmentB();
                break;
            case 2:
                f = new MyFragmentC();
                break;
        }
        fragments[position] = f;
    }

    return f;
}

或者看这里,这没有正确实现,因为super.instantiateItem(container, position) 从未创建您想要的三个 Fragment 类中的任何一个。

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
        fragments[position]  = createdFragment;
        return createdFragment;
    }

所以,我会在这里删除该方法

虽然我会有一个按钮,但在 FragmentB 的内部。我现在需要能够单击此按钮并创建一个新片段 FragmentD,它将取代 FragmentB...在所有这些过程中,选项卡仍应显示 FragmentB 是活动选项卡。

您需要从FragmentB 回调到 Activity

How to implement OnFragmentInteractionListener

然后,在 Activity 回调中,您创建并可能“替换第 2 页”ViewPager

这个新片段需要有一个带有后退箭头的操作栏,以便它可以返回到 FragmentB。

您还需要在该界面中使用第二种方法来表示 onBackPressed 以在 ViewPager 中重新创建和加载 FragmentB 而不是 FragmentD

【讨论】:

  • 所以在 MyFragmentB 我有一个按钮,需要调用一个片段,这是我的问题。当调用它时,我需要加载 MyFragmentD。当它被加载时,它应该充当 MyFragmentB 的“子级”,因此该选项卡仍然显示 MyFragmentB 已被选中,但显示的是 MyFragmentD。这个片段还需要能够有一个返回按钮才能返回到 MyFragmentB。
  • 好的,所以 1) FragmentB 可以有一个 FragementInteractionListener。 2) 父 Activity 需要创建这个 FragmentD 并将其添加到某个视图中。除非您通过代码明确移动 ViewPager 选择,否则 FragmentB 当然仍会被选中。
  • 我试图用 FragmentTrasactions 来“替换”页面查看器的第 2 页,但无法正常工作。我将如何替换此页面?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-23
  • 1970-01-01
  • 2013-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多