(使用 Android Studio 2021.1.1)
使用 Navigation Drawer Activity 創建一個新專案:
- 使用 Navigation Drawer Activity 模板創建了一個默認的 android 應用程式。
- 在專案中添加了一個設定片段來測驗
action_settings選單和配置選單項。 - 重寫
onOptionsItemSelected()以MainActivity.java處理設定選單,如下所示:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Bundle bundle = new Bundle();
switch (item.getItemId()) {
case R.id.action_settings:
Navigation
.findNavController(this, R.id.nav_host_fragment_content_main)
.navigate(R.id.nav_settings);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
測驗:
運行專案,抽屜選單作業正常并按預期打開片段。問題是,當您單擊溢位選單以打開設定片段時,它可以作業,但在打開主片段時抽屜選單不再起作用。


觀察:
經過一番測驗,我發現是依賴版本的原因,將其從2.4.1降級到2.3.5即可解決問題。
我的代碼有問題還是因為 API 更改?如何在不降級的情況下處理這個問題?
額外資訊:
在MainActivity'sonCreate()方法中,我添加了以下內容:
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow, R.id.nav_settings)
.setOpenableLayout(drawer)
.build();
app模塊的build.gradle:
plugins {
id 'com.android.application'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.myapplication"
minSdk 23
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
buildToolsVersion '32.0.0'
ndkVersion '23.1.7779620'
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.1'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1'
implementation 'androidx.navigation:navigation-fragment:2.4.1'
implementation 'androidx.navigation:navigation-ui:2.4.1'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
}
uj5u.com熱心網友回復:
tl/dr:您應該遵循將目標系結到選單項檔案并使用NavigationUI.onNavDestinationSelected()以獲得正確的行為:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
NavController navController = Navigation.findNavController(this,
R.id.nav_host_fragment_content_main);
// By calling onNavDestinationSelected(), you always get the right behavior
return NavigationUI.onNavDestinationSelected(item, navController)
|| super.onOptionsItemSelected(item);
}
為什么
根據添加導航抽屜指南,導航 2.4 使用與您的每個元素關聯的多個后退堆疊:NavigationView
從Navigation 2.4.0-alpha01開始,當您使用 setupWithNavController 時,每個選單項的狀態都會被保存和恢復。
這意味著“主”螢屏有一個與之關聯的后臺堆疊,當您點擊該圖示時會恢復該后臺堆疊,對于圖庫、幻燈片和設定也是如此。這就是為該專案保存狀態的方式。
這意味著每次點擊抽屜中的專案不只是導航到該螢屏,而是在與該專案關聯的整個后臺堆疊中交換 - 您從第一個螢屏導航到的所有內容。
因此,當您呼叫 時Navigation.findNavController(this, R.id.nav_host_fragment_content_main).navigate(R.id.nav_settings);,您所做的事情與選擇抽屜中的“設定”項不同 - 您只是將“設定”螢屏添加到“主”螢屏的后臺堆疊。這就是為什么點擊主頁圖示不會做任何事情的原因 - 你已經在“主頁”螢屏的后臺堆疊上。
您真正想要做的是交換到與 nav_settings 專案關聯的完全獨立的后退堆疊。這會將 nav_settings 后臺堆疊與主頁后臺堆疊分開,從而確保點擊主頁圖示將您帶回主螢屏的后臺堆疊。
這正是NavigationUI.onNavDestinationSelected()API 所做的(因為這正是setupWithNavControllerAPI 使用的),因此您可以直接在onOptionsItemSelected().
但是,如果您想手動呼叫navigate()(順便說一句,這意味著您沒有獲得使用時默認獲得的交叉淡入淡出影片onNavDestinationSelected),您可以通過應用 NavOptions 以編程方式將保存狀態標志添加到您的導航呼叫:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Bundle bundle =new Bundle();
switch (item.getItemId()) {
case R.id.action_settings:
{
// Manually build the NavOptions that manually do
// what NavigationUI.onNavDestinationSelected does for you
NavOptions navOptions = new NavOptions.Builder()
.setPopUpTo(R.id.nav_home, false, true)
.setRestoreState(true)
.build();
NavController navController = Navigation.findNavController(this,
R.id.nav_host_fragment_content_main);
navController.navigate(R.id.nav_settings, navOptions);
return true;
}
default:
return super.onOptionsItemSelected(item);
}
}
Note that the setupWithNavController API relies on the nested graph of the current destination to determine which item is selected - the expectation is that all destinations in the 'Home' tab are part of the 'Home' navigation graph. So because you've swapped to the nav_settings, setupWithNavController assumes you've swapped to that back stack. Since you haven't actually done that, that's why your selected item gets out of sync with which back stack you are on.
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/446612.html
