ビューページャーで現在のFragmentインスタンスを取得する


210

以下は、3 Fragment classesの3つのタブそれぞれに埋め込まれたコードViewPagerです。メニューオプションがあります。に示すように、onOptionsItemSelected()オプションを選択して、現在表示されているフラグメントを更新する必要があります。これを更新するには、フラグメントクラスにあるメソッドを呼び出す必要があります。誰かがそのメソッドを呼び出す方法を提案できますか?

public class MainActivity  extends ActionBarActivity {

     ViewPager ViewPager;
     TabsAdapter TabsAdapter;

     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            ViewPager = new ViewPager(this);
            ViewPager.setId(R.id.pager);
            setContentView(ViewPager);

            final ActionBar bar = getSupportActionBar();

            bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

            //Attaching the Tabs to the fragment classes and setting the tab title.
            TabsAdapter = new TabsAdapter(this, ViewPager);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
                    FragmentClass1.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
              FragmentClass2.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
              FragmentClass3.class, null);


            if (savedInstanceState != null) {
                bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
            }

        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {

            switch (item.getItemId()) {

            case R.id.addText:

           **// Here I need to call the method which exists in the currently visible Fragment class**

                    return true;

            }

            return super.onOptionsItemSelected(item);
        }


     @Override
     protected void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
            outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());

     }

     public static class TabsAdapter extends FragmentPagerAdapter
      implements ActionBar.TabListener, ViewPager.OnPageChangeListener {

      private final Context mContext;
            private final ActionBar mActionBar;
            private final ViewPager mViewPager;
            private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

            static final class TabInfo {
                private final Class<?> clss;
                private final Bundle args;

                TabInfo(Class<?> _class, Bundle _args) {
                    clss = _class;
                    args = _args;
                }
            }

      public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
       super(activity.getSupportFragmentManager());
                mContext = activity;
                mActionBar = activity.getSupportActionBar();
                mViewPager = pager;
                mViewPager.setAdapter(this);
                mViewPager.setOnPageChangeListener(this);
            }

      public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
                TabInfo info = new TabInfo(clss, args);
                tab.setTag(info);
                tab.setTabListener(this);
                mTabs.add(info);
                mActionBar.addTab(tab);
                notifyDataSetChanged();

            }

      @Override
      public void onPageScrollStateChanged(int state) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageSelected(int position) {
       // TODO Auto-generated method stub
       mActionBar.setSelectedNavigationItem(position);
      }

      @Override
      public void onTabReselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onTabSelected(Tab tab, FragmentTransaction ft) {
       Object tag = tab.getTag();
                for (int i=0; i<mTabs.size(); i++) {
                    if (mTabs.get(i) == tag) {
                        mViewPager.setCurrentItem(i);

                    }
                }

                tabPosition = tab.getPosition();
      }

      @Override
      public void onTabUnselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public Fragment getItem(int position) {
       TabInfo info = mTabs.get(position);
                return Fragment.instantiate(mContext, info.clss.getName(), info.args);
      }

      @Override
      public int getCount() {
       return mTabs.size();
      }

     }

    }

以下が、updateList()呼び出したいメソッドを含むフラグメントクラスだとします。

 public class FragmentClass1{

    ArrayList<String> originalData;


    @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
           Bundle savedInstanceState) {

          View fragmentView = inflater.inflate(R.layout.frag1, container, false);

          originalData = getOriginalDataFromDB();

          return fragmentView;

         }


    public void updateList(String text)
    {
       originalData.add(text);
       //Here I could do other UI part that need to added
    }
}

呼び出したいフラグメントのメソッドはどれですか?
Biraj Zalavadia 2013

@BirajZalavadia独自の定義済みメソッド。パラメーターがあり、ビューの作成中に既に初期化されているそのフラグメントクラスのインスタンス変数を使用します。
リック

1
ビューページャーにあるフラグメントのクラス名を指定できますか?
Biraj Zalavadia 2013

いくつかのソリューションstackoverflow.com/questions/7379165/...
アン・ドロイド

表示されているフラグメントにアクセスする最も簡単な方法は、stackoverflow.com / questions / 7379165 /…を使用することです。上の2つの答えを見てください。
Luksprog、2013

回答:


205

オプションを選択して、現在表示されているフラグメントを更新する必要があります。

これを行う簡単な方法は、FragmentPagerAdapter実装に関連するトリックを使用することです。

case R.id.addText:
     Fragment page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + ViewPager.getCurrentItem());
     // based on the current position you can then cast the page to the correct 
     // class and call the method:
     if (ViewPager.getCurrentItem() == 0 && page != null) {
          ((FragmentClass1)page).updateList("new item");     
     } 
return true;

変数の命名規則を考え直してください。変数名としてクラスの名前をViewPager ViewPager使用するViewPager mPagerと、非常に混乱します(たとえば、を使用しないでください)。


23
APIが変更された場合、そのフラグメントタグは将来性がありますか?
Maarten 14年

7
@Maartenいいえ、それはアダプターが登場してから(そしてそのソースコードが利用可能になってから)使用されている一般的なハックであり、まだ変更されていません。より信頼性の高いものが必要な場合は、他のオプションを使用する必要があります。最も注目すべきは、instantiateItem()メソッドをオーバーライドして、適切なフラグメントへの参照を自分で取得することです。
Luksprog、2014年

5
数時間の不満とからのページへの直接の質問の後mAdapter.getItem(position)、すごい...少なくとも今、私は他の8512トライアルがうまくいかなかったことを知っています。ありがとう
Diolor 2014

29
FragmentPagerAdapterではなくFragmentStatePagerAdapterを使用する場合、これは機能しないことに注意してください。
Shawn Lauzon、2015年

3
@ShawnLauzon FragmentStatePagerAdapterの実装は異なります。その場合、そのinstantiateItem()メソッドを呼び出して、表示されているフラグメントを取得します。
Luksprog、2015年

155
    public class MyPagerAdapter extends FragmentPagerAdapter {
        private Fragment mCurrentFragment;

        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
//...    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (getCurrentFragment() != object) {
                mCurrentFragment = ((Fragment) object);
            }
            super.setPrimaryItem(container, position, object);
        }
    }

28
Googleは、mCurrentPrimaryItemを返すFragmentPageAdapter.getCurrentPrimaryItem()を提供する必要があります。
eugene 14

1
この手法も使用します。Pag​​erFragmentをメソッドonPageSelected/で定義し、 onPageDeselectedすべてのページャーフラグメントで拡張します 次にsetPrimaryitem、ユーザーが新しいページにスワイプすると、これらのメソッドを適切に呼び出すことができます。これは、表示されていないページにデータをロードするためのレイジー戦略を実装できることを意味します。ただし、ページの移行中は、次のページに既にデータが入力されている方が見栄えが良いため、すべてのデータを遅延ロードonPageSelectedするのは理想的ではない場合があることに注意してください。
JHH

3
なぜif声明なのか?フラグメントequalsはオブジェクトのメソッドを呼び出すだけです。これは浅い比較です。では、なぜ常に電話しないのmCurrentFragment = ((Fragment) object);ですか?
オーバークローバー2017年

試してみましたが、
正常に機能します。getCurrentFragment

113

まず、すべての「アクティブな」フラグメントページを追跡します。この場合、ViewPagerで使用されるFragmentStatePagerAdapterでフラグメントページを追跡します。

@Override
public Fragment getItem(int index) {
    Fragment myFragment = MyFragment.newInstance();
    mPageReferenceMap.put(index, myFragment);
    return myFragment;
}

「非アクティブ」なフラグメントページへの参照を保持しないようにするには、FragmentStatePagerAdapterのdestroyItem(...)メソッドを実装する必要があります。

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

現在表示されているページにアクセスする必要がある場合は、次を呼び出します。

int index = mViewPager.getCurrentItem();
MyAdapter adapter = ((MyAdapter)mViewPager.getAdapter());
MyFragment fragment = adapter.getFragment(index);

MyAdapterのgetFragment(int)メソッドは次のようになります。

public MyFragment getFragment(int key) {
    return mPageReferenceMap.get(key);
}

お役に立てれば幸いです。


分かりやすく説明していただけますか?このFragmentStatePagerAdapterクラスをコードのどこに保持する必要がありますか?ところで私は3つのフラグメントクラスを持っていますが、単一のMyFragmentClassではありません。
リック

7
getPageの代わりにinstantiateItemでmPageReferenceMapを更新すると、向きが変更された後にも動作するため、さらに優れています。'@Override public Object instantiateItem(ViewGroup container、int position){Fragment fragment =(Fragment)Super.instantiateItem(container、position); mPageReferenceMap.put(position、fragment); フラグメントを返す; } '
pmellaaho 14

mPageReferenceMapはどのタイプですか?
DoruAdryan 2014年

10
この答えは本当に悪いです!ViewPagerのキャッシュは単独で処理するため、手動で保持しないでください。ViewPagerは、フラグメントを割り当てるかどうか、いつ停止するか、いつ停止するかを決定します。すべてのフラグメントで参照を保持すると、無駄なオーバーヘッドが追加され、メモリに対して最適化されません。
Livio

3
私はこのアプローチを試みましたが、残念ながら、アクティビティが再作成されたときに機能しません。Android N以降では、マルチウィンドウ機能を使用するときにこれを確認できます。アプリが開いたら、「最近」ボタン(四角いボタン)を押し続けます。アクティビティとフラグメントは、savedInstanceStateから再作成され、アダプターは再作成されます(したがって、mPageReferenceMapは空になります)が、getItemは再度呼び出されません。マップは空のままなので、adapter.getFragment(index)はクラッシュします。
Martin Konicek、2018年

102

これは、特定のフラグメントクラスのインスタンス変数に対してNullPointerExceptionを取得しない唯一の方法です。これは、同じことにこだわっている他の人に役立つかもしれません。onOptionsItemSelected()で、次のようにコーディングしました。

if(viewPager.getCurrentItem() == 0) {
    FragmentClass1 frag1 = (FragmentClass1)viewPager
                            .getAdapter()
                            .instantiateItem(viewPager, viewPager.getCurrentItem());
    frag1.updateList(text); 
} else if(viewPager.getCurrentItem() == 1) {
    FragmentClass2 frag2 = (FragRecentApps)viewPager
                            .getAdapter()
                            .instantiateItem(viewPager, viewPager.getCurrentItem());
    frag2.updateList(text);
}

3
私はこれが最も正しい答えだと思います- FragmentStatePagerAdapterコードを上書きせずにの設計に合わせます。実際、関数はreturnと同じくらい単純でなければなりませんviewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem())
John Pang

39

FragmentStatePagerAdapterには、指定したパラメーター値に基づいてフラグメントを返す、instantiateItemという名前のパブリックメソッドがあり、このメソッドには、ViewGroup(ViewPager)と位置の2つのパラメーターがあります。

public Object instantiateItem(ViewGroup container, int position);

このメソッドを使用して、指定された位置のフラグメントを取得し、

Fragment fragment = (Fragment) adaper.instantiateItem(mViewPager, position);

5
しかし、これは現在すでにインスタンス化されているフラグメントを返しませんが、代わりに新しいフラグメントを返しますか?したがって、「インスタンス化」という名前を付けます...
Ixx

1
@Ixxいいえ、新しいフラグメントは作成されません。ここではメソッド名が間違っていると思います。
バグは

15

手遅れだと知っていますが、私にはそれを行う簡単な方法があります。

// 0位置のフラグメントの場合

((mFragment) viewPager.getAdapter().instantiateItem(viewPager, 0)).yourMethod();

10

これには、これを予測どおりに実行する方法が実際にはないという基本的な事実に実際には対応していない多くの回答があります。また、将来のある時点で足を撃つことにならない方法で。

FragmentStatePagerAdapterによって追跡されるフラグメントに確実にアクセスする方法を知っている唯一のクラスFragmentManagerです。フラグメントのIDまたはタグを試して推測しようとすると、長期的に信頼できません。また、インスタンスを手動で追跡しようとすると、状態が保存/復元されたときにうまく機能しない可能性があります。FragmentStatePagerAdapterときにうまく機能しない可能性があります。これは、状態を復元するときにコールバックを呼び出さない可能性があるです。

私が仕事をすることができた唯一のことについては、コードをコピーしFragmentStatePagerAdapter、位置を指定してフラグメントを返すメソッドを追加することです(mFragments.get(pos))をです。このメソッドは、フラグメントが実際に使用可能である(つまり、ある時点で表示されていた)ことを前提としています。

特に冒険したい場合は、リフレクションを使用してプライベートmFragmentsリストの要素にアクセスできますが、次にスクエアリストに戻ります(リストの名前が同じであるとは限りません)。


1
「状態が保存/復元されたときにうまく機能しない」に対処するために、メソッドsaveState()をオーバーライドします。そのため、アクティビティが一時停止したときにページャーがフラグメントを保存しないようにします。できます。
AntoineP 2015

2
それは根本的な問題を修正することなく、パッチワークに追加するだけです。私はそれが機能しないと主張していません-それは良い実装ではないということだけです。
Melllvar、2015年

8
getSupportFragmentManager().getFragments().get(viewPager.getCurrentItem());

上記の行から取得したインスタンスを、操作するフラグメントにキャストします。完全に正常に動作します。

viewPager

フラグメントを管理するページャーインスタンスです。


これは、すべてのページがフラグメントとしてロードされている場合にのみ機能します。たとえば、多くのタブ/ページのあるタブレイアウトがある場合、それらのすべてがロードされるわけではないため、indexoutofbounce例外が発生する可能性があります。
progNewbie 2018

@progNewbieはい、追加の回避策コードが必要になります。
Gaurav Pangam

@progNewbie Evgenyの以下の答えは、私が考えるそのような状況を処理します
Gaurav Pangam

7

オプションを選択して、現在表示されているフラグメントを更新する必要があります。

現在表示されているフラグメントへの参照を取得するには、ViewPageras への参照があると想定しますmPager。次に、次の手順でへの参照を取得しますcurrentFragment

  1. PageAdapter adapter = mPager.getAdapter();
  2. int fragmentIndex = mPager.getCurrentItem();
  3. FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
  4. Fragment currentFragment = fspa.getItem(fragmentIndex);

通常使用される唯一のキャスト使用ライン3が有効です。FragmentStatePagerAdapterViewPagerの便利なアダプターです。


7

これを行う最善の方法は、CallingFragmentName fragment =(CallingFragmentName)viewPager .getAdapter().instantiateItem(viewPager、viewPager.getCurrentItem());を呼び出すだけです。呼び出しフラグメントを再インスタンス化するため、nullポインター例外がスローされず、そのフラグメントのメソッドが呼び出されません。


6

現在のフラグメント:

これは、フラグメントタブバーテンプレートを使用してプロジェクトを作成した場合に機能します。

Fragment f = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());

これは、デフォルトのタブ付きアクティビティテンプレート実装で機能することに注意してください。


30
これはgetItem()の実装に依存します-フラグメントの新しいインスタンスを返す可能性がありますが、これはおそらく望んでいるものではありません。
トム

これがあなたのやり方です。フラグメントプロジェクトでテーブルを作成するときにデフォルトの設定がまだある場合。誰もこの解決策を持っていませんでした。だから助けになると思った。
ハサン、2016

3

私は以下を使用しました:

 int index = vpPager.getCurrentItem();
 MyPagerAdapter adapter = ((MyPagerAdapter)vpPager.getAdapter());
 MyFragment suraVersesFragment = (MyFragment)adapter.getRegisteredFragment(index);

1
これは、こちらにある回答からのカスタムページャーの実装に依存しています。stackoverflow.com
Tom Redman

1
これはまさに私がやろうとしていたことですが、オーバーライドするメソッドを知らなければ、何時間も無駄になっていたでしょう-ありがとう!
Bron Davies

2

FragmentStatePagerAdaptermCurrentPrimaryItemタイプと呼ばれるプライベートインスタンス変数がありますFragment。なぜAndroid開発者がゲッターを提供しなかったのか不思議に思うだけです。この変数はメソッドでインスタンス化されsetPrimaryItem()ます。したがって、この変数への参照を取得できるように、このメソッドをオーバーライドします。私は自分自身を宣言し、mCurrentPrimaryItemその内容をコピーするだけで終わりましたsetPrimaryItem()オーバーライドに。

あなたの実装ではFragmentStatePagerAdapter

private Fragment mCurrentPrimaryItem = null;

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
    Fragment fragment = (Fragment)object;
    if (fragment != mCurrentPrimaryItem) {
        if (mCurrentPrimaryItem != null) {
            mCurrentPrimaryItem.setMenuVisibility(false);
            mCurrentPrimaryItem.setUserVisibleHint(false);
        }
        if (fragment != null) {
            fragment.setMenuVisibility(true);
            fragment.setUserVisibleHint(true);
        }
        mCurrentPrimaryItem = fragment;
    }
}

public TasksListFragment getCurrentFragment() {
    return (YourFragment) mCurrentPrimaryItem;
}

2

あなたは定義することができPagerAdapter、あなたがどんな取得することができます。このようFragmentではViewPager

private class PagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment) {
        mFragmentList.add(fragment);
    }
}

現在を取得するには Fragment

Fragment currentFragment = mPagerAdapter.getItem(mViewPager.getCurrentItem());

2

viewPagerを使用する場合、アクティビティのフラグメントインスタンスにアクセスする良い方法は、instantiateItem(viewpager、index)です。// index-インスタンスが必要なフラグメントのインデックス。

たとえば、1つのインデックスのフラグメントインスタンスにアクセスしています。

Fragment fragment = (Fragment) viewPageradapter.instantiateItem(viewPager, 1);

if (fragment != null && fragment instanceof MyFragment) {      
 ((MyFragment) fragment).callYourFunction();

}

1

私は同じ問題を抱えており、このコードを使用してそれを解決しました。

MyFragment fragment = (MyFragment) thisActivity.getFragmentManager().findFragmentById(R.id.container);

MyFragmentという名前をフラグメントの名前に置き換え、フラグメントコンテナーのIDを追加するだけです。


1

これは、受け入れられた回答よりも将来性があります。

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    /* ------------------------------------------------------------------------------------------ */
    // region Private attributes :

    private Context _context;
    private FragmentManager _fragmentManager;
    private Map<Integer, String> _fragmentsTags = new HashMap<>();

    // endregion
    /* ------------------------------------------------------------------------------------------ */



    /* ------------------------------------------------------------------------------------------ */
    // region Constructor :

    public MyFragmentPagerAdapter(Context context, FragmentManager fragmentManager) {

        super(fragmentManager);

        _context = context;
        _fragmentManager = fragmentManager;
    }

    // endregion
    /* ------------------------------------------------------------------------------------------ */



    /* ------------------------------------------------------------------------------------------ */
    // region FragmentPagerAdapter methods :

    @Override
    public int getCount() { return 2; }

    @Override
    public Fragment getItem(int position) {

        if(_fragmentsTags.containsKey(position)) {

            return _fragmentManager.findFragmentByTag(_fragmentsTags.get(position));
        }
        else {

            switch (position) {

                case 0 : { return Fragment.instantiate(_context, Tab1Fragment.class.getName()); }
                case 1 : { return Fragment.instantiate(_context, Tab2Fragment.class.getName()); }
            }
        }

        return null;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {

        // Instantiate the fragment and get its tag :
        Fragment result = (Fragment) super.instantiateItem(container, position);
        _fragmentsTags.put(position, result.getTag());

        return result;
    }

    // endregion
    /* ------------------------------------------------------------------------------------------ */
}

代わりにWeakHashMapを使用してください。
Prakash Nadar 2017

1

問題のシナリオは、公式ドキュメントに記載されているように、独自のメニュー項目を追加し、onOptionsItemSelected()を直接処理する各Fragmentの方が適しています。文書化されていないトリックを回避することをお勧めします。


この回答では、実際にそれを行う方法の詳細を使用できます。メニュー項目を追加するとどのようにViewPager問題が解決しますか?
Suragch 16

@Suragch ViewPagerの問題は、メニューイベントがフラグメントをホストするアクティビティ内で処理される場合に発生し、イベントがフラグメント自体内で処理される場合には発生しません。リンクは、フラグメントが独自のメニュー項目を追加する方法を示しています。
Y2i 2017年

1

すべてのコメントと回答を読んだ後、この問題の最適な解決策を説明します。最良のオプションは@rikのソリューションなので、私の改善は彼に基づいています。

各FragmentClassに次のように尋ねる必要はありません

if(FragmentClass1){
   ...
if(FragmentClass2){
   ...
}

独自のインターフェースを作成し、子フラグメントに次のような実装をさせ​​ます

public interface MyChildFragment {
    void updateView(int position);
}

次に、このようなことを実行して、内部フラグメントを開始および更新できます。

Fragment childFragment = (Fragment) mViewPagerDetailsAdapter.instantiateItem(mViewPager,mViewPager.getCurrentItem());

if (childFragment != null) {
   ((MyChildFragment) childFragment).updateView();
}

PSそのコードを配置する場所に注意してください。システムが実際に作成する前にinsatiateItemを呼び出すsavedInstanceStateと、子フラグメントはnullになります。

public void onCreate(@Nullable Bundle savedInstanceState){
      super(savedInstanceState)
}

アプリがクラッシュします。

幸運を


1

彼が@chahat jainに答えたものに基づいて:

「viewPagerを使用する場合、アクティビティでフラグメントインスタンスにアクセスする良い方法は、instantiateItem(viewpager、index)です。// index-インスタンスが必要なフラグメントのインデックス。」

コトリンでそれをしたいなら

val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
                if ( fragment is YourFragmentFragment)
                 {
                    //DO somthign 
                 }

0からのフラグメントインスタンス

// ================================================ ========================= // // ##################### ########使用例################################# // // == ================================================== ===================== //

これは、について最も失われたビジョンを得るための完全な例です

これが.xmlファイルの私のveiewPagerです

   ...
    <android.support.v4.view.ViewPager
                android:id="@+id/mv_viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"/>
    ...

そして、タブを挿入するホームアクティビティ

...
import kotlinx.android.synthetic.main.movie_tab.*

class HomeActivity : AppCompatActivity() {

    lateinit var  adapter:HomeTabPagerAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
       ...
    }



    override fun onCreateOptionsMenu(menu: Menu) :Boolean{
            ...

        mSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
          ...

            override fun onQueryTextChange(newText: String): Boolean {

                if (mv_viewpager.currentItem  ==0)
                {
                    val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
                    if ( fragment is ListMoviesFragment)
                        fragment.onQueryTextChange(newText)
                }
                else
                {
                    val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 1) as Fragment
                    if ( fragment is ListShowFragment)
                        fragment.onQueryTextChange(newText)
                }
                return true
            }
        })
        return super.onCreateOptionsMenu(menu)
    }
        ...

}

1

以前の実装では、後でアクセスできるように子フラグメントのリストを保存しましたが、これは間違った実装であり、大量のメモリリークを引き起こしていることがわかりました。

instantiateItem(...)メソッドを使用して現在のフラグメントを取得します:

val currentFragment = adapter?.instantiateItem(viewPager, viewPager.currentItem)

または、他のフラグメントを配置するには:

val position = 0
val myFirstFragment: MyFragment? = (adapter?.instantiateItem(viewPager, position) as? MyFragment)

ドキュメントから:

指定された位置にページを作成します。アダプターは、ここで指定されたコンテナーにビューを追加する必要がありますが、finishUpdate(ViewGroup)から戻るまでにこれが確実に行われるようにする必要があります。


0

私の活動では:

int currentPage = 0;//start at the first tab
private SparseArray<Fragment> fragments;//list off fragments
viewPager.setOnPageChangeListener(new OnPageChangeListener() {

@Override
public void onPageSelected(int pos) {
        currentPage = pos;//update current page
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
@Override
public void onPageScrollStateChanged(int arg0) {}
});



@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);
    if(fragment instanceof Fragment1)
        fragments.put(0, fragment);
    if(fragment instanceof Fragment2)
        fragments.put(2, fragment);
    if(fragment instanceof Fragment3)
        fragments.put(3, fragment);
    if(fragment instanceof Fragment4)
        fragments.put(4, fragment);
}

Then I have the following method for getting the current fragment

public Fragment getCurrentFragment() {
    return fragments.get(currentPage);
}

0
final ViewPager.OnPageChangeListener onPageChangeListener =
    new ViewPager.OnPageChangeListener() {
      @Override public void onPageSelected(int position) {
        switch (position) {
          case 0:
            FragmentClass1 frag1 =
                (FragmentClass1) viewPager.getAdapter()
                    .instantiateItem(viewPager, viewPager.getCurrentItem());
            frag1.updateList("Custom text");
            break;
          case 1:
            break;
          case 2:
            break;
        }
      }

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

      }

      @Override public void onPageScrollStateChanged(int state) {
      }
    };


 viewPager.addOnPageChangeListener(onPageChangeListener);

viewPager.setAdapter(adapter);


viewPager.post(new Runnable() {
  @Override public void run() {
    onPageChangeListener.onPageSelected(viewPager.getCurrentItem());
  }
});

フラグメントがnullオブジェクトをディスパッチすることがあるので、新しいRunnableを実行して、最初のロードで問題を解決できます。

リックありがとう


このコードがOPの問題を解決する理由を説明するテキストを追加してください。また、他にも答えがいくつあるかを考えて、この答えがすでに与えられている答えよりも優れている理由を説明してください。他の人の理解を助ける。
APC

0

FragmentPagerAdapterからsetPrimaryItemをオーバーライドします。オブジェクトは可視フラグメントです。

 @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (mCurrentFragment != object) {
                mCurrentFragment = (LeggiCapitoloFragment) object;
            }
            super.setPrimaryItem(container, position, object);
        }

0

ページャーから現在のアイテムを取得し、アダプターにその位置のフラグメントを要求するだけです。

 int currentItem = viewPager.getCurrentItem();
    Fragment item = mPagerAdapter.getItem(currentItem);
    if (null != item && item.isVisible()) {
       //do whatever want to do with fragment after doing type checking
        return;
    }

3
getItem新しいインスタンスを作成するとどうなるか
Prakash Nadar 2017

0

現在のフラグメントを取得するには-ViewPagerでpublic void onPageSelected(final int position)の位置を取得し、次に

public PlaceholderFragment getFragmentByPosition(Integer pos){
    for(Fragment f:getChildFragmentManager().getFragments()){
        if(f.getId()==R.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
            return (PlaceholderFragment) f;
        }
    }
    return null;
}

SECTNUM- public static PlaceholderFragment newInstance(int sectionNumber);で割り当てられた位置引数破片の

getChildFragmentManager()またはgetFragmentManager()-作成されたSectionsPagerAdapterに依存


0

BroadcastReceiverをFragmentに実装し、どこからでもインテントを送信できます。フラグメントのレシーバーは、特定のアクションをリッスンして、インスタンスのメソッドを呼び出すことができます。

注意点の1つは、Viewコンポーネントが既にインスタンス化されていること、およびリストのスクロールなどの一部の操作では、ListViewが既にレンダリングされていることを確認することです。


0

これが最も簡単なハックです。

fun getCurrentFragment(): Fragment? {
    return if (count == 0) null
    else instantiateItem(view_pager, view_pager.currentItem) as? Fragment
}

(kotlinコード)

呼び出しinstantiateItem(viewPager, viewPager.getCurrentItem()てにキャストしてくださいFragment。アイテムはすでにインスタンス化されています。確実にチェックを追加できるgetCount

との両方FragmentPagerAdapterで機能しFragmentStatePagerAdapterます!


0

ページャーがフラグメント内にある場合は、これを使用します。

private fun getPagerCurrentFragment(): Fragment? {
    return childFragmentManager.findFragmentByTag("android:switcher:${R.id.myViewPagerId}:${myViewPager.currentItem}")
}

R.id.myViewPagerIdXMLレイアウト内のViewPagerのIDはどこにありますか。


これは通常のFragmentPageAdapterでのみ機能し、FragmentStatePageAdapterでは機能しません。
progNewbie 2018

0

フラグメントの配列をレジスタフラグメントとして宣言できます

class DashboardPagerAdapter(fm: FragmentManager?) : FragmentStatePagerAdapter(fm!!) {
    // CURRENT FRAGMENT
    val registeredFragments = SparseArray<Fragment>()

    override fun instantiateItem(container: ViewGroup, position: Int): Any {
        val fragment = super.instantiateItem(container, position) as Fragment
        registeredFragments.put(position, fragment)
        return fragment
    }

    override fun getItem(position: Int): Fragment {
        return when (position) {
            0 -> HomeFragment.newInstance()
            1 -> ConverterDashboardFragment.newInstance()
            2 -> CartFragment.newInstance()
            3 -> CustomerSupportFragment.newInstance()
            4 -> ProfileFragment.newInstance()
            else -> ProfileFragment.newInstance()
        }
    }

    override fun getCount(): Int {
        return 5
    }

}

その後、次のように使用できます

adapter?.let {
    val cartFragment = it.registeredFragments[2] as CartFragment?
    cartFragment?.myCartApi(true)
}

そのようにする場合は、destroyItem()も実装し、破棄されたインスタンスをregisteredFragmentsから削除する必要があります。そうしないと、メモリリークが発生します。
デフィネラ

それは良いアドバイスです。回答を編集してください。
Hamza Khan

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.