Android ViewPager.setOffscreenPageLimit(0) 不能按预期工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10073214/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ViewPager.setOffscreenPageLimit(0) doesn't work as expected
提问by Chris Lacy
The fragments I use in my ViewPager
instance are quite resource intensive, so I'd only like to load one at a time. When I try the following:
我在我的ViewPager
实例中使用的片段非常占用资源,所以我只想一次加载一个。当我尝试以下操作时:
mViewPager.setOffscreenPageLimit(0);
mViewPager.setAdapter(mPagerAdapter);
My FragmentStatePagerAdapter.getItem(int position)
override function is called 3 times, which is what happens when I call mViewPager.setOffscreenPageLimit(1)
. I would expect it to only be called once, because I specified 0 offscreen pages.
我的FragmentStatePagerAdapter.getItem(int position)
覆盖函数被调用了 3 次,这就是我调用mViewPager.setOffscreenPageLimit(1)
. 我希望它只被调用一次,因为我指定了 0 个屏幕外页面。
I believe I'm calling everything correctly, because if I call mViewPager.setOffscreenPageLimit(2)
, FragmentStatePagerAdapter.getItem(int position)
is called 5 times as I would expect.
我相信我正确地调用了所有内容,因为如果我调用mViewPager.setOffscreenPageLimit(2)
,FragmentStatePagerAdapter.getItem(int position)
会按照我的预期调用 5 次。
Does ViewPager require a minimum of 1 offscreen pages, or am I doing something wrong here?
ViewPager 是否至少需要 1 个屏幕外页面,还是我在这里做错了什么?
回答by Tyler Davis
The best way that I found was setUserVisibleHint
add this to your fragment
我发现的最好方法是setUserVisibleHint 将此
添加到您的片段中
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// load data here
}else{
// fragment is no longer visible
}
}
回答by CommonsWare
Does ViewPager require a minimum of 1 offscreen pages
ViewPager 是否至少需要 1 个离屏页面
Yes. If I am reading the source code correctly, you should be getting a warning about this in LogCat, something like:
是的。如果我正确阅读源代码,您应该会在 LogCat 中收到关于此的警告,例如:
Requested offscreen page limit 0 too small; defaulting to 1
回答by Terry
You can try like this :
你可以这样尝试:
public abstract class LazyFragment extends Fragment {
protected boolean isVisible;
/**
* 在这里实现Fragment数据的缓加载.
* @param isVisibleToUser
*/
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(getUserVisibleHint()) {
isVisible = true;
onVisible();
} else {
isVisible = false;
onInvisible();
}
}
protected void onVisible(){
lazyLoad();
}
protected abstract void lazyLoad();
protected void onInvisible(){}
protected abstract void lazyLoad();
protected void onInvisible(){}
回答by Terry
First Add
首先添加
boolean isFragmentLoaded = false;
than
比
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && !isFragmentLoaded) {
//Load Your Data Here like.... new GetContacts().execute();
isFragmentLoaded = true;
}
else{
}
}
回答by Friends_little_black
ViewPager is default to load the next page(Fragment) which you can't change by setOffscreenPageLimit(0). But you can do something to hack. You can implement onPageSelected function in Activity containing the ViewPager. In the next Fragment(which you don't want to load), you write a function let's say showViewContent() where you put in all resource consuming init code and do nothing before onResume() method. Then call showViewContent() function inside onPageSelected. Hope this will help.
ViewPager 默认加载下一页(Fragment),您无法通过 setOffscreenPageLimit(0) 更改该页面。但是你可以做一些事情来破解。您可以在包含 ViewPager 的 Activity 中实现 onPageSelected 函数。在下一个 Fragment(您不想加载)中,您编写了一个函数,比如 showViewContent(),您将所有资源消耗的初始化代码放入其中,并且在 onResume() 方法之前不执行任何操作。然后在onPageSelected 中调用showViewContent() 函数。希望这会有所帮助。
回答by AREF
in my case i wanted to start some animations in views, but with setUserVisibleHint got some issues ...
my solution is :
就我而言,我想在视图中开始一些动画,但是 setUserVisibleHint 遇到了一些问题......
我的解决方案是:
1/ addOnPageChangeListener for your adapter :
1/ addOnPageChangeListener 为您的适配器:
mViewPager.addOnPageChangeListener(this);
2/ implement OnPageChangeListener :
2/ 实现 OnPageChangeListener :
public class PagesFragment extends Fragment implements ViewPager.OnPageChangeListener
3/ override the 3 methodes :
3/ 覆盖 3 种方法:
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
{
}
@Override
public void onPageSelected(int position)
{
}
@Override
public void onPageScrollStateChanged(int state)
{
}
4/ declare and initialize this variable on your class
4/ 在你的类上声明并初始化这个变量
private static int mTabState = 1;
notice: i have three fragments in my adapter, and use mTabState for setCurrentItem and current position of adapter which recognize which fragment is show to user in time ... 5/ in onPageSelected method add this codes :
注意:我的适配器中有三个片段,并使用 mTabState 作为 setCurrentItem 和适配器的当前位置,以识别哪个片段及时显示给用户...... 5/ 在 onPageSelected 方法中添加以下代码:
if (mTabState == 0 || position == 0)
{
Intent intent = new Intent("animation");
intent.putExtra("current_position", position);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
}
if previous page or current page is page 0(fragment in position 0) then do this stuff
如果上一页或当前页是第 0 页(位置 0 的片段),则执行此操作
6/ now in your fragment class (fragment in position 0 of adapter), you must create broadcast receiver and register it in onResume method and unregister it onPause methos :
6/ 现在在您的片段类(适配器位置 0 中的片段)中,您必须创建广播接收器并在 onResume 方法中注册它并在 onPause 方法中取消注册:
BroadcastReceiver broadcastReceiver = new BroadcastReceiver()
{
@Override
public void onReceive(Context context, Intent intent)
{
if (Objects.equals(intent.getAction(), "animation"))
{
int currentPosition = intent.getIntExtra("current_position", 0);
if (currentPosition == 0)
{
startAnimation();
setViewsVisible();
} else
{
setViewsInvisible();
}
}
}
};
@Override
public void onResume()
{
super.onResume();
LocalBroadcastManager.getInstance(mContext).registerReceiver(broadcastReceiver, new IntentFilter("animation"));
}
@Override
public void onPause()
{
super.onPause();
LocalBroadcastManager.getInstance(mContext).unregisterReceiver(broadcastReceiver);
}
summary :i have Fragment Pager Adapter witch shows Three Fragments in it, I want show some Animations on Views in Fragment in Position 0 of Adapter, For this I use BroadcastReceiver. When Fragment is Picked I start the Animation method and shows the Views to User, When Fragment is not Showing to User I try to Invisible Views...
摘要:我有 Fragment Pager Adapter 女巫在其中显示了三个 Fragment,我想在 Adapter 位置 0 的 Fragment 中的视图上显示一些动画,为此我使用 BroadcastReceiver。当挑选片段时,我启动动画方法并将视图显示给用户,当片段没有向用户显示,我尝试看不见的视图......
回答by Abhijeet Sharma
Please Try This Code for resolve issue of refreshing view in Viewpager....
请尝试此代码以解决 Viewpager 中刷新视图的问题....
/* DO NOT FORGET! The ViewPager requires at least “1” minimum OffscreenPageLimit */
int limit = (mAdapter.getCount() > 1 ? mAdapter.getCount() - 1 : 1);
mViewPager.setOffscreenPageLimit(limit);
回答by K20
I kind of have the same problem. I found some useful code on this site and transform it.
我有同样的问题。我在此站点上找到了一些有用的代码并对其进行了转换。
The min int for mViewPager.setOffscreenPageLimit(...); is 1, so even if you change it to 0 you will still have 2 pages loaded.
mViewPager.setOffscreenPageLimit(...) 的最小整数;是 1,所以即使您将其更改为 0,您仍然会加载 2 个页面。
First thing to do is to create a static int we will call maxPageCount and override FragmentStatePagerAdapter method getCount() to return maxPageCount:
首先要做的是创建一个静态整数,我们将调用 maxPageCount 并覆盖 FragmentStatePagerAdapter 方法 getCount() 以返回 maxPageCount:
@Override
public int getCount() {
return maxPageCount;
}
Create then a static method accessible from any where in the program that will allow you to change this maxCount:
然后创建一个可从程序中的任何位置访问的静态方法,该方法将允许您更改此 maxCount:
public static void addPage(){
maxPageCount++; //or maxPageCount = fragmentPosition+2
mFragmentStatePagerAdapter.notifyDataSetChanged(); //notifyDataSetChanged is important here.
}
Now initialize maxPageCount to 1. When ever you want you can add another page. In my case when I needed the user to treat the current page first before generated the other. He do it and then, without problem can swipe to the next page.
现在将 maxPageCount 初始化为 1。您可以随时添加另一个页面。在我的情况下,当我需要用户在生成另一个页面之前首先处理当前页面时。他这样做,然后可以毫无问题地滑动到下一页。
Hope it help someone.
希望它可以帮助某人。
回答by Rohit Sharma
Use This // create boolean for fetching data private boolean isViewShown = false;
使用此 // 创建用于获取数据的布尔值 private boolean isViewShown = false;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (getView() != null) {
isViewShown = true;
// fetchdata() contains logic to show data when page is selected mostly asynctask to fill the data
fetchData();
} else {
isViewShown = false;
}
}
回答by android developer
for the "instantiateItem" function, just prepare the fragment, but don't load the heavy content.
对于“instantiateItem”函数,只需准备片段,但不要加载繁重的内容。
Use "onPageChangeListener" , so that each time you go to a specific page, you load its heavy content and show it.
使用 "onPageChangeListener" ,以便每次转到特定页面时,加载其大量内容并显示它。