[英]How to edit a navigation menu item title while the DrawerLayout is open on Android
On Android, when a NavigationView
is created in a DrawerLayout
, the title of individual MenuItems
can be modified by 1) getting handles for the MenuItems
in the main activity: 在Android上,当在
DrawerLayout
创建NavigationView
时,可以通过以下方式修改单个MenuItems
的标题:1)在主活动中获取MenuItems
句柄:
// Get a handle for the navigation view.
NavigationView navigationView = findViewById(R.id.navigationview);
// Get handles for the navigation menu items.
final Menu navigationMenu = navigationView.getMenu();
final MenuItem navigationFirstMenuItem = navigationMenu.getItem(0);
final MenuItem navigationSecondMenuItem = navigationMenu.getItem(1);
final MenuItem navigationThirdMenuItem = navigationMenu.getItem(2);
and 2) modifying the titles of the menu items when the drawer is opened using a DrawerListener
: 和2)使用
DrawerListener
打开抽屉时修改菜单项的标题:
// The drawer listener is used to update the navigation menu.
drawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() {
@Override
public void onDrawerSlide(@NonNull View drawerView, float slideOffset) {
}
@Override
public void onDrawerOpened(@NonNull View drawerView) {
}
@Override
public void onDrawerClosed(@NonNull View drawerView) {
}
@Override
public void onDrawerStateChanged(int newState) {
if ((newState == DrawerLayout.STATE_SETTLING) || (newState == DrawerLayout.STATE_DRAGGING)) { // A drawer is opening or closing.
// Update the title of the menu items.
navigationFirstMenuItem.setTitle(getString(R.string.newString));
navigationSecondMenuItem.setEnabled(false);
navigationThirdMenuItem.setTitle(getString(R.string.title) + " - " + counterInt);
}
}
});
However, once the drawer is open, attempting to change the title of one of the menu items from a part of the main activity running on a different thread results in the following error, which crashes the app: 但是,一旦打开抽屉,尝试从运行在不同线程上的主要活动的一部分更改菜单项之一的标题,则会导致以下错误,从而使应用程序崩溃:
W/System.err: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
For example, this error can be produced by attempting to update a navigation menu item from inside WebViewClient.shouldInterceptRequest()
as follows: 例如,尝试从
WebViewClient.shouldInterceptRequest()
内部更新导航菜单项,可能会产生此错误,如下所示:
// Get a handle for the WebView.
WebView webView = findViewById(R.id.webview);
// Set a WebViewClient.
webView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url){
navigationFirstMenuItem.setTitle(getString(R.string.newString));
navigationSecondMenuItem.setEnabled(false);
navigationThirdMenuItem.setTitle(getString(R.string.title) + " - " + counterInt);
}
}
The question is how to update a menu item, for example, having a counter that increments in one of the titles, while the navigation drawer is open and the event that needs to update the menu item is running on a different thread. 问题是如何更新菜单项,例如,在打开导航抽屉且需要更新菜单项的事件在不同线程上运行的同时,其中一个计数器在标题之一中递增。
As suggested by @MikeM., the solution to the problem is to use Activity.runOnUiThread()
to update the navigation from the same thread that created it. 如@MikeM。所建议,解决该问题的方法是使用
Activity.runOnUiThread()
从创建它的同一线程更新导航。 Specifically, the following code works for me. 具体来说,以下代码对我有用。
// Get a handle for the activity. This is used to update the menu item titles while the navigation menu is open.
Activity activity = this;
// Get a handle for the WebView.
WebView webView = findViewById(R.id.webview);
// Set a WebViewClient.
webView.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url){
// Update the menu items' titles from the UI thread.
activity.runOnUiThread(() -> {
navigationFirstMenuItem.setTitle(getString(R.string.newString));
navigationSecondMenuItem.setEnabled(false);
navigationThirdMenuItem.setTitle(getString(R.string.title) + " - " + counterInt);
});
}
}
The key to understanding this problem is that the navigation view is created by the UI thread. 理解此问题的关键是导航视图是由UI线程创建的。 That seems obvious in hindsight, but the error message doesn't specifically state that, and the behavior had initially led me to believe that there was some dedicated
DrawerLayout
thread that could only be accessed via the DrawerLayout
listener. 在事后看来,这似乎很明显,但是错误消息并未具体说明这一点,并且这种行为最初使我相信有一些专用的
DrawerLayout
线程只能通过DrawerLayout
侦听器进行访问。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.