Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Android上打开抽屉布局时编辑导航菜单项标题_Android_Navigationview_Android Navigationview - Fatal编程技术网

如何在Android上打开抽屉布局时编辑导航菜单项标题

如何在Android上打开抽屉布局时编辑导航菜单项标题,android,navigationview,android-navigationview,Android,Navigationview,Android Navigationview,在Android上,当在抽屉布局中创建导航视图时,可以通过1)获取主活动中菜单项的句柄来修改单个菜单项的标题: // Get a handle for the navigation view. NavigationView navigationView = findViewById(R.id.navigationview); // Get handles for the navigation menu items. final Menu navigationMenu = navigationV

在Android上,当在
抽屉布局中创建
导航视图
时,可以通过1)获取主活动中
菜单项的句柄来修改单个
菜单项的标题

// 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);
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);
            }
        }
    });
但是,一旦抽屉打开,尝试更改在不同线程上运行的主活动部分的一个菜单项的标题将导致以下错误,从而使应用程序崩溃:

W/System.err: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
例如,试图从
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);
    }
}

问题是如何更新菜单项,例如,当导航抽屉打开且需要更新菜单项的事件在另一个线程上运行时,在其中一个标题中有一个递增的计数器。

正如@MikeM所建议的那样,问题的解决方案是使用
Activity.runOnUiThread()
从创建导航的同一线程更新导航。具体地说,下面的代码适合我

// 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);
        });
    }
}

理解这个问题的关键是导航视图是由UI线程创建的。事后看来,这似乎很明显,但错误消息并没有具体说明这一点,而这一行为最初让我相信,有一些专用的
DrawerLayout
线程只能通过
DrawerLayout
侦听器访问。

你到底怎么样“正在尝试更改主活动中某个菜单项的标题”?方法是运行
onDrawerStateChanged()
下列出的相同命令。例如,
navigationThirdMenuItem.setTitle(getString(R.string.title)+“-”+计数器)
我们需要更多的上下文。异常消息意味着您正在从一个单独的线程调用它;例如,从一个
异步任务
、一个
计时器
,等等。它是作为
WebViewClient.shouldInterceptRequest()
的一部分从活套线程调用的。使用
活动#rununuithread()
方法。