我有一个ViewPager,一次加载三个页面。如果我从第1页到第2页再刷到3,则第一页(片段)转到onPause()
。然后,如果我滑到第二页,即使用户仍然看不到页面1,第一页也会转到onResume()
。所以,我的问题是:如何区分代码中的第一页和第二页?例如,如果我必须在片段可见时运行一段代码,那该怎么办?
答案 0 :(得分:37)
除了显示的片段之外,FragmentPagerAdapter还会将其他片段保持在恢复状态。解决方案是实现自定义的OnPageChangeListener并为显示片段时创建一个新方法。
1)创建LifecycleManager接口该接口将有两个方法,每个ViewPager的Fragment将实现它。这些方法如下:
public interface FragmentLifecycle {
public void onPauseFragment();
public void onResumeFragment();
}
2)让每个Fragment为每个类声明实现接口Add 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的帮助下调用新Fragment上的接口方法。我可以在这里调用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) { }
};
答案 1 :(得分:7)
如果您的Fragment扩展android.support.v4.app.Fragment
你可以使用它,它对我有用。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (!isVisibleToUser) {
//do sth..
}
}
答案 2 :(得分:2)
用户方法pager.setOffscreenPageLimit(number)设置要在堆栈中保留的片段数。
答案 3 :(得分:2)
覆盖setUserVisibleHint()
。一旦片段对用户可见,此方法将调用。
答案 4 :(得分:0)
覆盖 setUserVisibleHint(),当片段对用户可见时,这将调用
答案 5 :(得分:0)
解决您的问题:
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;
}
}
答案 6 :(得分:0)
在片段之间滑动时,不会调用片段的生命周期方法。您可以使用ViewPager.SimpleOnPageChangeListener
解决此问题。示例代码如下(在Kotlin中)。
// other code
mViewPager.addOnPageChangeListener(object: ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) {
val oldPosition = mViewPager.currentItem
val oldFragment = mViewPager.adapter?.instantiateItem(mViewPager, oldPosition)
oldFragment.onPauseStuff() // Hint: do as here call onPause
val newFragment = mViewPager.adapter?.instantiateItem(mViewPager, position)
newFragment.onResumeStuff() // Hint: do as here call onResume
}
// other code