我终于在一个新项目中采用了导航体系结构组件,并且我已经遇到了一些文档似乎无法解决的问题。
在活动中设置了ActionBar菜单后,当我导航到另一个片段然后尝试使用收到的ActionBar菜单时
java.lang.IllegalArgumentException: Navigation action/destination X cannot be found from the current destination
看来,我还必须将所有可能的目标位置的动作添加到所有其他目标位置,这似乎有些过分,但这不可能。对于我找不到的问题,必须有解决方案。
我打算打开对MainActivity进行扩展的应用程序,然后对fragment元素中的MainFragment进行扩展。 MainActivity仍应在ActionBar中处理顶级导航。绝对没有必要在每个片段中重复菜单单击操作并为应用程序所有其他区域定义目标。
MainActivity
class MainActivity : AppCompatActivity() {
private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration
private var menu: Menu? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val controller by lazy { findNavController(R.id.fragment_container) }
navController = controller
val appBarConfig by lazy { AppBarConfiguration(navController.graph) }
appBarConfiguration = appBarConfig
setSupportActionBar(toolbar)
setupActionBarWithNavController(navController, appBarConfiguration)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.appbar_menu, menu)
this.menu = menu
return true
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
var direction: NavDirections? = null
when(item.itemId) {
R.id.action_messages -> {
direction = MainFragmentDirections.actionMainFragmentToMessagesFragment()
}
R.id.action_menu -> {
direction = MainFragmentDirections.actionMainFragmentToMessagesFragment()
}
else -> super.onOptionsItemSelected(item)
}
if (direction != null) navController.navigate(direction)
return true
}
override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
activity_main
<?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/card_id_test"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
android:background="@color/colorPrimary"
android:elevation="4dp"
android:clipToPadding="false"
app:menu="@menu/appbar_menu"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:titleTextColor="@color/white" />
<fragment
android:id="@+id/fragment_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"
app:layout_constraintTop_toBottomOf="@+id/toolbar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
MainFragment
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
private val binding get() = _binding!!
private var mActivity : MainActivity? = null
private var mView: View? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentMainBinding.inflate(inflater, container, false)
mView = binding.root
mActivity = (activity as MainActivity)
return mView
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btn_dashboard.setOnClickListener {
findNavController().navigate(
MainFragmentDirections.actionMainFragmentToDashboardFragment())
}
}
}
fragment_main
<?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/content_test"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="Main Fragment"
android:textSize="24dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/btn_dashboard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="Dashboard" />
</androidx.constraintlayout.widget.ConstraintLayout>
DashboardFragment
class DashboardFragment : Fragment() {
private var _binding: FragmentDashboardBinding? = null
private val binding get() = _binding!!
private var mActivity : MainActivity? = null
private var mView: View? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
super.onCreateView(inflater, container, savedInstanceState)
_binding = FragmentDashboardBinding.inflate(inflater, container, false)
mView = binding.root
mActivity = (activity as MainActivity)
return mView
}
}
fragment_dashboard
<?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/content_test"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:text="Dashboard Fragment"
android:textSize="24dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
nav_graph
<?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"
android:id="@+id/nav_graph"
app:startDestination="@id/mainFragment">
<fragment
android:id="@+id/mainFragment"
android:name="com.example.appbarnavigation.MainFragment"
android:label="Main" >
<action
android:id="@+id/action_mainFragment_to_messagesFragment"
app:destination="@id/action_messages" />
<action
android:id="@+id/action_mainFragment_to_menuFragment"
app:destination="@id/action_menu" />
<action
android:id="@+id/action_mainFragment_to_dashboardFragment"
app:destination="@id/dashboardFragment" />
</fragment>
<fragment
android:id="@+id/action_messages"
android:name="com.example.appbarnavigation.MessagesFragment"
android:label="Messages" />
<fragment
android:id="@+id/action_menu"
android:name="com.example.appbarnavigation.MenuFragment"
android:label="Menu" />
<fragment
android:id="@+id/dashboardFragment"
android:name="com.example.appbarnavigation.DashboardFragment"
android:label="Dashboard" />
</navigation>
appbar_menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_messages"
android:orderInCategory="1"
android:title="Messages"
android:icon="@drawable/ic_message"
app:showAsAction="always"/>
<item
android:id="@+id/action_menu"
android:orderInCategory="2"
android:title="Menu"
android:icon="@drawable/ic_menu"
app:showAsAction="always"/>
</menu>
答案 0 :(得分:0)
此问题已通过定义和使用全局操作解决。
<?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"
android:id="@+id/nav_graph"
app:startDestination="@id/mainFragment">
<fragment
android:id="@+id/mainFragment"
android:name="com.example.appbarnavigation.MainFragment"
android:label="Main" >
<action
android:id="@+id/action_mainFragment_to_dashboardFragment"
app:destination="@id/dashboardFragment" />
</fragment>
<fragment
android:id="@+id/action_messages"
android:name="com.example.appbarnavigation.MessagesFragment"
android:label="Messages" />
<fragment
android:id="@+id/action_menu"
android:name="com.example.appbarnavigation.MenuFragment"
android:label="Menu" />
<fragment
android:id="@+id/dashboardFragment"
android:name="com.example.appbarnavigation.DashboardFragment"
android:label="Dashboard" />
<action android:id="@+id/action_global_action_messages" app:destination="@id/action_messages" />
<action android:id="@+id/action_global_action_menu" app:destination="@id/action_menu" />
</navigation>
和MainActivity
override fun onOptionsItemSelected(item: MenuItem) = when(item.itemId) {
R.id.action_messages -> {
navController.navigate(R.id.action_global_action_messages)
true
}
R.id.action_menu -> {
navController.navigate(R.id.action_global_action_menu)
true
}
// This is used for menu buttons or anything not explicitly defined here
else -> {
super.onOptionsItemSelected(item)
}
}