英文:
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"
<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'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">
<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>
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 -> return RadarFragment()
        1 -> 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(
    "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
}
}
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 -> {
                    Toast.makeText(this@MainActivity, "First Item Clicked", Toast.LENGTH_SHORT).show()
                }
                R.id.drawerFilters -> {
                    Toast.makeText(this@MainActivity, "Second Item Clicked", Toast.LENGTH_SHORT).show()
                }
                R.id.drawerSettings -> {
                    Toast.makeText(this@MainActivity, "third Item Clicked", 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">
<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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:defaultNavHost="true"
    app:layout_constraintBottom_toTopOf="@id/nav_view"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:navGraph="@navigation/mobile_navigation" />
<androidx.drawerlayout.widget.DrawerLayout 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/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/drawerNavView"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer_nav_menu" />
</androidx.drawerlayout.widget.DrawerLayout>
</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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论