Android Kotlin ViewPager2 和 TabLayout 在一个片段中不显示在屏幕上。

huangapple go评论72阅读模式
英文:

Android Kotlin ViewPager2 and TabLayout in a fragment not showing up on the screen

问题

以下是您提供的内容的中文翻译:

"代码工作正常,编译无错误,应用程序打开,底部导航正常工作,但我放置视图页面和选项卡布局的片段为空。请参见[截图][1]。"

"由于编译或logcat中没有错误,我不知道要尝试什么。"

"这是我的布局"

<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ui.browse.BrowseFragment">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/browse_tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"/>

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/browse_view_pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/browse_tab_layout"
        app:layout_constraintBottom_toBottomOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

"我的适配器"

import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter

private const val NUM_TABS = 2

public class BrowsePagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    FragmentStateAdapter(fragmentManager, lifecycle) {

    override fun getItemCount(): Int {
        return NUM_TABS
    }

    override fun createFragment(position: Int): Fragment {
        when (position) {
            0 -> return RadarFragment()
            1 -> return MatchFragment()
        }
        return RadarFragment()
    }
}

"以及在屏幕上为空的我的片段"

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.android.material.tabs.TabLayoutMediator
import com.swarm.databinding.FragmentBrowseBinding

class BrowseFragment : Fragment() {

    private var _binding:FragmentBrowseBinding? = null;
    private val binding get() = _binding!!;
    val fragmentsArray = arrayOf(
        "Radar",
        "Match"
    )

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentBrowseBinding.inflate(inflater,container,false);
        val view = binding.root;
        return view;
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val viewPager = binding.browseViewPager
        val tabLayout = binding.browseTabLayout

        val adapter = BrowsePagerAdapter(childFragmentManager, lifecycle)
        viewPager.adapter = adapter

        TabLayoutMediator(tabLayout, viewPager) { tab, position ->
            tab.text = fragmentsArray[position]
        }.attach()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

"我的主要活动"

import android.os.Bundle
import android.widget.Toast
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.swarm.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 设置内容视图
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        // 设置导航
        val navView: BottomNavigationView = binding.navView
        val navController = findNavController(R.id.nav_host_fragment_activity_main)

        // 设置顶级目的地
        val appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.navigation_feed, R.id.navigation_browse, R.id.navigation_explore, R.id.navigation_inbox
            )
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)

        // 抽屉
        binding.apply {
            drawerNavView.setNavigationItemSelectedListener {
                when (it.itemId) {
                    R.id.drawerMood -> {
                        Toast.makeText(this@MainActivity, "第一项已点击", Toast.LENGTH_SHORT).show()
                    }
                    R.id.drawerFilters -> {
                        Toast.makeText(this@MainActivity, "第二项已点击", Toast.LENGTH_SHORT).show()
                    }
                    R.id.drawerSettings -> {
                        Toast.makeText(this@MainActivity, "第三项已点击", Toast.LENGTH_SHORT).show()
                    }
                }
                true
            }
        }
    }
}

"和我的主要布局"

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="?attr/actionBarSize">

    <com.google.android.material.bottomnavigation.BottomNavigationView
        android:id="@+id/nav_view"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="0dp"
        android:layout_marginEnd="0dp"
        android:background="?android:attr/windowBackground"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:menu="@menu/bottom_nav_menu" />

    <fragment
        android:id="@+id/nav_host_fragment_activity_main"
        android:name="androidx.navigation.fragment.NavHostFragment&quot

<details>
<summary>英文:</summary>

The code works fine and compiles without error, the application opens, and the bottom nav works, but the fragment where I put my view pager and tab layout is empty. See [screenshot][1].



Since there is no error at compilation or the logcat, I don&#39;t know what to try.

Here is my layout

<?xml version="1.0" encoding="utf-8"?>
<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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.browse.BrowseFragment">

&lt;com.google.android.material.tabs.TabLayout
    android:id=&quot;@+id/browse_tab_layout&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;wrap_content&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot;/&gt;

&lt;androidx.viewpager2.widget.ViewPager2
    android:id=&quot;@+id/browse_view_pager&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;0dp&quot;
    app:layout_constraintTop_toBottomOf=&quot;@id/browse_tab_layout&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;/&gt;

</androidx.constraintlayout.widget.ConstraintLayout>


my adapter

import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter

private const val NUM_TABS = 2

public class BrowsePagerAdapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
FragmentStateAdapter(fragmentManager, lifecycle) {

override fun getItemCount(): Int {
    return NUM_TABS
}

override fun createFragment(position: Int): Fragment {
    when (position) {
        0 -&gt; return RadarFragment()
        1 -&gt; return MatchFragment()
    }
    return RadarFragment()
}

}


and my fragment that appears empty on the screen

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.google.android.material.tabs.TabLayoutMediator
import com.swarm.databinding.FragmentBrowseBinding

class BrowseFragment : Fragment() {

private var _binding:FragmentBrowseBinding? = null;
private val binding get() = _binding!!;
val fragmentsArray = arrayOf(
    &quot;Radar&quot;,
    &quot;Match&quot;
)

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    _binding = FragmentBrowseBinding.inflate(inflater,container,false);
    val view = binding.root;
    return view;
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    val viewPager = binding.browseViewPager
    val tabLayout = binding.browseTabLayout

    val adapter = BrowsePagerAdapter(childFragmentManager, lifecycle)
    viewPager.adapter = adapter

    TabLayoutMediator(tabLayout, viewPager) { tab, position -&gt;
        tab.text = fragmentsArray[position]
    }.attach()
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

}


my main activity

import android.os.Bundle
import android.widget.Toast
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController
import com.swarm.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

private lateinit var binding: ActivityMainBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // set content view
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)

    // set nav
    val navView: BottomNavigationView = binding.navView
    val navController = findNavController(R.id.nav_host_fragment_activity_main)

    // set top level destinations
    val appBarConfiguration = AppBarConfiguration(
        setOf(
            R.id.navigation_feed, R.id.navigation_browse, R.id.navigation_explore, R.id.navigation_inbox
        )
    )
    setupActionBarWithNavController(navController, appBarConfiguration)
    navView.setupWithNavController(navController)

    // drawer
    binding.apply {
        drawerNavView.setNavigationItemSelectedListener {
            when (it.itemId) {
                R.id.drawerMood -&gt; {
                    Toast.makeText(this@MainActivity, &quot;First Item Clicked&quot;, Toast.LENGTH_SHORT).show()
                }
                R.id.drawerFilters -&gt; {
                    Toast.makeText(this@MainActivity, &quot;Second Item Clicked&quot;, Toast.LENGTH_SHORT).show()
                }
                R.id.drawerSettings -&gt; {
                    Toast.makeText(this@MainActivity, &quot;third Item Clicked&quot;, Toast.LENGTH_SHORT).show()
                }
            }
            true
        }
    }
}

}


and my main layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingTop="?attr/actionBarSize">

&lt;com.google.android.material.bottomnavigation.BottomNavigationView
    android:id=&quot;@+id/nav_view&quot;
    android:layout_width=&quot;0dp&quot;
    android:layout_height=&quot;wrap_content&quot;
    android:layout_marginStart=&quot;0dp&quot;
    android:layout_marginEnd=&quot;0dp&quot;
    android:background=&quot;?android:attr/windowBackground&quot;
    app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
    app:layout_constraintLeft_toLeftOf=&quot;parent&quot;
    app:layout_constraintRight_toRightOf=&quot;parent&quot;
    app:menu=&quot;@menu/bottom_nav_menu&quot; /&gt;

&lt;fragment
    android:id=&quot;@+id/nav_host_fragment_activity_main&quot;
    android:name=&quot;androidx.navigation.fragment.NavHostFragment&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    app:defaultNavHost=&quot;true&quot;
    app:layout_constraintBottom_toTopOf=&quot;@id/nav_view&quot;
    app:layout_constraintLeft_toLeftOf=&quot;parent&quot;
    app:layout_constraintRight_toRightOf=&quot;parent&quot;
    app:layout_constraintTop_toTopOf=&quot;parent&quot;
    app:navGraph=&quot;@navigation/mobile_navigation&quot; /&gt;

&lt;androidx.drawerlayout.widget.DrawerLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    android:id=&quot;@+id/drawerLayout&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    android:fitsSystemWindows=&quot;true&quot;
    tools:openDrawer=&quot;start&quot;&gt;

    &lt;com.google.android.material.navigation.NavigationView
        android:id=&quot;@+id/drawerNavView&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;match_parent&quot;
        android:layout_gravity=&quot;start&quot;
        android:fitsSystemWindows=&quot;true&quot;
        app:headerLayout=&quot;@layout/drawer_header&quot;
        app:menu=&quot;@menu/drawer_nav_menu&quot; /&gt;

&lt;/androidx.drawerlayout.widget.DrawerLayout&gt;

</androidx.constraintlayout.widget.ConstraintLayout>


  [1]: https://i.stack.imgur.com/ZuSjs.jpg

</details>


# 答案1
**得分**: 1

你需要像下面这样更改 **onCreateView** 方法:

```kotlin
override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    _binding = FragmentBrowseBinding.inflate(inflater, container, false)
    val view = _binding!!.root
    return view
}

你需要将变量 view = binding.root; 替换为 view = _binding!!.root;

正确的绑定不返回任何视图,这就是问题发生的原因。

英文:

You have to change the onCreateView like below.

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = FragmentBrowseBinding.inflate(inflater,container,false);
        val view = _binding!!.root;
        return view;
    }

You to replace the view variable view = binding.root; to view = _binding!!.root;

Right the binding not returning any view that's why the issue occurs

huangapple
  • 本文由 发表于 2023年5月30日 12:09:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/76361563.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定