只有在被选中时才在 ViewPager 中加载片段
Posted
技术标签:
【中文标题】只有在被选中时才在 ViewPager 中加载片段【英文标题】:load fragment in ViewPager only when its selected 【发布时间】:2018-05-09 09:04:10 【问题描述】:我有一个带有 3 个标签的 ViewPager。
我在每个片段中加载大数据。
应用程序会加载每个片段,但我只想在片段被选中时才加载片段。
我该怎么做?我不知道。 我在等你的帮助。谢谢
我的代码:
public class Fragments extends AppCompatActivity
private TabLayout tabLayout;
private ViewPager viewPager;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_tabs);
viewPager = (ViewPager) findViewById(R.id.viewpager);
setupViewPager(viewPager);
tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
private void setupViewPager(ViewPager viewPager)
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new FirstFragment(), "1");
adapter.addFragment(new SecondFragment(), "2");
adapter.addFragment(new ThirdFragment(), "3");
viewPager.setAdapter(adapter);
class ViewPagerAdapter extends FragmentPagerAdapter
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager)
super(manager);
@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);
@Override
public CharSequence getPageTitle(int position)
return mFragmentTitleList.get(position);
【问题讨论】:
【参考方案1】:如果没有人给你一个好的答案,我知道这是 5 年后,但任何人都在读这篇文章。我实际上遇到了相反的问题。我需要同时加载所有标签。现在发生在我身上的是一次只加载一个标签。我需要将此适配器用于带有 tablayout 的 viewpager2,以便我可以针对我的特定用例禁用从左到右滑动的 viewpager。
这是我的代码:
警告代码在 KOTLIN 而非 JAVA 中
class RecipeTabAdapter internal constructor(fm: FragmentManager, lifecycle: Lifecycle) : FragmentStateAdapter(fm, lifecycle)
val fragmentsList: ArrayList<Fragment> = arrayListOf()
fun addFragment(fragment: Fragment)
fragmentsList.add(fragment)
override fun getItemCount(): Int
return fragmentsList.size
override fun createFragment(position: Int): Fragment
when (position)
position -> fragmentsList[position]
position -> fragmentsList[position]
return fragmentsList[position]
【讨论】:
【参考方案2】:是否可以禁用离屏页面限制?
没有。它已设置为可能的最小值:查看页面的每一侧都有一个页面。这是使动画效果发挥作用所必需的——您可以同时看到两个片段(原始片段和新片段)的一部分。
【讨论】:
【参考方案3】:在
OncreateView()
//.... dont initialize your view here
if(isMenuVisible()) // menu should be visible if current fragment is visible right now
setUserVisibleHint(true); // manually set value to true
在
oncreate()
setHasOptionsMenu(true);
最后有一个名为 setuservisiblehint() 的方法,该方法仅在片段对用户可见时调用,这是您初始化所有视图的唯一方法。
@Override
public void setUserVisibleHint(boolean isVisibleToUser)
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser && v != null)
// initialize your view here and call you fetch_data_function()
【讨论】:
【参考方案4】:这是我的解决方案,它按预期工作。在您的所有子片段中创建一个boolean
变量:
private boolean loadFragmentExecuted = false;
在子片段中创建一个名为 loadFragment
的通用方法,并将您在 onCreateView
中添加的所有逻辑移至该方法:
public void loadFragment()
if(!loadFragmentExecuted)
//Add your logic to manipulate the UI or load data etc...
loadFragmentExecuted = true;
在您的网页浏览逻辑中动态创建片段,例如:
//add the fragment
String fragmentName = "com.something." + fragmentId;
//check if the class exists
try
Class myFragmentClass = Class.forName(fragmentName);
Fragment myFragment = (Fragment) myFragmentClass.newInstance();
mFragments.add(myFragment);
catch (ClassNotFoundException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
catch (InstantiationException e)
e.printStackTrace();
然后设置您的寻呼机适配器并附上一个tablayout:
//set our pager adapter that contains different fragments
mPagerAdapter = new BasePagerAdapter(mFragmentManager, mFragments);
//link the adapter to the viewpager
mViewPager.setAdapter(mPagerAdapter);
//cache fragments
int limit = (mPagerAdapter.getCount() > 0 ? mPagerAdapter.getCount() : 1);
mViewPager.setOffscreenPageLimit(limit);
//add the page listner to the viewPager and link it to the tabLayout
mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabLayout));
//on tab selected select current viewpager item
mTabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
@Override
public void onTabSelected(TabLayout.Tab tab)
mViewPager.setCurrentItem(tab.getPosition());
//get fragment for the selected tab
Fragment f = mPagerAdapter.getItem(tab.getPosition());
//load the content of the fragment
try
Class c = f.getClass();
Method loadFragment = c.getMethod("loadFragment");
loadFragment.invoke(f);
catch (IllegalAccessException e)
catch (InvocationTargetException e)
catch (NoSuchMethodException e)
@Override
public void onTabUnselected(TabLayout.Tab tab)
@Override
public void onTabReselected(TabLayout.Tab tab)
);
【讨论】:
【参考方案5】:我有一个不需要子类化的解决方案,并且很容易引入到现有项目中。它使用子片段机制。
基本思想是用几乎空的片段替换您的内容片段,并在用户真正可见时将您的内容片段添加为子片段
代码的要点是这样的
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState)
super.onViewCreated(view, savedInstanceState);
boolean hasFragment = getChildFragmentManager().findFragmentById(R.id.container) != null;
if (hasFragment)
return;
if (getUserVisibleHint())
addFragment("onViewCreated");
@Override
public void onResume()
super.onResume();
if (getUserVisibleHint())
addFragment("onResume");
@Override
public void setUserVisibleHint(boolean isVisibleToUser)
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser && isResumed())
addFragment("setUserVisibleHint");
private void addFragment(String cause)
if (getChildFragmentManager().findFragmentById(R.id.container) == null)
getChildFragmentManager().beginTransaction()
.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
.add(R.id.container, createFragment()).commit();
在此处查看我的完整解决方案,其中还包含一个进度条,以及以指定延迟自动开始加载背景片段的选项:Lazy Load Fragment
【讨论】:
这行不通。由于 onResume 已经被调用,并且 isVisibleToUser 仅在用户可见时才为真,因此不会满足此条件,因此它不是解决方案。以上是关于只有在被选中时才在 ViewPager 中加载片段的主要内容,如果未能解决你的问题,请参考以下文章
[Android] Android ViewPager 中加载 Fragmenet的几种方式
将 ViewPager 与 Fragments 一起使用时,在滑动时会破坏 Fragment