【问题标题】:Bottom Navigation Bar Floating Button with action covering the whole screen - how to do this?底部导航栏浮动按钮,动作覆盖整个屏幕 - 如何做到这一点?
【发布时间】:2022-09-23 19:29:12
【问题描述】:

我有一个带有底部导航栏的 Android 应用程序。在主活动中,我有一个浮动按钮,当我按下它时,我想打开一个覆盖整个屏幕的片段(或其他活动?)(底部导航栏和其他内容将在我新打开的片段下方).我想补充一点,这个新打开的片段将用于添加一些项目,当用户填写名称、体重等所有文件并单击“添加”时,片段应该关闭,我们应该看到底部导航条及其\' 片段。

你能提供我的问题的解决方案吗?我将不胜感激一些代码能够做到这一点!

以下是我的代码中最重要的部分:

活动主.xml:

<?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: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_constraintHorizontal_bias=\"0.0\"
        app:layout_constraintLeft_toLeftOf=\"parent\"
        app:layout_constraintRight_toRightOf=\"parent\"
        app:layout_constraintTop_toTopOf=\"parent\"
        app:layout_constraintVertical_bias=\"1.0\"
        app:navGraph=\"@navigation/mobile_navigation\" />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id=\"@+id/buttonAdd\"
        android:layout_width=\"wrap_content\"
        android:layout_height=\"wrap_content\"
        android:layout_marginEnd=\"16dp\"
        android:layout_marginBottom=\"84dp\"
        android:contentDescription=\"@string/add_button\"
        android:src=\"@drawable/ic_add\"
        app:layout_constraintBottom_toBottomOf=\"parent\"
        app:layout_constraintEnd_toEndOf=\"parent\" />


</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity.kt:

package com.example.myapp

import android.os.Bundle
import android.view.View
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.example.myapp.databinding.ActivityMainBinding
import com.example.myapp.ui.AddProductFragment
import com.google.android.material.snackbar.Snackbar

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)
        // Passing each menu ID as a set of Ids because each
        // menu should be considered as top level destinations.
        val appBarConfiguration = AppBarConfiguration(setOf(
                R.id.navigation_expiring, R.id.navigation_storages, R.id.navigation_notifications))
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)

        // floating button:
        val buttonAdd: View = findViewById(R.id.buttonAdd)
        buttonAdd.setOnClickListener {
            //navigate(R.id.action_login_to_registration)
            //view.findNavController().navigate(R.id.actionAddProduct)
            supportFragmentManager
                .beginTransaction().add(R.id.nav_host_fragment_activity_main, AddProductFragment())
                .commit()
        }
    }
}

fragment_storages.xml:(我已经拥有的其他片段几乎相同)

<?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.storages.StoragesFragment\">

    <TextView
        android:id=\"@+id/text_dashboard\"
        android:layout_width=\"match_parent\"
        android:layout_height=\"wrap_content\"
        android:layout_marginStart=\"8dp\"
        android:layout_marginTop=\"8dp\"
        android:layout_marginEnd=\"8dp\"
        android:textAlignment=\"center\"
        android:textSize=\"20sp\"
        app:layout_constraintBottom_toBottomOf=\"parent\"
        app:layout_constraintEnd_toEndOf=\"parent\"
        app:layout_constraintStart_toStartOf=\"parent\"
        app:layout_constraintTop_toTopOf=\"parent\" />
</androidx.constraintlayout.widget.ConstraintLayout>

StoragesFragment.kt:(我已经拥有的其他片段几乎一样)

package com.example.myapp.ui.storages

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.example.myapp.databinding.FragmentStoragesBinding

class StoragesFragment : Fragment() {

    private var _binding: FragmentStoragesBinding? = null

    // This property is only valid between onCreateView and
    // onDestroyView.
    private val binding get() = _binding!!

    override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
    ): View {
        val dashboardViewModel =
                ViewModelProvider(this).get(StoragesViewModel::class.java)

        _binding = FragmentStoragesBinding.inflate(inflater, container, false)
        val root: View = binding.root

        val textView: TextView = binding.textDashboard
        dashboardViewModel.text.observe(viewLifecycleOwner) {
            textView.text = it
        }
        return root
    }

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

片段添加产品.xml:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"
    xmlns:tools=\"http://schemas.android.com/tools\"
    android:layout_width=\"match_parent\"
    android:layout_height=\"match_parent\"
    tools:context=\".ui.AddProductFragment\">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width=\"match_parent\"
        android:layout_height=\"match_parent\"
        android:text=\"Add Product Fragment\" />

</androidx.constraintlayout.widget.ConstraintLayout>

AddProductFragment.kt:

package com.example.myapp.ui

import android.os.Bundle
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.myapp.R

class AddProductFragment : Fragment() {

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

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_add_product, container, false)
    }
}

bottom_nav_menu.xml:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">

    <item
        android:id=\"@+id/navigation_expiring\"
        android:icon=\"@drawable/ic_expiring\"
        android:title=\"@string/title_expiring\" />

    <item
        android:id=\"@+id/navigation_storages\"
        android:icon=\"@drawable/ic_storages\"
        android:title=\"@string/title_storages\" />

    <item
        android:id=\"@+id/navigation_notifications\"
        android:icon=\"@drawable/ic_notifications_black_24dp\"
        android:title=\"@string/title_notifications\" />

</menu>

mobile_navigation.xml:

<?xml version=\"1.0\" encoding=\"utf-8\"?>
<navigation 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/mobile_navigation\"
    app:startDestination=\"@+id/navigation_expiring\">

    <fragment
        android:id=\"@+id/navigation_expiring\"
        android:name=\"com.example.myapp.ui.expiring.ExpiringFragment\"
        android:label=\"@string/title_expiring\"
        tools:layout=\"@layout/fragment_expiring\" >
    </fragment>

    <fragment
        android:id=\"@+id/navigation_storages\"
        android:name=\"com.example.myapp.ui.storages.StoragesFragment\"
        android:label=\"@string/title_storages\"
        tools:layout=\"@layout/fragment_storages\" />

    <fragment
        android:id=\"@+id/navigation_notifications\"
        android:name=\"com.example.myapp.ui.notifications.NotificationsFragment\"
        android:label=\"@string/title_notifications\"
        tools:layout=\"@layout/fragment_notifications\" />

    <fragment
        android:id=\"@+id/navigation_add_product\"
        android:name=\"com.example.myapp.ui.AddProductFragment\"
        android:label=\"Add product\"
        tools:layout=\"@layout/fragment_notifications\" />

</navigation>

    标签: android kotlin android-fragments bottomnavigationview bottom-navigation-bar


    【解决方案1】:

    不要导航到片段,而是在单击“添加”浮动操作按钮后尝试启动另一个 Activity。 您的新活动不会像您预期的那样有底部导航栏。

    【讨论】:

    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
    • 好的,你是对的 - 启动新的 Activity 是一个很好的解决方案。但是,如何使用 Fragment 实现相同的功能?
    • @The_Long_Distance_Runner 您找到解决方案了吗?
    • @w0wka91 不幸的是,没有,在开始新活动时使用了这个想法。您是否知道如何使用 Fragment 执行此操作?
    【解决方案2】:

    我有一个解决方案。它对我有用。 首先,您只需在 BottomNavigationView 所在的 Activity 中编写此代码。

    MainActivity.xml

     binding.fab.setOnClickListener(object : View.OnClickListener {
            override fun onClick(view: View) {
                binding.bottomNavigationView.selectedItemId = R.id.nav_cards
                navController.navigate(R.id.nav_cards)
            }
        })
        binding.bottomNavigationView.setOnItemSelectedListener {
            when (it.itemId) {
                R.id.nav_home -> {
                    navController.navigate(R.id.nav_home)
                    true
                }
                R.id.nav_book -> {
                    navController.navigate(R.id.nav_book)
                    true
                }
                R.id.nav_bookmark -> {
                    navController.navigate(R.id.nav_bookmark)
                    true
                }
                R.id.nav_settings -> {
                    navController.navigate(R.id.nav_settings)
                    true
                }
                else -> false
            }
        }
    

    之后,您应该使用 onBackPressed 函数。否则,您可能会出现另一个属于收集 backStacks 的问题。

      override fun onBackPressed() {
        if (binding.bottomNavigationView.selectedItemId == R.id.nav_home) {
            binding.bottomNavigationView.selectedItemId = R.id.nav_home
            super.onBackPressed()
            finish()
        } else {
            binding.bottomNavigationView.selectedItemId = R.id.nav_home
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 1970-01-01
      • 2022-08-11
      • 1970-01-01
      • 1970-01-01
      • 2020-03-06
      相关资源
      最近更新 更多