【问题标题】:How to use ViewPager2 with tabs in Kotlin?如何在 Kotlin 中使用 ViewPager2 和选项卡?
【发布时间】:2021-03-03 09:39:09
【问题描述】:

实际上,在我的应用程序中,我有一个包含第一个片段的活动,然后从该片段中我能够按一些按钮导航到另一个片段,现在我将更改活动并添加一个 tablayout 从中我将能够在我拥有的三个片段之间导航,但是通过阅读文档,我无法理解如何使用 ViewPager2 通过单击选项卡在其中显示我的片段。

我的活动布局现在看起来像这样:

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".LetturaActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        app:elevation="0dp"
        android:layout_height="wrap_content"
        android:theme="@style/Theme.VisualStock.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/Theme.VisualStock.PopupOverlay" />

        <com.google.android.material.tabs.TabLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:elevation="8dp"
            app:tabSelectedTextColor="#ffffff"
            app:tabBackground="@drawable/tab_selector"
            app:tabIndicatorGravity="top"
            app:tabIndicatorColor="#ffffff"
            app:tabMode="fixed">

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/riepilogo"
                />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/testata"
                />

            <com.google.android.material.tabs.TabItem
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/corpo"
                />

        </com.google.android.material.tabs.TabLayout>

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />


    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/floatingActionButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:clickable="true"
        android:contentDescription="@string/menu_per_lo_scarico_nuovo_documento_o_riepilogo_articoli"
        android:focusable="true"
        app:fabSize="normal"
        app:layout_anchor="@+id/pager"
        app:layout_anchorGravity="end|bottom"
        app:srcCompat="@drawable/ic_add"
        app:tint="@android:color/white" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

然后我有三个像这样的片段文件:

class LetturaFragment : Fragment() {
...
      override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_lettura, container, false)
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
...
     }
 }

class ArticoliFragment : Fragment() {
    override fun onCreateView(
            inflater: LayoutInflater, container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_articoli, container, false)
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
...
}
}

和活动

class LetturaActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_lettura)
}

如何使用我的片段在选项卡中导航并在 ViewPager2 中显示它们?

【问题讨论】:

  • 嗨,Kasper Juner 先生,如果我的回答是正确的,请将其标记为有用

标签: android kotlin android-fragments android-viewpager2


【解决方案1】:

你问我在我的项目中应用的同样的东西也适用于你

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/root_layout_home_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">


<com.google.android.material.tabs.TabLayout
    android:id="@+id/home_fragment_tabs"
    android:layout_width="match_parent"
    android:layout_height="?android:attr/actionBarSize"
    android:background="@drawable/gradianttoolbarbottom"
    app:itemTextColor="@drawable/custom_menue_bar_color"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"

    app:layout_constraintTop_toBottomOf="@+id/constraintLayout3"
    app:tabGravity="fill"
    app:tabIndicatorColor="@color/Orange"
    app:tabMode="scrollable"
    app:tabSelectedTextColor="@color/white"
    app:tabTextColor="@color/gray_400_dark" />

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/home_fragment_viewPager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:animateLayoutChanges="true"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/home_fragment_tabs" />

 </androidx.constraintlayout.widget.ConstraintLayout>

这是 Kotlin 类

 class Home_Fragment : Fragment() {
private lateinit var homeViewModel: HomeFragmentViewModel
private var myContext: FragmentActivity? = null


override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
    homeViewModel = ViewModelProvider(this).get(HomeFragmentViewModel::class.java)
    val root = inflater.inflate(R.layout.fragment_home, container, false)
    myContext=activity
    val viewpagger: ViewPager2 =root.findViewById<ViewPager2>(R.id.home_fragment_viewPager)
    viewpagger.isSaveEnabled=false
    val tabs: TabLayout = root.findViewById<TabLayout>(R.id.home_fragment_tabs)
    val adapter =MyViewPagerAdapter(childFragmentManager,lifecycle)
    adapter.addFragment(Fragment1(), getString(R.string.text_Fragment1))
    adapter.addFragment(Fragment2(), getString(R.string.text_Fragment2))
    adapter.addFragment(Fragment3(), getString(R.string.text_Fragment3))
    adapter.addFragment(Fragment4(),getString(R.string.text_Fragment4))
    adapter.addFragment(Fragment5(), getString(R.string.text_Fragment5))
    adapter.notifyDataSetChanged()
    viewpagger.adapter =adapter
      TabLayoutMediator(tabs, viewpagger) { tab, position ->
        tab.text = adapter.getPageTitle(position)
        viewpagger.setCurrentItem(tab.position, true)
    }.attach()
    return root
  }

   class MyViewPagerAdapter(manager: FragmentManager, lifecycle: Lifecycle) :  FragmentStateAdapter(manager,lifecycle ){
    private val fragmentList : MutableList<Fragment> =ArrayList()
    private val titleList : MutableList<String> =ArrayList()
    override fun getItemCount(): Int {
        return fragmentList.size
    }

    override fun createFragment(position: Int): Fragment {
        return  fragmentList[position]
    }


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

    fun getPageTitle(position: Int): CharSequence? {
        return titleList[position]
    }
  }
 }

【讨论】:

  • 如何设置选项卡默认选择第一项?我的意思是标签1而不是0?通过设置 tablayout.getTabAt(1)?.select() 它在加载活动时滚动到
  • for set tab of any position just right viewpagger.setCurrentItem(2) // 传递你想要的任何位置,但在 TabLayoutMediator(){}.attach() 之后键入这行代码
  • 嗨 Hassnain,还有一个问题,现在我只用图标设置选项卡,我这样做就像 `tablayout.getTabAt(0)?.icon = ContextCompat.getDrawable(this, R.drawable. .attach() 之后的 ic_outline_inventory)` 是正确的方法吗?
  • 正确的方法是在 .attach() 之前执行诸如设置文本图标等之类的操作,或者如果您想覆盖默认设置,则在 .attach 之后执行此操作,但不让支持任何空引用错误
【解决方案2】:

您需要使用适配器将您的活动与 ViewPager2 对象挂钩。见here

【讨论】:

    【解决方案3】:

    您需要一个适配器将这些片段显示到TabLayout

    class PagerAdapter(fragmentActivity: FragmentActivity) :
        FragmentStateAdapter(fragmentActivity) {
    
        override fun createFragment(position: Int): Fragment {
            when (position){
                 0 -> {
                     return LetturaFragment.newInstance(position)
                 }
                 1->{
                     return ArticoliFragment.newInstance(position)
                     }
    
            }
            return LetturaFragment.newInstance(position)
        }
    
        override fun getItemCount(): Int {
            return ITEM_COUNT
        }
    
        companion object {
            private const val ITEM_COUNT = 2
        }
    }
    

    在您的 Fragments 中,定义伴随对象以获取像这样的单个实例

    class LetturaFragment : Fragment() {
    ...
          override fun onCreateView(
                inflater: LayoutInflater, container: ViewGroup?,
                savedInstanceState: Bundle?
        ): View? {
            // Inflate the layout for this fragment
            return inflater.inflate(R.layout.fragment_lettura, container, false)
        }
        override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
    ...
         }
        companion object {
            private const val ARG_COUNT = "param1"
            fun newInstance(counter: Int?): LetturaFragment {
                val fragment = LetturaFragment()
                val args = Bundle()
                args.putInt(ARG_COUNT, counter!!)
                fragment.arguments = args
                return fragment
            }
        }
     }
    
    

    其他子片段也一样

    现在在您的Activity 中,创建一个TabLayoutMediator 以将TabLayout 链接到ViewPager2,并将其附加如下:

    viewPager.adapter = PagerAdapter(this)
     TabLayoutMediator(tabLayout, viewPager) { tab, position ->
                tab.setText("$position + 1")
                mainBinding.pager.setCurrentItem(tab.position, true)
            }.attach()
    

    更多详情请阅读this

    【讨论】:

      【解决方案4】:

      使用这个 TabLayoutMediator 如下after you set adapter to ViewPager2

      TabLayoutMediator(tab_layout, view_pager) { tab, position ->
                      tab.text = fragmentList[position].second
                  }.attach()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-05-10
        • 1970-01-01
        • 1970-01-01
        • 2019-05-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-07-21
        相关资源
        最近更新 更多