私はバックスタックの最後のフラグメントを取得したい、または現在表示されているのはtab b_1
。次の画像でわかるように、ViewPagerと、もう1つの内部tab b
。したがって、4つの現在のフラグメントが表示されます。
質問:Fragment 2
インスタンス?
私は別の解決策を見ましたが、このシナリオにはうまくいきません。
注釈:返すフラグメントは、ViewPagerでホストされている必要はありません。タブでさらに2つのフラグメントを開くことができます。
このメソッドを使用すると、現在表示されているすべてのフラグメントを取得できますが、特定のフラグメントは取得できません。
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;
}
}
最初に、以下のような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;
}
destroyItem
のViewPagers
メソッドもオーバーライドします
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
ViewPager
Fragments
インスタンスを取得する新しいメソッドを定義します。
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
そして最後にPageChangeListener
をViewPagers
に追加して設定します:
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つのインスタンスと最上位フラグメントを保持できます。
DEADMCでいくつかコメントした後、メモリを追加して実装し、開いているフラグメントをリストに保存することにしました。
私の解決策を説明します。 2つのタイプの特別なフラグメント、Hostとrootがあります。ホストフラグメントは、タブの初期化であるものです。ルートフラグメントは、ViewPagerを保持するものです。このシナリオでは、tab_b
には、内部ViewPagerを持つルートフラグメントがあります。
各タブについて、これは、各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();
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 ;
}
私はそのようなことをします:
1。このようなインターフェースを作成します。
_public interface ReturnMyself {
Fragment returnMyself();
}
_
2。 ViewPagers内のすべてのフラグメントは、これを実装する必要があります。
。 OnPageChangeListener
をメインVPに追加します。だから、あなたは常に現在の位置を知ることができます。
4。 OnPageChangeListener
を内部VPに追加して、画面上にどのVPがあるかを確認します。
5。渡されたリストからフラグメントを返すメソッドをアダプタ(メインと内部の両方)に追加します。
_public ReturnMyself getReturnMyselfAtPosition()
_
6。すべてのフラグメントは、returnMyself()
でこれを返す必要があります
7。内部フラグメントを持つフラグメントは、returnMyselfのようなものを返す必要があります。
_Fragment returnMyself() {
return this.myInnerFragmentAdapter.getReturnMyselfAtPosition().returnMyself();
}
_
8。メインフラグメント/アクティビティから呼び出すだけです。
_this.adapter.getReturnMyselfAtPosition().returnMyself();
_
そして、あなたはあなたの現在の断片を得ました。