英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论