简体   繁体   English

使用 FragmentPagerAdapter 替换 ViewPager 中的片段

[英]Replace a Fragment in a ViewPager using FragmentPagerAdapter

I am using a ViewPager with 4 pages, and I'm looking for an efficient way to replace/switch between fragments in each page.我正在使用一个有 4 个页面的 ViewPager,我正在寻找一种有效的方法来替换/切换每个页面中的片段。

This is the interaction pattern that I'm trying to create:这是我要创建的交互模式:

  1. User presses a button on a page that currently holds fragment A用户按下当前包含片段 A 的页面上的按钮
  2. Fragment A is swapped out for some new fragment B片段 A 换出一些新的片段 B
  3. The user does some work in fragment B, and then presses a button when he/she is done用户在片段 B 中做了一些工作,然后在他/她完成后按下按钮
  4. Fragment B is removed, and is replaced by fragment A (the original fragment)片段 B 被删除,并由片段 A(原始片段)替换

I've found a way to do this, but it seems to have significant flaws.我找到了一种方法来做到这一点,但它似乎有重大缺陷。 The solution involves removing the original fragment, and then overriding getItemPosition (essentially the method described in this related question ):解决方案涉及删除原始片段,然后重写getItemPosition (本质上是此相关问题中描述的方法):

//An array to keep track of the currently visible fragment in each page
private final Fragment[] activeFragments= new Fragment[4];

public void openFragmentB(ViewPager pager, int position) {

    startUpdate(pager);

    //Remove the original fragment
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    transaction.remove(activeFragments[position]);
    transaction.commit();

    //Create a new tile search fragment to replace the original fragment
    activeFragments[position] = FragmentB.newInstance();
    pageStates[position] = PageState.STATE_B;

    finishUpdate(pager);
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {

    //If the main fragment is not active, return POSITION_NONE
    if(object instanceof FragmentA) {
        FragmentA a = (FragmentA) object;
        if(pageStates[a.getPosition()] != PageState.STATE_A) {
            return POSITION_NONE;
        }
    }

    //If the secondary fragment is not active, return POSITION_NONE
    if(object instanceof FragmentB) {
        FragmentB b = (FragmentB) object;
        if(pageStates[b.getPosition()] != PageState.STATE_B) {
            return POSITION_NONE;
        }
    }

    return POSITION_UNCHANGED;
}

This method works, but has undesirable side effects.这种方法有效,但有不良副作用。 Removing the fragment and setting it's position to POSITION_NONE causes the fragment to be destroyed.删除片段并将其 position 设置为 POSITION_NONE 会导致片段被销毁。 So when the user finishes using FragmentB, I would need to create a new instance of FragmentA instead of reusing the original fragment.因此,当用户结束使用 FragmentB 时,我需要创建一个新的 FragmentA 实例,而不是重新使用原始片段。 The main fragments in the pager (FragmentA in this example) will contain relatively large database backed lists, so I want to avoid recreating them if possible.寻呼机中的主要片段(本例中的 FragmentA)将包含相对较大的数据库支持列表,因此我希望尽可能避免重新创建它们。

Essentially I just want to keep references to my 4 main fragments and swap them in and out of pages without having to recreate them every time.本质上,我只想保留对我的 4 个主要片段的引用,并将它们换入和换出页面,而不必每次都重新创建它们。 Any ideas?有任何想法吗?

A simple way to avoid recreating your Fragments is to keep them as member variables in your Activity.避免重新创建 Fragment 的一种简单方法是将它们作为成员变量保存在 Activity 中。 I do this anyway in conjunction with onRetainCustomNonConfigurationInstance() order to retain my fragments during configuration changes (mostly screen rotation).无论如何,我都会结合 onRetainCustomNonConfigurationInstance() 来执行此操作,以便在配置更改(主要是屏幕旋转)期间保留我的片段。 I keep my Fragments in a 'retainer' object since onRetainCustomNonConfigurationInstance only returns a single object.我将我的片段保存在“固定器”object 中,因为 onRetainCustomNonConfigurationInstance 只返回一个 object。

In your case, instead of calling Fragment.newInstance() all the time, just check to see if the fragments contained in the retainer object is null before creating a new one.在您的情况下,不是一直调用 Fragment.newInstance() ,而是在创建新片段之前检查保留器 object 中包含的片段是否为 null 。 If it isn't null, just re-use the previous instance.如果不是 null,只需重新使用之前的实例即可。 This checking should happen in your ViewPager adapter's getItem(int) method.这种检查应该发生在您的 ViewPager 适配器的 getItem(int) 方法中。

In effect, doing this basically means you are handling whether or not Fragments are recycled when getItem is called, and overriding the getItemPosition(Object) method to always return POSITION_NONE when for relevant Segments.实际上,这样做基本上意味着您正在处理调用 getItem 时是否回收 Fragments,并覆盖 getItemPosition(Object) 方法以在相关 Segments 时始终返回 POSITION_NONE。

FragmentPagerAdapter provides an overrideable method called getItemId that will help you here. FragmentPagerAdapter 提供了一个名为getItemId的可重写方法,它将在此处为您提供帮助。

If you assign a unique long value to each Fragment in your collection, and return that in this method, it will force the ViewPager to reload a page when it notices the id has changed.如果您为集合中的每个 Fragment 分配一个唯一的 long 值,并在此方法中返回该值,它将强制 ViewPager 在发现 id 已更改时重新加载页面。

Better late than never, I hope this helps somebody out there!迟到总比不到好,我希望这可以帮助那里的人!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用fragmentPagerAdapter在ViewPager中替换另一个片段 - How to replace a fragment from another in a ViewPager with fragmentPagerAdapter 使用FragmentPagerAdapter在viewpager中添加/删除片段 - add/remove fragment in viewpager using FragmentPagerAdapter 用FragmentPagerAdapter作为片段本身的ViewPager? - ViewPager with FragmentPagerAdapter as a fragment itself? 第一次加载活动时,使用 FragmentPagerAdapter 的 ViewPager 中的片段为空白 - Fragment in ViewPager using FragmentPagerAdapter is blank the first time activity is loaded 使用ViewPager或FragmentPagerAdapter查找显示的片段 - Finding Displayed Fragment with ViewPager or FragmentPagerAdapter 使用FragmentPagerAdapter和ViewPager在Fragment中启动新Activity时的NullPE - NullPE on starting new Activity in Fragment using FragmentPagerAdapter with ViewPager 使用 FragmentPagerAdapter 的 ViewPager 中的片段在第二次查看时为空白 - Fragment in ViewPager using FragmentPagerAdapter is blank the second time it is viewed 使用FragmentPagerAdapter具有3个片段的Viewpager - Viewpager with 3 fragments using FragmentPagerAdapter 在片段中使用FragmentPagerAdapter - Using FragmentPagerAdapter in a Fragment 替换FragmentPagerAdapter内部的部分片段 - Replace part of fragment inside of FragmentPagerAdapter
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM