【问题标题】:How to handle ActionBar's icons visibility when using SearchView使用 SearchView 时如何处理 ActionBar 的图标可见性
【发布时间】:2017-06-15 22:33:48
【问题描述】:

嗯,我想要的是:

  • 使用除“searchSettings”之外的所有项目初始化 ActionBar;
  • 点击搜索图标时,会出现searchSettings,其余图标消失;
  • 当关闭搜索EditText(按下设备的返回按钮或ActionBar的返回按钮)时,ActionBar恢复到原来的状态(所有图标都出现了,除了“searchSettings”)。

我的实际代码如下:

(我导入了android.support.v7.widget.SearchView 而不是android.widget.SearchView。当我使用android.widget.SearchView 时,这工作正常,但其他事情却不行)

private MenuItem searchIteam, searchSettings;
private SearchView searchView;

@Override
public boolean onCreateOptionsMenu(final Menu menu) {

    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.menu_main, menuMain);
    searchItem = menu.findItem(R.id.search);
    searchSettings = menu.findItem(R.id.action_searchSettings);
    searchView = (SearchView)MenuItemCompat.getActionView(item);
    searchSettings.setVisible(false); // hide searchSettings Item when Menu is created

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            (...)

            return false;
        }
    });

    // Detect SearchView icon clicks
    searchView.setOnSearchClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setItemsVisibility(menuMain, item, false);
            searchSettings.setVisible(true);
        }
    });
    // Detect SearchView close
    searchView.setOnCloseListener(new SearchView.OnCloseListener() {
        @Override
        public boolean onClose() {
            supportInvalidateOptionsMenu(); //shouldn't this reload the Action Bar as it was when onCreate?
            return true;
        }
    });

    return super.onCreateOptionsMenu(menu);

}

private void setItemsVisibility(Menu menu, MenuItem exception, boolean visible) {
    for (int i=0; i<menu.size(); ++i) {
        MenuItem item = menu.getItem(i);
        if (item != exception) item.setVisible(visible);
    }
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    if (id == android.R.id.home) {
        onBackPressed();
    }

    return super.onOptionsItemSelected(item);
}

@Override
public void onBackPressed() {
    supportInvalidadeOptionsMenu();
    super.onBackPressed();
}

此代码不起作用,当我第一次按“返回”时,它只会关闭搜索的 EditText,并且图标不会改变。如果我再次按下返回,活动会升级,但我可以看到图标开始(当我第一次按下“返回”时应该得到)在活动关闭前一段时间......

--- 编辑---

目前,如果我点击 Search ActionBar Icon,然后开始反复按“返回按钮”,会发生以下情况:

  • 第一次按下:键盘隐藏,但搜索EditText仍然打开;
  • 第二次按下:搜索结束(搜索EditText关闭并显示正常活动的内容);
  • 第三次按下:活动关闭。

然后,出于测试目的,我这样做了:

boolean pressed1, pressed2, pressed3;

searchView.setOnSearchClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            pressed1 = false;
            pressed2 = false;
            pressed3 = false;
            setItemsVisibility(menuMain, item, false);
            searchSettings.setVisible(true);
        }
    });

@Override
public void onBackPressed() {
    if (!pressed1) {
        pressed1 = true;
    }
    else if(!pressed2) {
        pressed2 = true;
    }
    else if(!pressed3) {
        pressed3 = true;
        supportInvalidateOptionsMenu();
    }
    else {
        super.onBackPressed();
    }
}

现在,发生的事情是:

  • 第一次按下:键盘隐藏,但搜索EditText仍然打开;
  • 第二次按下:搜索结束(搜索EditText关闭并显示正常活动的内容);
  • 第三次按下:没有任何反应;
  • 第四次按下:没有任何反应;
  • 第 5 次按下:ActionBar 按我的意愿重新加载;
  • 第6次按下:活动结束;

--- 编辑 2 ---

那我改成这样了:

@Override
public void onBackPressed() {
    if (!pressed1) {
        pressed1 = true;
        onBackPressed();
    }
    else if(!pressed2){
        pressed2 = true;
        onBackPressed();
    }
    else if(!pressed3){
        pressed3 = true;
        supportInvalidateOptionsMenu();
    }
    else {
        super.onBackPressed();
    }
}

现在发生的事情是:

  • 第一次按下:键盘隐藏,但搜索EditText仍然打开;
  • 第二次按下:搜索结束(搜索EditText关闭并显示正常活动的内容);
  • 第三次按下:ActionBar 按我的意愿重新加载;
  • 第四次按下:活动结束;

--- 编辑 3 ---(解决方案)---

我猜setOnSearchClickListenersetOnCloseListener 方法来自android.widget.SearchView... 因为我已经导入了android.support.v7.widget.SearchView,所以我将它们更改为:

MenuItemCompat.setOnActionExpandListener(searchItem,
            new MenuItemCompat.OnActionExpandListener() {
                @Override
                public boolean onMenuItemActionExpand(MenuItem menuItem) {
                    setItemsVisibility(menu, searchItem, false);
                    return true;
                }
                @Override
                public boolean onMenuItemActionCollapse(MenuItem menuItem) {
                    supportInvalidateOptionsMenu();
                    return true;
                }
            });

现在它工作得很好(:

【问题讨论】:

    标签: android searchview android-actionbar-compat


    【解决方案1】:

    我希望我说的对:第一次按 BACK 时,键盘会被隐藏。第二次按 BACK 时,应用程序退出。

    如果是这种情况,那么一切正常。因为这是 super.onBackPressed() 应该做的。如果显示,它将尝试隐藏键盘。如果没有,它将尝试去上一个活动。如果没有,它将退出应用程序。

    所以你需要做的是使用 onBackPressed() 方法。基本上,如果你确定你应该做什么,你不一定需要调用 super 方法。

    @Override
    public void onBackPressed() {
        if ( isSearching) {
            supportInvalidadeOptionsMenu();
            isSearching = false;     
        } else {
            super.onBackPressed();
        }
    }
    

    所以现在,当您从不按 BACK 按钮时,Activity 将检查是否正在搜索,并决定重新渲染操作栏或照常执行其正常操作。

    您需要添加一些逻辑来设置布尔标志 isSearching,例如,在单击 Search 时将 isSearching 设置为 true。

    我不确定 supportInvalidadeOptionsMenu() 是否会重置您的操作栏。无论如何,您可以改为调整每个视图的可见性。

    【讨论】:

    • 谢谢,克里斯!但我怕你听错了……我第一次按返回,键盘隐藏(好吧,这很正常),然后,我“第一次”按返回,搜索结束,但图标没有'不要重新加载......我已经尝试手动设置可见性而不是使用“supportInvalidateOptionsMenu()”,但它仍然不起作用;(。如果我使用你的方法,它会再次按下返回......它不会回到以前的活动,但也不会在第一次按下时工作 =/
    • 这是因为你调用了super.onBackPressed(),除非你按照我说的那样做,否则super方法会退出应用程序。当您在代码中按下后退按钮时,每次都会调用 super.onBackPressed(),这就是问题所在。
    • 您需要准确地告诉 onBackPressed() 方法应该发生什么。如果显示键盘,则使用 super.onBackPressed(),否则如果正在搜索,则重新渲染操作栏,不要调用 super.onBackPressed(),否则调用 super.onBackPressed()。在这种情况下,您应该转到以前的活动。
    • 做了这一切之后,我不知道为什么,仍然需要 2 次“Back Hits”才能重新加载 ActionBar =/
    • 请检查 onBackPressed() 方法中 if 语句的顺序,在返回之前您可能没有点击所需的子句。如果仍有问题,请发布您的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多