Android: 如何让设置菜单与 NavigationUI 一起显示?
Android: How do I get the Settings menu to appear with NavigationUI?
我正在尝试遵循这个:https://developer.android.com/guide/navigation/navigation-ui along with a review of https://codelabs.developers.google.com/codelabs/android-navigation/#8(尽管第二个 link 在 Kotlin 中,我在 Javascript 中编码)在 [=32] 中实现一个应用程序=] 左侧有导航抽屉,右上角有一个设置按钮(首选项)。
我正在为抽屉和设置中的每个选项使用带片段的 NavigationUI。
我的问题是我的设置片段没有出现。我想我快到了,但是尽管查看了几篇文章和问题还是无法让它发挥作用。
此代码允许我从导航抽屉切换片段:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
//NavigationUI.setupWithNavController(toolbar, navController, mAppBarConfiguration);
}
如果我在最后两行切换注释代码(所以我执行最后一行而不是倒数第二行)以匹配指南,则片段切换失败。
我处理设置菜单的代码是:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.onNavDestinationSelected(item, navController)
|| super.onOptionsItemSelected(item);
/*
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
// TODO: Do something to accept settings
View contextView = findViewById(R.id.nav_host_fragment); // Apparently any layout can be used
Snackbar.make(contextView, "Settings", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
//changeFragment(new SettingsFragment());
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.nav_host_fragment, new SettingsFragment(), "nh")
.addToBackStack("nh")
.commit();
return true;
}
return super.onOptionsItemSelected(item);
*/
}
活动部分与上面的指南相符,正在调用(通过设置断点证明)但什么也没做。
如果我选择将其切换为注释掉的代码,那么我的设置片段会出现但会覆盖当前片段。我从另一个答案了解到,这是因为我使用两种不同的方法来处理片段可见性,这是有道理的,也是我试图让 NavigationUI 框架处理我的设置片段的原因。
我觉得治愈一定很简单,但是看了一遍又一遍的指南(很多答案都无法解决)
您有不同的选择:
只需在您的导航图中定义 SettingsFragment
:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!--Your fragments-->
<!--Settings fragment-->
<fragment
android:id="@+id/settingsFragment"
android:name=".SettingsFragment"/>
</navigation>
然后用以下方法扩充你的菜单:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
在您的菜单中使用图表中使用的相同 ID:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/settingsFragment"
.../>
</menu>
最后覆盖onOptionsItemSelected
方法:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.onNavDestinationSelected(item, navController)
|| super.onOptionsItemSelected(item);
}
你也可以定义一个Global Action.
<?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">
<!--Global action-->
<action android:id="@+id/action_global_open_settings_fragment"
app:destination="@id/settingsFragment"/>
</navigation>
然后在您的代码中导航到目的地只需使用:
Navigation.findNavController(view).navigate(R.id.action_global_open_settings_fragment);
我不确定我是否理解你的问题。但这是我的解决方案,希望对您有所帮助。
这是我的导航图
这是准则。如您所见,我在 SettingsFragment:
中有一个动作
<fragment
android:id="@+id/settingsFragment"
android:name="packageName.SettingsFragment"
android:label="Settings Fragment">
<action
android:id="@+id/actionSettingsToPassword"
app:destination="@id/passwordDialogFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit" />
这是我的 bottomNavigationMenu XML:
<item
android:id="@+id/settingsFragment"
android:icon="@drawable/ic_settings"
android:title="Settings" />
请记住,导航和菜单中的 ID 应该相同。 正如您在代码中看到的,“设置片段”的 ID 是一样的:
android:id="@+id/settingsFragment"
我不知道你是否知道如何在你的资源中添加preferences.xml。当然我也写了:
Right Click on "res" New > Android Resource Directory
在“资源类型”字段中,取件 XML。现在你将在“res”下有 xml 文件夹。再次:
Right Click on "xml" New > XML Recourse File
现在,这是我的“preferences.xml”:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Weather Location">
<SwitchPreference
android:defaultValue="true"
android:disableDependentsState="true"
android:key="USE_DEVICE_LOCATION"
android:summary="Allow The App To Get Your Location"
android:title="Use Device Location" />
<EditTextPreference
android:defaultValue="Tehran"
android:dependency="USE_DEVICE_LOCATION"
android:key="CUSTOM_LOCATION"
android:summary="The Location For Which The Weather Is Displayed"
android:title="Location" />
</PreferenceCategory>
<PreferenceCategory android:title="Units">
<ListPreference
android:defaultValue="METRIC"
android:entries="@array/unitSystemEntries"
android:key="UNIT_SYSTEM"
android:summary="%s"
android:title="Unit System"
android:entryValues="@array/unitSystemValues"/>
</PreferenceCategory>
</PreferenceScreen>
然后创建一个“Kotlin”或“Java”class 并将 XML 设置为您的 class 像这样 (取决于哪个你写的语言):
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as? AppCompatActivity)?.supportActionBar?.title = "Settings"
(activity as? AppCompatActivity)?.supportActionBar?.subtitle = null
}
}
这是我的申请 Class:
class ForecastApplication : Application(){
override fun onCreate() {
super.onCreate()
PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
}
}
并在您应用程序的清单中,在应用程序标签内,定义您已经创建的应用程序 class。
android:name=".ForecastApplication"
希望这就是您所需要的。
我正在尝试遵循这个:https://developer.android.com/guide/navigation/navigation-ui along with a review of https://codelabs.developers.google.com/codelabs/android-navigation/#8(尽管第二个 link 在 Kotlin 中,我在 Javascript 中编码)在 [=32] 中实现一个应用程序=] 左侧有导航抽屉,右上角有一个设置按钮(首选项)。
我正在为抽屉和设置中的每个选项使用带片段的 NavigationUI。
我的问题是我的设置片段没有出现。我想我快到了,但是尽管查看了几篇文章和问题还是无法让它发挥作用。
此代码允许我从导航抽屉切换片段:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
mAppBarConfiguration = new AppBarConfiguration.Builder(
R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
.setDrawerLayout(drawer)
.build();
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
NavigationUI.setupWithNavController(navigationView, navController);
//NavigationUI.setupWithNavController(toolbar, navController, mAppBarConfiguration);
}
如果我在最后两行切换注释代码(所以我执行最后一行而不是倒数第二行)以匹配指南,则片段切换失败。
我处理设置菜单的代码是:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.onNavDestinationSelected(item, navController)
|| super.onOptionsItemSelected(item);
/*
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
// TODO: Do something to accept settings
View contextView = findViewById(R.id.nav_host_fragment); // Apparently any layout can be used
Snackbar.make(contextView, "Settings", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
//changeFragment(new SettingsFragment());
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.nav_host_fragment, new SettingsFragment(), "nh")
.addToBackStack("nh")
.commit();
return true;
}
return super.onOptionsItemSelected(item);
*/
}
活动部分与上面的指南相符,正在调用(通过设置断点证明)但什么也没做。
如果我选择将其切换为注释掉的代码,那么我的设置片段会出现但会覆盖当前片段。我从另一个答案了解到,这是因为我使用两种不同的方法来处理片段可见性,这是有道理的,也是我试图让 NavigationUI 框架处理我的设置片段的原因。
我觉得治愈一定很简单,但是看了一遍又一遍的指南(很多答案都无法解决)
您有不同的选择:
只需在您的导航图中定义 SettingsFragment
:
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!--Your fragments-->
<!--Settings fragment-->
<fragment
android:id="@+id/settingsFragment"
android:name=".SettingsFragment"/>
</navigation>
然后用以下方法扩充你的菜单:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
在您的菜单中使用图表中使用的相同 ID:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/settingsFragment"
.../>
</menu>
最后覆盖onOptionsItemSelected
方法:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
return NavigationUI.onNavDestinationSelected(item, navController)
|| super.onOptionsItemSelected(item);
}
你也可以定义一个Global Action.
<?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">
<!--Global action-->
<action android:id="@+id/action_global_open_settings_fragment"
app:destination="@id/settingsFragment"/>
</navigation>
然后在您的代码中导航到目的地只需使用:
Navigation.findNavController(view).navigate(R.id.action_global_open_settings_fragment);
我不确定我是否理解你的问题。但这是我的解决方案,希望对您有所帮助。
这是我的导航图
这是准则。如您所见,我在 SettingsFragment:
中有一个动作 <fragment
android:id="@+id/settingsFragment"
android:name="packageName.SettingsFragment"
android:label="Settings Fragment">
<action
android:id="@+id/actionSettingsToPassword"
app:destination="@id/passwordDialogFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit" />
这是我的 bottomNavigationMenu XML:
<item
android:id="@+id/settingsFragment"
android:icon="@drawable/ic_settings"
android:title="Settings" />
请记住,导航和菜单中的 ID 应该相同。 正如您在代码中看到的,“设置片段”的 ID 是一样的:
android:id="@+id/settingsFragment"
我不知道你是否知道如何在你的资源中添加preferences.xml。当然我也写了:
Right Click on "res" New > Android Resource Directory
在“资源类型”字段中,取件 XML。现在你将在“res”下有 xml 文件夹。再次:
Right Click on "xml" New > XML Recourse File
现在,这是我的“preferences.xml”:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="Weather Location">
<SwitchPreference
android:defaultValue="true"
android:disableDependentsState="true"
android:key="USE_DEVICE_LOCATION"
android:summary="Allow The App To Get Your Location"
android:title="Use Device Location" />
<EditTextPreference
android:defaultValue="Tehran"
android:dependency="USE_DEVICE_LOCATION"
android:key="CUSTOM_LOCATION"
android:summary="The Location For Which The Weather Is Displayed"
android:title="Location" />
</PreferenceCategory>
<PreferenceCategory android:title="Units">
<ListPreference
android:defaultValue="METRIC"
android:entries="@array/unitSystemEntries"
android:key="UNIT_SYSTEM"
android:summary="%s"
android:title="Unit System"
android:entryValues="@array/unitSystemValues"/>
</PreferenceCategory>
</PreferenceScreen>
然后创建一个“Kotlin”或“Java”class 并将 XML 设置为您的 class 像这样 (取决于哪个你写的语言):
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.preferences)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
(activity as? AppCompatActivity)?.supportActionBar?.title = "Settings"
(activity as? AppCompatActivity)?.supportActionBar?.subtitle = null
}
}
这是我的申请 Class:
class ForecastApplication : Application(){
override fun onCreate() {
super.onCreate()
PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
}
}
并在您应用程序的清单中,在应用程序标签内,定义您已经创建的应用程序 class。
android:name=".ForecastApplication"
希望这就是您所需要的。