仅在选中时才在ViewPager中加载片段

时间:2017-11-25 17:24:51

标签: android android-fragments android-viewpager android-tabs

我有一个带有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);
        }
    }
}

5 个答案:

答案 0 :(得分: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]
}

}

答案 1 :(得分:0)

  

是否可以禁用屏幕外页面限制?

没有。它已设置为最小可能值:查看页面每侧一页。这对于使动画效果起作用是必要的 - 你可以同时看到两个片段(原始片段和新片段)的一部分。

答案 2 :(得分:0)

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()

}

答案 3 :(得分:0)

这是我的解决方案,它按预期工作。在您的所有子片段中创建一个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)
    {
    }
});

答案 4 :(得分:-1)

我有一个不需要子类化的解决方案,并且很容易引入现有项目中。它使用子片段机制。

基本思想是用几乎为空的片段替换您的内容片段,并在用户真正看到它时将您的内容片段添加为子片段

代码要旨是这样的

@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