一度に3つのページを読み込むViewPagerがあります。ページ1からページ2にスワイプしてから3にスワイプすると、最初のページ(フラグメント)はonPause()
に移動します。次に、2ページ目にスワイプすると、1ページ目がまだユーザーに表示されていなくても、1ページ目がonResume()
になります。だから、私の質問は次のとおりです。コードの最初のページと2番目のページを区別する方法は?たとえば、フラグメントが表示されているときにコードを実行する必要がある場合、それはどのように行われますか?
FragmentPagerAdapterは、表示されているものに加えて、追加のフラグメントを再開状態に保持します。解決策は、カスタムOnPageChangeListenerを実装し、フラグメントが表示されるときのための新しいメソッドを作成することです。
1)LifecycleManagerインターフェースの作成インターフェースには2つのメソッドがあり、各ViewPagerのフラグメントはそれを実装します。これらの方法は次のとおりです。
public interface FragmentLifecycle {
public void onPauseFragment();
public void onResumeFragment();
}
2)各フラグメントにインターフェースを実装させ、各クラス宣言にiplementsステートメントを追加します。
public class FragmentBlue extends Fragment implements FragmentLifecycle
public class FragmentGreen extends Fragment implements FragmentLifecycle
public class FragmentPink extends Fragment implements FragmentLifecycle
3)各フラグメントにインターフェースメソッドを実装する期待どおりに動作することを確認するために、メソッド呼び出しをログに記録し、Toastを表示します。
@Override
public void onPauseFragment() {
Log.i(TAG, "onPauseFragment()");
Toast.makeText(getActivity(), "onPauseFragment():" + TAG, Toast.LENGTH_SHORT).show();
}
@Override
public void onResumeFragment() {
Log.i(TAG, "onResumeFragment()");
Toast.makeText(getActivity(), "onResumeFragment():" + TAG, Toast.LENGTH_SHORT).show();
}
4)ViewPagerページ変更時にインターフェイスメソッドを呼び出すViewPagerでOnPageChangeListenerを設定し、ViewPagerが別のページを表示するたびにコールバックを取得できます。
pager.setOnPageChangeListener(pageChangeListener);
5)OnPageChangeListenerを実装して、カスタムライフサイクルメソッドを呼び出す
リスナーは新しい位置を認識しており、PagerAdapterの助けを借りて新しいフラグメントでインターフェースメソッドを呼び出すことができます。ここでは、新しいフラグメントに対してonResumeFragment()を呼び出し、現在のフラグメントに対してonPauseFragment()を呼び出すことができます。
ユーザーが左から右にスクロールしたのか、右から左にスクロールしたのかわからないため、現在のフラグメントの位置も保存する必要があります(最初は現在の位置は0です)。コードで私が意味するものを見てください:
private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
int currentPosition = 0;
@Override
public void onPageSelected(int newPosition) {
FragmentLifecycle fragmentToShow = (FragmentLifecycle)pageAdapter.getItem(newPosition);
fragmentToShow.onResumeFragment();
FragmentLifecycle fragmentToHide = (FragmentLifecycle)pageAdapter.getItem(currentPosition);
fragmentToHide.onPauseFragment();
currentPosition = newPosition;
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) { }
public void onPageScrollStateChanged(int arg0) { }
};
私はコードを書きませんでした。完全なチュートリアルはこちら: http://looksok.wordpress.com/2013/11/02/viewpager-with-detailed-fragment-lifecycle-onresumefragment-include-source-code/
フラグメントがAndroid.support.v4.app.Fragmentを拡張する場合
あなたはこれを使うことができます、それは私のために働きます。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (!isVisibleToUser) {
//do sth..
}
}
setUserVisibleHint()
をオーバーライドします。このメソッドは、フラグメントがユーザーに表示されると呼び出します。
ユーザーメソッドpager.setOffscreenPageLimit(number)スタックに保持するフラグメントの数を設定します。
オーバーライドsetUserVisibleHint()これは、フラグメントがユーザーに見えるときに呼び出されます
問題を解決します。
public class FragmentVisibleHelper implements LifecycleObserver {
private static final String TAG = "VipVisibleHelper";
public interface IVisibleListener {
void onVisible();
void onInVisible();
}
boolean mIsVisibleToUser;
boolean mStarted = false;
volatile boolean mIsCalledVisible = false;
volatile boolean mIsCalledInvisible = false;
IVisibleListener mListener;
public void setListener(IVisibleListener mListener) {
this.mListener = mListener;
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void onResume() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "onResume() called:"));
if (mIsVisibleToUser) {
dispatchVisible();
}
}
private void dispatchVisible() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchVisible() called mIsCalledVisible = [" + mIsCalledVisible + "] mIsCalledInvisible = [" + mIsCalledInvisible + "] "));
if (!mIsCalledVisible) {
mIsCalledVisible = true;
mIsCalledInvisible = false;
if (Profile.LOG) {
Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchVisible() called onVisible"));
}
if (mListener != null) {
mListener.onVisible();
}
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void onPause() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "onPause() called:"));
if (mIsVisibleToUser) {
dispatchInvisible();
}
}
private void dispatchInvisible() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchInvisible() called mIsCalledVisible = [" + mIsCalledVisible + "] mIsCalledInvisible = [" + mIsCalledInvisible + "] "));
if (!mIsCalledInvisible) {
mIsCalledInvisible = true;
mIsCalledVisible = false;
if (Profile.LOG) {
Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchInvisible() called onInVisible"));
}
if (mListener != null) {
mListener.onInVisible();
}
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onStart() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "onStart() called"));
mStarted = true;
if (mIsVisibleToUser) {
dispatchVisible();
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onStop() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "onStop() called"));
if (mIsVisibleToUser) {
dispatchInvisible();
}
mStarted = false;
}
public void setUserVisibleHint(boolean isVisibleToUser) {
Log.d(TAG, String.format("%-60s %s", this.toString(), "setUserVisibleHint() called with: isVisibleToUser = [" + isVisibleToUser + "]:"));
mIsVisibleToUser = isVisibleToUser;
if (mStarted) { // fragment have created
if (mIsVisibleToUser) {
dispatchVisible();
} else {
dispatchInvisible();
}
}
}
public boolean isVisibleToUser() {
return mIsVisibleToUser;
}
}