我在ViewPager
实例中使用的片段是非常耗费资源的,所以我只想一次加载一个。当我尝试以下内容时:
mViewPager.setOffscreenPageLimit(0);
mViewPager.setAdapter(mPagerAdapter);
我的FragmentStatePagerAdapter.getItem(int position)
覆盖函数被调用3次,这是我调用mViewPager.setOffscreenPageLimit(1)
时发生的情况。我希望它只被调用一次,因为我指定了0个屏幕外页面。
我相信我正在调用所有内容,因为如果我拨打mViewPager.setOffscreenPageLimit(2)
,FragmentStatePagerAdapter.getItem(int position)
会被调出5次,就像我期望的那样。
ViewPager是否需要至少1个屏幕外页面,或者我在这里做错了什么?
答案 0 :(得分:118)
我找到的最佳方式是setUserVisibleHint
将此添加到您的片段
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
// load data here
}else{
// fragment is no longer visible
}
}
答案 1 :(得分:108)
ViewPager是否需要至少1个屏幕外页面
是。如果我正确地阅读源代码,您应该在LogCat中收到关于此的警告,例如:
Requested offscreen page limit 0 too small; defaulting to 1
答案 2 :(得分:7)
您可以尝试这样:
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(){}
答案 3 :(得分:7)
首先添加
boolean isFragmentLoaded = false;
大于
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && !isFragmentLoaded) {
//Load Your Data Here like.... new GetContacts().execute();
isFragmentLoaded = true;
}
else{
}
}
答案 4 :(得分:1)
ViewPager默认加载下一页(片段),您无法通过setOffscreenPageLimit(0)进行更改。但你可以做点什么来破解。 您可以在包含ViewPager的Activity中实现onPageSelected函数。在下一个片段(你不想加载)中,你编写了一个函数,让我们说showViewContent()你放入所有资源消耗的初始化代码,并且在onResume()方法之前什么也不做。然后在onPageSelected中调用showViewContent()函数。希望这会有所帮助。
答案 5 :(得分:1)
就我而言,我想在视图中开始一些动画,但是使用setUserVisibleHint遇到了一些问题...
我的解决方案是:
1 /您的适配器的addOnPageChangeListener:
mViewPager.addOnPageChangeListener(this);
2 /实现OnPageChangeListener:
public class PagesFragment extends Fragment implements ViewPager.OnPageChangeListener
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 /在您的课程上声明并初始化此变量
private static int mTabState = 1;
通知:我的适配器中有三个片段,并将mTabState用于setCurrentItem和适配器的当前位置,以识别哪个片段及时显示给用户... 5 /在onPageSelected方法中添加以下代码:
if (mTabState == 0 || position == 0)
{
Intent intent = new Intent("animation");
intent.putExtra("current_position", position);
LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
}
如果上一页或当前页是第0页(片段位于位置0),则请进行此操作
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);
}
摘要:我有片段分页器Adapter巫婆在其中显示了三个片段,我想在Adapter位置0的Fragment中的视图上显示一些动画,为此,我使用BroadcastReceiver。选择片段后,我将启动“动画”方法并向用户显示视图,而当片段未向用户显示时,我将尝试使视图不可见...
答案 6 :(得分:0)
对于“instantiateItem”函数,只需准备片段,但不要加载繁重的内容。
使用“onPageChangeListener”,这样每次进入特定页面时,都会加载其重要内容并显示它。
答案 7 :(得分:0)
这可能是旧线程,但这似乎对我有用。覆盖此功能:
@Override
public void setMenuVisibility(boolean menuVisible) {
super.setMenuVisibility(menuVisible);
if ( menuVisible ) {
/**
* Load your stuffs here.
*/
} else {
/**
* Fragment not currently Visible.
*/
}
}
快乐的编码...
答案 8 :(得分:0)
我有同样的问题。我在这个网站上找到了一些有用的代码并对其进行了转换。
mViewPager.setOffscreenPageLimit(...)的min int;是1,所以即使你把它改为0你仍然会加载2页。
要做的第一件事是创建一个静态int我们将调用maxPageCount并重写FragmentStatePagerAdapter方法getCount()以返回maxPageCount:
@Override
public int getCount() {
return maxPageCount;
}
然后创建一个静态方法,可以从程序中的任何位置访问,以便更改此maxCount:
public static void addPage(){
maxPageCount++; //or maxPageCount = fragmentPosition+2
mFragmentStatePagerAdapter.notifyDataSetChanged(); //notifyDataSetChanged is important here.
}
现在将maxPageCount初始化为1.如果需要,可以添加其他页面。 在我的情况下,我需要用户在生成另一个之前先处理当前页面。他这样做,然后,没有问题可以刷到下一页。
希望对某人有所帮助。
答案 9 :(得分:0)
使用此 //创建用于获取数据的布尔值 私人布尔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;
}
}
答案 10 :(得分:0)
请尝试使用此代码解决Viewpager中刷新视图的问题。...
loopy
答案 11 :(得分:0)
仅使用一页查看寻呼机:
这是 2021 年 - 2 月,Alhamdulillah,我只能使用 viewPager 添加一页。方法是:ViewPager
、FragmentPagerAdapter
、Tablayout
和 fragment
。就我而言,我可以用多个 Pages
填充多个 tabs
,或者只用一个 Page
填充一个 Tab
。当一个选项卡和一页,向左或向右滑动时,我可以设法更改我的文档的章节(我想接下来显示)。当有很多页面和很多标签时,我可以更改整个文档集。
在主 Activity Oncreate 中:(这是我的工作代码方法,我的工作代码在这里没有任何更改):
if(getIntent()!=null){
if(getIntent().getStringExtra("ONLY_TAFHEEM")!=null)
sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), suraName, suraId, ayatId, true);
else
sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), suraName, suraId, ayatId, false);
}else {
sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager(), suraName, suraId, ayatId, false);
}
final ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(sectionsPagerAdapter);
tabsLayout = findViewById(R.id.tabs);
tabsLayout.animate();
tabsLayout.setupWithViewPager(viewPager);
在适配器中:
@NonNull
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
return PlaceholderFragment.sendData(mContext, postion, suraName, suraId, ayahId, ARABIC_AYAH, BENGALI_AYAH, actualDbNames[position], tafsirDisplayNames[position]);
}
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return tafsirDisplayNames[position];
}
@Override
public int getCount() {
// this is the tricky part // Show pages according to array length. // this may only one // this is the tricky part :
return tafsirDisplayNames.length;
}
最后是片段公共构造函数:
public static PlaceholderFragment sendData(Context mContext, int tabIndex, String suraName, String suraId, String ayahNumber, String arabicAyah, String bengaliAyah, String actualDbName, String displayDbName) {
Log.i("PlaceHolder", "Tafhim sendData: " + bengaliAyah);
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle bundle = new Bundle();
mContext_ = mContext;
BENGALI_AYAH = bengaliAyah;
_DISPLAY_DB_NAME = displayDbName;
bundle.putInt(ARG_SECTION_NUMBER, tabIndex);
bundle.putString(SURA_NAME, suraName);
bundle.putString(SURA_ID, suraId);
bundle.putString(AYAH_NUMBER, ayahNumber);
bundle.putString(ARABIC_AYAH, arabicAyah);
bundle.putString(ACTUAL_DB_NAME, actualDbName);
bundle.putString(DISPLAY_DB_NAME, displayDbName);
fragment.setArguments(bundle);
return fragment;
}
就是这样,只需将数组(选项卡标签)传递给适配器,(它可能只有一个元素,以防万一,一页),根据我的需要,我可以填充一页或多页,并根据它填充一个或多个选项卡:在上面的代码中,数组是:tafsirDisplayNames
。我也可以在适配器中手动创建数组,当适配器第一次调用时,或者,在重新创建 MainActivity 时使用 +-元素重新创建数组。
多数民众赞成,Alhamdulillah,快乐编码.......
答案 12 :(得分:0)
// step 1: add BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT FragmentPagerAdapter contractor
public class BottomTabViewPager extends FragmentPagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public BottomTabViewPager(FragmentManager manager) {
super(manager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
public void addTabs(String title) {
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
// return null;
}
}
// step 2: You can try like this :
public class MyFragment extends Fragment {
public MyFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_ui, container, false);
return view;
}
@Override
public void onResume() {
super.onResume();
/**
* Load your stuffs here.
*/
}
}