【问题标题】:ViewPager not inflating FragmentViewPager 不膨胀片段
【发布时间】:2020-03-19 07:02:11
【问题描述】:

我正在使用ViewPager2FragmentStateAdapterTabLayout 创建选项卡式布局。我的 TabLayout 和 ViewPager2 在 Fragment 中,并且适配器有一个列表,其中包含另外两个用于选项卡的片段。当我使用调试器或在日志语句中时,永远不会调用每个片段的 OnCreateViewcreateFragment 也永远不会在选项卡适配器中调用

MainTabHolderFragment:片段

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    val tabAdapter = TabAdapter(childFragmentManager, lifecycle)
    tabAdapter.addFragment(AddItemFragment(), "Add Item")
    tabAdapter.addFragment(WishListFragment(), "Wish List")

    binding.viewPager.adapter = tabAdapter
    TabLayoutMediator(
        binding.tabLayout, binding.viewPager,
        TabLayoutMediator.TabConfigurationStrategy { tab, position ->
            tab.text = tabAdapter.getPageTitle(position)
            Timber.d("tab = ${tab.position}, pos = $position")
            binding.viewPager.setCurrentItem(position, true)
        }).attach()
}

TabAdapter

class TabAdapter(fm: FragmentManager, lifecycle: Lifecycle) : FragmentStateAdapter(fm, lifecycle) {

    private val fragmentList = mutableListOf<FragmentListItem>()

    override fun createFragment(position: Int) = fragmentList[position].fragment

    override fun getItemCount() = fragmentList.size

    fun addFragment(fragment: Fragment, title: String) {
        fragmentList.add(FragmentListItem(fragment, title))
    }

    fun getPageTitle(position: Int): CharSequence? = fragmentList[position].title


    private data class FragmentListItem(val fragment: Fragment, val title: String)
}

TabLayoutMediator 中的tab.postion 变量始终为-1,ViewPager 永远不会对fragment 进行膨胀,导致tab 布局下出现黑屏。我需要使用TabLayoutMediatorFragmentStateAdapter 以外的其他内容吗?

编辑:添加了说明 createFragment 未调用的信息

【问题讨论】:

    标签: android android-fragments kotlin android-viewpager


    【解决方案1】:

    太简单了,添加这个..(ONCREATEVIEW 内部)

    TabLayout tabs = (TabLayout) findViewById(R.id.tabsID);
    
        tabsID.addTab(tabsID.newTab().setText("Fragment1"));
        tabsID.addTab(tabsID.newTab().setText("Fragment2"));
    

    现在您已经有了带有名称的 tablayout,现在创建方法(ONCREATEVIEW 之外),您必须为每个 TABITEM 创建一个

    public void homeScreen () {
        homeAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_activated_2, homeInformation) {
            @NonNull
            @Override
            public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
                if (convertView == null) {
                    LayoutInflater inflater = (LayoutInflater) getActivity().getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                    convertView = inflater.inflate(R.layout.home_item, parent, false);
                }
    
                Random rand = new Random();
                int random_number_home = rand.nextInt(10) + 1;
    
                TextView number_home_list  = (TextView) convertView.findViewById(R.id.number_home_list);
                TextView textViewHome = (TextView) convertView.findViewById(R.id.textViewHome);
                textViewHome.setText(homeInformation[position]);
                number_home_list.setText(Integer.toString(random_number_home));
                return convertView;
            }
        };
        homeList.setAdapter(homeAdapter);
    }
    

    此代码显示带有随机数的列表视图,现在此代码用于选择不同的选项卡....当您进入应用程序时,第一个主屏幕是您看到的第一个主屏幕(ONCREATEVIEW 内部)

    homeScreen();
    
        final TabLayout.BaseOnTabSelectedListener eventChangeTab = new TabLayout.BaseOnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                if (tab.getText().toString().equals("Resumen")) {
                    homeScreen();
                } else if (tab.getText().toString().equals("Datos Abonado")) {
                    receiptsScreen();
                } 
            }
    
    
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
    
            }
    
    
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
                if (tab.getText().toString().equals("Fragment1")) {
                    homeScreen();
                } else if (tab.getText().toString().equals("Fragment2")) {
                    receiptsScreen();
                } 
            }
        };
    
        tabsID.addOnTabSelectedListener(eventChangeTab );
    

    【讨论】:

    • 这个homeList是什么类型的?我为 viewpager 的每一页使用单独的片段,而不是一个被重写的 ListView。谢谢你的帮助,但这似乎不是我的问题
    • ListView 主列表; (oncreateview 之外)和 homelist = (ListView) rootView.findViewById(R.id.list_Home); (oncreateview里面) -->list_Home是XML中的listview ID
    • 如果你有 3 个标签,你必须创建 3 个片段,如果你想在一个片段中显示不同的东西是不同的,
    【解决方案2】:

    我的建议是仅使用 Fragment 参数更改 TabAdapterConstructor,并将其用作我个人项目的下一个方法:

    class YourAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
    
        private lateinit var yourList: List<YourListType>
    
        override fun getItemCount(): Int = yourList.size
    
        override fun createFragment(position: Int): Fragment =
            YourFragment.instance(yourList[position]) // Only is needed to pass data
    
        fun setList(yourList: List<YourListType>) {
            this.yourList = yourList
        }
    } 
    

    以及在主片段中设置的ViewPager:

    view_pager.adapter = YourAdapter(this).apply{ 
        setList(yourList) 
    }
    

    以及初始化Fragment的方法:

    companion object {
            private const val KEY_YOUR_OBJECT = "KEY_YOUR_OBJECT"
    
            fun instance(yourObject: YourObject): YourFragment {
                val arguments = Bundle().apply {
                    putSerializable(KEY_YOUR_OBJECT, yourObject)
                }
    
                return YourFragment().apply {
                    this.arguments = arguments
                }
            }
    }
    

    【讨论】:

    • 不幸的是 createFragment 从未被调用,所以这似乎不是解决方案。使用片段的instance 方法,是你自己使用单例模式的实现吗?
    猜你喜欢
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 2016-02-11
    • 2013-07-02
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    相关资源
    最近更新 更多