web-dev-qa-db-ja.com

ビューページャーの特定のタブに現在のフラグメントを表示する方法は?

私はバックスタックの最後のフラグメントを取得したい、または現在表示されているのはtab b_1。次の画像でわかるように、ViewPagerと、もう1つの内部tab b。したがって、4つの現在のフラグメントが表示されます。

質問Fragment 2インスタンス?

私は別の解決策を見ましたが、このシナリオにはうまくいきません。

注釈:返すフラグメントは、ViewPagerでホストされている必要はありません。タブでさらに2つのフラグメントを開くことができます。

scenario

このメソッドを使用すると、現在表示されているすべてのフラグメントを取得できますが、特定のフラグメントは取得できません。

public ArrayList<Fragment> getVisibleFragment() {
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    ArrayList<Fragment> visibleFragments = new ArrayList<>();
    if (fragments != null) {
        for (Fragment fragment : fragments) {
            if (fragment != null && fragment.isVisible())
                visibleFragments.add(fragment);
        }
    }
    return visibleFragments;
}

いくつかの興味深いコード

activity_main.xml

<Android.support.design.widget.CoordinatorLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/activity_main"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent">

    <Android.support.design.widget.AppBarLayout
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        Android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <Android.support.design.widget.TabLayout
            Android:id="@+id/tabs"
            Android:layout_width="match_parent"
            Android:layout_height="wrap_content"
            app:tabMode="fixed"
            app:tabGravity="fill"/>
    </Android.support.design.widget.AppBarLayout>

    <Android.support.v4.view.ViewPager
        Android:id="@+id/viewpager"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</Android.support.design.widget.CoordinatorLayout>

MainActivity.Java

public class MainActivity extends AppCompatActivity {

    private static ViewPagerAdapter adapter;
    private static ViewPager viewPager;
    private TabLayout tabLayout;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewPager = (ViewPager) findViewById(R.id.viewpager);
        setupViewPager();

        tabLayout = (TabLayout) findViewById(R.id.tabs);
        tabLayout.setupWithViewPager(viewPager);
        setupTabIcons();
    }

    private void setupViewPager() {
        adapter = new ViewPagerAdapter(getSupportFragmentManager());
        // Wrap with HostFragment to get separate tabbed nagivation.
        adapter.addFrag(HostFragment.newInstance(new Fragment1()), null);
        adapter.addFrag(HostFragment.newInstance(new RootFragment2()), null);
        adapter.addFrag(HostFragment.newInstance(new Fragment4()), null);
        viewPager.setAdapter(adapter);
        viewPager.setOffscreenPageLimit(2);
    }

    public void openNewFragment(Fragment fragment) {
        HostFragment hostFragment = (HostFragment) adapter.getItem(viewPager.getCurrentItem());
        hostFragment.replaceFragment(fragment, true);
    }
}

fragment_Host.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:id="@+id/hosted_fragment"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"/>

HostFragment.Java

/**
 * This class implements separate navigation for a tabbed viewpager.
 *
 * Based on https://medium.com/@nilan/separate-back-navigation-for-
 * a-tabbed-view-pager-in-Android-459859f607e4#.u96of4m4x
 */
public class HostFragment extends BackStackFragment {

    private Fragment fragment;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        super.onCreateView(inflater, container, savedInstanceState);
        View view = inflater.inflate(R.layout.fragment_Host, container, false);
        if (fragment != null) {
            replaceFragment(fragment, false);
        }
        return view;
    }

    public void replaceFragment(Fragment fragment, boolean addToBackstack) {
        if (addToBackstack) {
            getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).addToBackStack(null).commit();
        } else {
            getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).commit();
        }
    }

    public static HostFragment newInstance(Fragment fragment) {
        HostFragment hostFragment = new HostFragment();
        hostFragment.fragment = fragment;
        return hostFragment;
    }

    public Fragment getFragment() {
        return fragment;
    }
}

fragment2_root.xml

<LinearLayout
    xmlns:Android="http://schemas.Android.com/apk/res/Android"
    xmlns:app="http://schemas.Android.com/apk/res-auto"
    Android:id="@+id/fragment2_root"
    Android:layout_width="match_parent"
    Android:layout_height="match_parent"
    Android:orientation="vertical">

    <Android.support.design.widget.TabLayout
        Android:id="@+id/tab2_tabs"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"
        app:tabMode="fixed"
        app:tabGravity="fill"/>

    <Android.support.v4.view.ViewPager
        Android:id="@+id/tab2_viewpager"
        Android:layout_width="match_parent"
        Android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</LinearLayout>

RootFragment2.Java

public class RootFragment2 extends Fragment {

    private ViewPagerAdapter adapter;
    private ViewPager viewPager;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Inflate the layout for this fragment.
        View root = inflater.inflate(R.layout.fragment2_root, container, false);

        viewPager = (ViewPager) root.findViewById(R.id.tab2_viewpager);
        setupViewPager(viewPager);

        TabLayout tabLayout = (TabLayout) root.findViewById(R.id.tab2_tabs);
        tabLayout.setupWithViewPager(viewPager);

        return root;
    }

    private void setupViewPager(ViewPager viewPager) {
        adapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager());
        // Wrap with HostFragment to get separate tabbed nagivation.
        adapter.addFrag(HostFragment.newInstance(new Fragment2()), null);
        adapter.addFrag(HostFragment.newInstance(new Fragment3()), null);
        viewPager.setAdapter(adapter);
        viewPager.setOffscreenPageLimit(1);
    }

    public ViewPagerAdapter getAdapter() {
        return adapter;
    }

    public ViewPager getViewPager() {
        return viewPager;
    }
}
18
Santiago Gil

最初に、以下のようなSparseArray 'アダプターでViewPagersを定義します。この配列では、フラグメントのインスタンスを保持します。

SparseArray<Fragment> registeredFragments = new SparseArray<>();

そして、アダプターのinstantiateItemメソッドをオーバーライドします。

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Fragment fragment = (Fragment) super.instantiateItem(container, position);
    registeredFragments.put(position, fragment);
    return fragment;
}

destroyItemViewPagersメソッドもオーバーライドします

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    registeredFragments.remove(position);
    super.destroyItem(container, position, object);
}

ViewPagerFragmentsインスタンスを取得する新しいメソッドを定義します。

public Fragment getRegisteredFragment(int position) {
    return registeredFragments.get(position);
}

そして最後にPageChangeListenerViewPagersに追加して設定します:

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        // Here's your instance
        YourFragment fragment =(YourFragment)yourPagerAdapter.getRegisteredFragment(position);

    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
});

これがお役に立てば幸いです。がんばろう。

編集:申し訳ありませんが、あなたが何をしようとしているのかを正確に理解することはできませんが、サブフラグメント(b_1、b_2)インスタンスを保持する必要がある場合は、アクティビティにメソッドを定義できます

public void setCurrentFragment(Fragment fragment){
      this.currentFragment = fragment;
}

サブビューページャーのアダプターでは、このメソッドを次のように呼び出すことができます。

subViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        // Here's your instance
        YourFragment fragment =(YourFragment)yourSubPagerAdapter.getRegisteredFragment(position);
        ((MyActivity)getActivity).setCurrentFragment(fragment);
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
});

この方法で、1つのインスタンスと最上位フラグメントを保持できます。

34
savepopulation

DEADMCでいくつかコメントした後、メモリを追加して実装し、開いているフラグメントをリストに保存することにしました。

私の解決策を説明します。 2つのタイプの特別なフラグメント、Hostrootがあります。ホストフラグメントは、タブの初期化であるものです。ルートフラグメントは、ViewPagerを保持するものです。このシナリオでは、tab_bには、内部ViewPagerを持つルートフラグメントがあります。

Hierarchy

各タブについて、これは、各HostFragmentに対して、このタブで開いたフラグメントを保存するためのリストfragmentsを追加しました。また、このタブに最後に表示されるメソッドgetCurrentFragmentもあります。

public class HostFragment extends BackStackFragment {

    private ArrayList<Fragment> fragments = new ArrayList<>();

    public Fragment getCurrentFragment() {
        return fragments.get(fragments.size() - 1);
    }

また、真の状態を維持するには、このタブに表示されている最後のフラグメントを削除する方法が必要です。 [戻る]ボタンをこのメソッドにリダイレクトする必要があります。

    public void removeCurrentFragment() {
        getChildFragmentManager().popBackStack();
        fragments.remove(fragments.size() - 1);
    }

また、開いた新しいフラグメントをリストに挿入するには、以前のメソッドを変更する必要があります。

    public void replaceFragment(Fragment fragment, boolean addToBackstack) {
        // NEW: Add new fragment to the list.
        fragments.add(fragment);
        if (addToBackstack) {
            getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).addToBackStack(null).commit();
        } else {
            getChildFragmentManager().beginTransaction().replace(R.id.hosted_fragment, fragment).commit();
        }
    }

    public static HostFragment newInstance(Fragment fragment) {
        HostFragment hostFragment = new HostFragment();
        // NEW: Add first fragment to the list.
        hostFragment.fragments.add(fragment);
        return hostFragment;
    }
} // HostFragment.

RootFragmentは、ViewPagerを保持するこれらのフラグメントによって実装されるインターフェースです。

public interface RootFragment {

    /**
     * Opens a new Fragment in the current page of the ViewPager held by this Fragment.
     *
     * @param fragment - new Fragment to be opened.
     */
    void openNewFragment(Fragment fragment);

    /**
     * Returns the fragment displayed in the current tab of the ViewPager held by this Fragment.
     */
    Fragment getCurrentFragment();
}

そして、実装は次のようになります。

MainActivityはフラグメントではありませんが、意味のためにRootFragmentインターフェースを実装しています。

public class MainActivity extends AppCompatActivity implements RootFragment {

    private void setupViewPager() {
        adapter = new ViewPagerAdapter(getSupportFragmentManager());
        // Wrap with HostFragment to get separate tabbed nagivation.
        adapter.addFrag(HostFragment.newInstance(new Fragment1()), null);
        adapter.addFrag(new RootFragment2(), null); // This is a Root, not a Host.
        adapter.addFrag(HostFragment.newInstance(new Fragment4()), null);
        viewPager.setAdapter(adapter);
        // 2 because TabLayout has 3 tabs.
        viewPager.setOffscreenPageLimit(2);
    }

    @Override
    public void openNewFragment(Fragment fragment) {
        Fragment hosted = adapter.getItem(viewPager.getCurrentItem());
        // Replace the fragment of current tab to [fragment].
        if (hosted instanceof HostFragment) {
            ((HostFragment) hosted).replaceFragment(fragment, true);
        // Spread action to next ViewPager.
        } else {
            ((RootFragment) hosted).openNewFragment(fragment);
        }
    }

    @Override
    public Fragment getCurrentFragment() {
        Fragment hosted = adapter.getItem(viewPager.getCurrentItem());
        // Return current tab's fragment.
        if (hosted instanceof HostFragment) {
            return ((HostFragment) hosted).getCurrentFragment();
        // Spread action to next ViewPager.
        } else {
            return ((RootFragment) hosted).getCurrentFragment();
        }
    }
}

およびRootFragment2

public class RootFragment2 extends Fragment implements RootFragment {

    private void setupViewPager(ViewPager viewPager) {
        adapter = new ViewPagerAdapter(getActivity().getSupportFragmentManager());
        // Wrap with HostFragment to get separate tabbed nagivation.
        adapter.addFrag(HostFragment.newInstance(new Fragment2()), null);
        adapter.addFrag(HostFragment.newInstance(new Fragment3()), null);
        viewPager.setAdapter(adapter);
        // 1 because TabLayout has 2 tabs.
        viewPager.setOffscreenPageLimit(1);
    }

    @Override
    public void openNewFragment(Fragment fragment) {
        ((HostFragment) adapter.getItem(viewPager.getCurrentItem())).replaceFragment(fragment, true);
    }

    @Override
    public Fragment getCurrentFragment() {
        return ((HostFragment) adapter.getItem(viewPager.getCurrentItem())).getCurrentFragment();
    }
}

そして、私は電話するだけです:

((MainActivity)getActivity())。getCurrentFragment();

3
Santiago Gil

CustomFragmentメソッドを含み、getClassNameクラスから拡張されるFragmentクラスのようなものを作成できます。次に、CustomFragmentだけでなく、FragmentクラスのRootFragment2などのすべてのフラグメントを拡張します。

したがって、次のようなフラグメントを取得できます。

public CustomFragment getNeededFragment(String fragmentName) {
    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    CustomFragment result = null;
    if (fragments != null) {
        for (Fragment fragment : fragments) {
            if (fragment != null && fragment.isVisible()) {
                try {
                    CustomFragment customFragment = (CustomFragment) customFragment;
                    if (customFragment.getClassName().equals(fragmentName)))
                    result = customFragment;
                } catch (ClassCastException e) {
                }
            }
        }
    }
    return result ;
}
0
Andrey Danilov

私はそのようなことをします:

1。このようなインターフェースを作成します。

_public interface ReturnMyself {
    Fragment returnMyself();
}
_

2。 ViewPagers内のすべてのフラグメントは、これを実装する必要があります。

OnPageChangeListenerをメインVPに追加します。だから、あなたは常に現在の位置を知ることができます。

4OnPageChangeListenerを内部VPに追加して、画面上にどのVPがあるかを確認します。

5。渡されたリストからフラグメントを返すメソッドをアダプタ(メインと内部の両方)に追加します。

_public ReturnMyself getReturnMyselfAtPosition()
_

6。すべてのフラグメントは、returnMyself()でこれを返す必要があります

7。内部フラグメントを持つフラグメントは、returnMyselfのようなものを返す必要があります。

_Fragment returnMyself() {
    return this.myInnerFragmentAdapter.getReturnMyselfAtPosition().returnMyself(); 
}
_

8。メインフラグメント/アクティビティから呼び出すだけです。

_this.adapter.getReturnMyselfAtPosition().returnMyself();
_

そして、あなたはあなたの現在の断片を得ました。