如何在ViewPager2中按标签获取片段

时间:2019-11-23 17:21:25

标签: android android-viewpager2

有人告诉我使用FragmentStateAdapter的createFragment重写按索引获取当前片段。

这就是我的适配器的外观。

class AddRestaurantPagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    FragmentStateAdapter(fragmentManager, lifecycle) {
    private var fragments = listOf<Fragment>(
        FragmentA.newInstance(),
        FragmentB.newInstance(),
        FragmentC.newInstance(),
        FragmentD.newInstance()
    )

    override fun getItemCount() = 4
    override fun createFragment(position: Int) =
        fragments[position]

}

在我们对该活动/片段强制使用onSaveInstance / OnRestoreInstance之前,此方法可以正常工作。

ViewPager2在其上重新加载已经存在的片段,我们需要一种方法来访问它。 FragmentStateAdapter类中的以下LOC证明了这一点

private void ensureFragment(int position) {
        long itemId = getItemId(position);
        if (!mFragments.containsKey(itemId)) {
            // TODO(133419201): check if a Fragment provided here is a new Fragment
            Fragment newFragment = createFragment(position);
            newFragment.setInitialSavedState(mSavedStates.get(itemId));
            mFragments.put(itemId, newFragment);
        }
    }

在活动/片段重新创建之后,您会发现this If块永远不会执行,因为mFragments将已经包含在收集活动之前添加的片段。

所以我想知道应该如何提取viewpager2中已经存在的片段

1 个答案:

答案 0 :(得分:0)

如果你看看这个方法,

/**
 * @param holder that has been bound to a Fragment in the {@link #onBindViewHolder} stage.
 */
@SuppressWarnings("WeakerAccess") // to avoid creation of a synthetic accessor
void placeFragmentInViewHolder(@NonNull final FragmentViewHolder holder) {
    Fragment fragment = mFragments.get(holder.getItemId());
    if (fragment == null) {
        throw new IllegalStateException("Design assumption violated.");
    }
    FrameLayout container = holder.getContainer();
    View view = fragment.getView();

    /*
    possible states:
    - fragment: { added, notAdded }
    - view: { created, notCreated }
    - view: { attached, notAttached }

    combinations:
    - { f:added, v:created, v:attached } -> check if attached to the right container
    - { f:added, v:created, v:notAttached} -> attach view to container
    - { f:added, v:notCreated, v:attached } -> impossible
    - { f:added, v:notCreated, v:notAttached} -> schedule callback for when created
    - { f:notAdded, v:created, v:attached } -> illegal state
    - { f:notAdded, v:created, v:notAttached } -> illegal state
    - { f:notAdded, v:notCreated, v:attached } -> impossible
    - { f:notAdded, v:notCreated, v:notAttached } -> add, create, attach
     */

    // { f:notAdded, v:created, v:attached } -> illegal state
    // { f:notAdded, v:created, v:notAttached } -> illegal state
    if (!fragment.isAdded() && view != null) {
        throw new IllegalStateException("Design assumption violated.");
    }

    // { f:added, v:notCreated, v:notAttached} -> schedule callback for when created
    if (fragment.isAdded() && view == null) {
        scheduleViewAttach(fragment, container);
        return;
    }

    // { f:added, v:created, v:attached } -> check if attached to the right container
    if (fragment.isAdded() && view.getParent() != null) {
        if (view.getParent() != container) {
            addViewToContainer(view, container);
        }
        return;
    }

    // { f:added, v:created, v:notAttached} -> attach view to container
    if (fragment.isAdded()) {
        addViewToContainer(view, container);
        return;
    }

    // { f:notAdded, v:notCreated, v:notAttached } -> add, create, attach
    if (!shouldDelayFragmentTransactions()) {
        scheduleViewAttach(fragment, container);
        mFragmentManager.beginTransaction()
                .add(fragment, "f" + holder.getItemId())
                .setMaxLifecycle(fragment, STARTED)
                .commitNow();
        mFragmentMaxLifecycleEnforcer.updateFragmentMaxLifecycle(false);
    } else {
        if (mFragmentManager.isDestroyed()) {
            return; // nothing we can do
        }
        mLifecycle.addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (shouldDelayFragmentTransactions()) {
                    return;
                }
                source.getLifecycle().removeObserver(this);
                if (ViewCompat.isAttachedToWindow(holder.getContainer())) {
                    placeFragmentInViewHolder(holder);
                }
            }
        });
    }
}

这个 tag"f" + holder.getItemId()

@Override
    public long getItemId(int position) {
        return position;
    }

getItemId(int postion) 默认返回位置。但是如果你重写这个方法。

int postionOfTheFragmentYouWantToGet=0;
Fragment page = getSupportFragmentManager().findFragmentByTag("f" + postionOfTheFragmentYouWantToGet);