kotlin 导航组件设置标题崩溃
kotlin navigation components set title crash
我正在同时使用 navigation
组件和 bottomNavigationView
。当我多次来回切换选项卡时,出现崩溃消息:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:5361)
at android.view.ViewGroup.addView(ViewGroup.java:5190)
at android.view.ViewGroup.addView(ViewGroup.java:5162)
at androidx.appcompat.widget.Toolbar.addSystemView(Toolbar.java:1528)
at androidx.appcompat.widget.Toolbar.setTitle(Toolbar.java:777)
at com.atp.newarchitecture.activity.AppActivity.onCreate$lambda-0(AppActivity.kt:119)
密码是:
navController.addOnDestinationChangedListener { _,
destination,
argument ->
binding.toolbar.title = resources.getString(when (destination.id) {
R.id.fragmentId -> R.string.fragmentTitle
//... more ids
})
布局文件是:
<LinearLayout 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"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ToolBarTheme"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="?attr/homeAsUpIndicator" />
<TextView
android:id="@+id/selected_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/login_text_input_layout"
app:layout_constraintBottom_toBottomOf="@+id/toolbar"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1"
tools:text="@string/selected_count" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/alert_tip_root"
android:layout_width="0dp"
android:layout_height="@dimen/quadruple_margin"
android:layout_margin="@dimen/default_margin"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
android:theme="@style/BottomNavigationTheme"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_bar" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment_activity_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/bottom_navigation_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/nav_graph" />
<View
android:id="@+id/loading_background_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
我知道崩溃消息意味着一个视图应该只有 parent,但这里似乎没有 addView
。想知道是否每次 binding.root.title
分配调用 addView
?有什么帮助吗?谢谢!
编辑:
def nav_version = "2.3.5"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")
implementation("androidx.navigation:navigation-compose:2.4.0-beta02")
如 Navigation UI guide 中所述:
Caution: If you pass a Toolbar
as the argument to setSupportActionBar()
, the ActionBar
assumes complete ownership of that Toolbar
and you must not use any Toolbar APIs after that call.
在您调用 setSupportActionBar()
的所有情况下都是如此。这意味着直接调用任何 Toolbar
API,例如 setTitle
,将破坏该所有权契约并导致此类异常。
相反,您应该:
根本不要使用setSupportActionBar()
。您可以 connect a Toolbar to Navigation directly and upgrade to AppCompat 1.4.0 让片段通过 MenuHost
和 MenuProvider
API 将元素添加到工具栏。
如果使用setSupportActionBar()
,则需要通过ActionBar API设置标题。即,调用 supportActionBar!!.title = ...
按照 app bar guide 并在导航图 XML 文件中的每个目的地设置 android:label
(即 android:label="@string/fragmentTitle"
)。这将在当前目的地更改时自动更新标题(假设您已调用 NavigationUI
的适当 setup
方法)。这将完全消除使用侦听器的需要,从而允许您完全删除所有代码。
我正在同时使用 navigation
组件和 bottomNavigationView
。当我多次来回切换选项卡时,出现崩溃消息:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
at android.view.ViewGroup.addViewInner(ViewGroup.java:5361)
at android.view.ViewGroup.addView(ViewGroup.java:5190)
at android.view.ViewGroup.addView(ViewGroup.java:5162)
at androidx.appcompat.widget.Toolbar.addSystemView(Toolbar.java:1528)
at androidx.appcompat.widget.Toolbar.setTitle(Toolbar.java:777)
at com.atp.newarchitecture.activity.AppActivity.onCreate$lambda-0(AppActivity.kt:119)
密码是:
navController.addOnDestinationChangedListener { _,
destination,
argument ->
binding.toolbar.title = resources.getString(when (destination.id) {
R.id.fragmentId -> R.string.fragmentTitle
//... more ids
})
布局文件是:
<LinearLayout 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"
android:orientation="vertical">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:theme="@style/ToolBarTheme"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="?attr/homeAsUpIndicator" />
<TextView
android:id="@+id/selected_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/login_text_input_layout"
app:layout_constraintBottom_toBottomOf="@+id/toolbar"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1"
tools:text="@string/selected_count" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/alert_tip_root"
android:layout_width="0dp"
android:layout_height="@dimen/quadruple_margin"
android:layout_margin="@dimen/default_margin"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="0dp"
android:layout_marginEnd="0dp"
android:background="?android:attr/windowBackground"
android:theme="@style/BottomNavigationTheme"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/bottom_bar" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment_activity_main"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="@id/bottom_navigation_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/nav_graph" />
<View
android:id="@+id/loading_background_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
我知道崩溃消息意味着一个视图应该只有 parent,但这里似乎没有 addView
。想知道是否每次 binding.root.title
分配调用 addView
?有什么帮助吗?谢谢!
编辑:
def nav_version = "2.3.5"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
androidTestImplementation("androidx.navigation:navigation-testing:$nav_version")
implementation("androidx.navigation:navigation-compose:2.4.0-beta02")
如 Navigation UI guide 中所述:
Caution: If you pass a
Toolbar
as the argument tosetSupportActionBar()
, theActionBar
assumes complete ownership of thatToolbar
and you must not use any Toolbar APIs after that call.
在您调用 setSupportActionBar()
的所有情况下都是如此。这意味着直接调用任何 Toolbar
API,例如 setTitle
,将破坏该所有权契约并导致此类异常。
相反,您应该:
根本不要使用
setSupportActionBar()
。您可以 connect a Toolbar to Navigation directly and upgrade to AppCompat 1.4.0 让片段通过MenuHost
和MenuProvider
API 将元素添加到工具栏。如果使用
setSupportActionBar()
,则需要通过ActionBar API设置标题。即,调用supportActionBar!!.title = ...
按照 app bar guide 并在导航图 XML 文件中的每个目的地设置
android:label
(即android:label="@string/fragmentTitle"
)。这将在当前目的地更改时自动更新标题(假设您已调用NavigationUI
的适当setup
方法)。这将完全消除使用侦听器的需要,从而允许您完全删除所有代码。