web-dev-qa-db-ja.com

フラグメントを持つViewPager-onPause()、onResume()?

ViewPagerをフラグメントとともに使用する場合、タブ間を移動するときにonPause()、onResume()メソッドは呼び出されません。フラグメントを表示または非表示にしたときに、フラグメント内で把握できる方法はありますか?

残念ながら、onResume()、onPause()には、位置サービスに登録するようなロジックがあり、onPause()はアプリ全体を終了するまで呼び出されないため、タブを切り替えても停止することはありません。

ありがとう

47
user291701

ViewPagerには OnPageChangeListener インターフェイスが付属しています。前のページと現在表示されているページにいくつかのフラグを設定することにより、この動作をエミュレートできます。

17
Phix

以前の解決策はあまり明確ではないことを考慮して、Phixのヒントのおかげでそれをどのように解決したのですか?

OnPageChange()コールバックで:

    Fragment old_fragment = getActiveFragment(old_position);
    Fragment new_fragment = getActiveFragment(new_position);
    old_f.setUserVisibleHint(false);
    old_f.onPause();
    new_f.setUserVisibleHint(true);
    new_f.onResume();

次にonResume()で:

    if (getUserVisibleHint())
        /* resume code */

およびonPause()で:

    if (!getUserVisibleHint())
        /* pause code */

以下にgetActiveFragmentコードを示します。これも検索しません。

    return fragmentManager.findFragmentByTag("Android:switcher:" + viewPagerId + ":" + position);

注:フラグメントにはisVisible()メソッドがありますが、あまり一貫性がないように見えるため、UserVisibleHintを使用します。

編集:UserVisibleHintをプライベートフラグに置き換えます。ずっとうまくいった!

10
3c71

UがAndroid Support Library(rev 11)を使用している場合、getUserVisibleHint()を使用するか、または setUserVisibleHint() をオーバーライドして、表示される変更をキャプチャして非表示にできます。 投稿

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        // do something when visible.
    }
}
7
Evan

解決策1:

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

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

そして、OverrideアダプターのinstantiateItemメソッド。

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

また、OverridedestroyItemViewPagersメソッド

@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);
} 

これで、ViewPager'sOnPageChangeListenerを使用してロジックを実装できます。ビューページャーのonPageChangeListenerを実装する方法の例を次に示します。

現在の位置を保持する整数を定義します。

int currentPos;

yourViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                // Empty method
            }

            @Override
            public void onPageSelected(int position) {
                  // This is paused fragment.
                  final Fragment pausedFragment = yourAdapter.getRegisteredFragment(currentPos);

                  // update current position value
                  currentPos = position;

                  // This is resumed fragment
                  final Fragment resumedFragment = yourAdapter.getRegisteredFragment(currentPos);
            }

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

最後に、インスタンス状態を復元するために、現在の位置を更新して、ユーザーがViewPagerを残した位置を更新し続けます

currentPos = yourViewPager.getCurrentItem();

解決策2:

別の解決策として、ViewPagerFragmentsTagを見つけることができます。以下を使用してタグを生成できます。

@NonNull
public static String generateViewPagerFragmentTag(int viewPagerId, int position) {
        final StringBuilder tagBuilder = new StringBuilder();
        tagBuilder.append("Android:switcher:");
        tagBuilder.append(viewPagerId);
        tagBuilder.append(":");
        tagBuilder.append(position);
        return tagBuilder.toString();
    }

そして、Fragmentを見つけます:

final Fragment yourFragment = getSupportFragmentManager().findFragmentByTag(generateViewPagerFragmentTag(R.id.your_viewpager, currentPos));

編集:数年前、ViewPagerの現在のアイテムを取得するためのソリューションを探していたときに、UserVisibleHintFragmentsを試してみましたが、信頼できないことに気付きました。信頼できるかどうかは今はわかりませんが、使用することは避けています。

2
savepopulation

Fragmentで以下のメソッドを使用できます

public void setUserVisibleHint(boolean isVisibleToUser){

}

いつ isVisibleToUser == true、フラグメントが表示されます

2
tainy

savepopulation の答えでメソッドにもう少し定義を与えるには:

yourPager.setOnPageChangeListener(new GridViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int row, int column, float rowOffset, float columnOffset, int rowOffsetPixels, int columnOffsetPixels) {

        }

        @Override
        public void onPageSelected(int row, int column) {
            // When on page selected if position is not specific for you
            // you can find your fragment or you can switch position.
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });
0
suomi35

パーティーに少し遅れましたが、現在のアプリではビューページャーのOffScreenPageLimitを1に設定しています。これは、フラグメントがキャッシュされず、ビューが変更されるたびに現在のフラグメントがリロードされることを意味します

https://developer.Android.com/reference/Android/support/v4/view/ViewPager.html#getOffscreenPageLimit()

0
Phil