菜鸟写第一篇csdn博文,仅仅是因为自己遇到的问题百度而不得解,本着探索精神自己尝试后得到解决,感觉不错,分享出来给需要的朋友。
问题其实很简单,但是绕了好久。。。
目前在学习安卓,在一个项目中要用到search view组件。我想要的效果是:
1、顶部工具栏的搜索按钮点击后,在工具栏下方出现搜索栏。
2、这个搜索栏需要有关闭按钮,使得搜索栏可以从界面上消失。
3、当需要搜索时点击顶部工具栏按钮再出现。
最终实现布局如下:
图1:点击搜索按钮前:
图2:点击搜索按钮后:
图3:点击搜索栏右侧的关闭按钮后,恢复到图1。
很简单也很合理的要求,但是在实现的时候遇到个问题困扰了很久:searchview的两个方法:setIconifiedByDefault 和 setIconified。
searchview在布局中可以设置默认的形式,如下,iconified是指图标化。
<span style="font-size:18px;">android:iconifiedByDefault="true"</span>当iconifiedByDefault属性被设置为true时(java代码使用setIconifiedByDefault (true)设置),搜索栏的默认表现为一个单一的搜索图标,当点击这个图标后,才会展开显示完整的搜索图标、搜索输入框、关闭X按钮。如下:
图3:图标化搜索栏(收起状态)
图4:点击图标,展开搜索栏
为了达到我的目标,我希望默认为展开状态。所以,我将该值设置为false,也就是默认为非图标化。
但问题来了,设置iconifiedByDefault为false后,组件运行效果为:
图5:设置iconifiedByDefault为false后的组件表现
现象1:放大镜图标不在搜索框内,不如图4那样好看。
现象2:搜索内容为空时,搜索栏右侧的关闭按钮不显示
现象3:搜索内容不为空时,显示关闭按钮,但点击关闭按钮后清空文本,关闭按钮消失,无法关闭或收起搜索栏为图标化状态。
现象4:在现象2、3中,无法响应搜索栏关闭事件OnCloseListener()
显然,以上4点完全不满足我的要求(我要求关闭按钮时刻显示),而且我觉得也十分不合理。。。在排除了我的代码问题后,又百度没有发现有人遇到和我这样的情况。。。
好在刚学会了看android源码,抱着试一试的态度查看了setIconifiedByDefault 的源码,如下:
<span style="font-size:18px;"> public void setIconifiedByDefault(boolean iconified) { if (mIconifiedByDefault == iconified) return; mIconifiedByDefault = iconified; updateViewsVisibility(iconified); updateQueryHint(); }</span>跟踪updateViewsVisibility,如下:
<span style="font-size:18px;"> private void updateViewsVisibility(final boolean collapsed) { mIconified = collapsed; // Visibility of views that are visible when collapsed final int visCollapsed = collapsed ? VISIBLE : GONE; // Is there text in the query final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); mSearchButton.setVisibility(visCollapsed); updateSubmitButton(hasText); mSearchEditFrame.setVisibility(collapsed ? GONE : VISIBLE); mSearchHintIcon.setVisibility(mIconifiedByDefault ? GONE : VISIBLE); updateCloseButton(); updateVoiceButton(!hasText); updateSubmitArea(); }</span>我的关注点在关闭按钮,于是继续跟踪:updateCloseButton
<span style="font-size:18px;"> private void updateCloseButton() { final boolean hasText = !TextUtils.isEmpty(mQueryTextView.getText()); // Should we show the close button? It is not shown if there's no focus, // field is not iconified by default and there is no text in it. final boolean showClose = hasText || (mIconifiedByDefault && !mExpandedInActionView); mCloseButton.setVisibility(showClose ? VISIBLE : GONE); mCloseButton.getDrawable().setState(hasText ? ENABLED_STATE_SET : EMPTY_STATE_SET); }</span>关键来了。注释翻译为:
如果搜索框没有焦点,或者未被设置为【默认图标化】或搜索框内无文本时,不显示关闭按钮!
从代码和注释里可以知道,关闭按钮只在有搜索文本或者被【默认图标化(iconifiedByDefault为true)】且展开后才显示。
难道就不能默认展开,同时又允许关闭按钮一直显示吗?
我找到了另外一个类似的方法:setIconified (这个属性只可以用Java代码实现,而不是布局属性),该方法的说明文档如下:
<span style="font-size:18px;">Open Declaration void android.widget.SearchView.setIconified(boolean iconify) Iconifies or expands the SearchView. Any query text is cleared when iconified. This is a temporary state and does not override the default iconified state set by setIconifiedByDefault(boolean). If the default state is iconified, then a false here will only be valid until the user closes the field. And if the default state is expanded, then a true here will only clear the text field and not close it. Parameters: iconify a true value will collapse the SearchView to an icon, while a false will expand it.</span>
若默认图标化,setIconified(false)在用户关闭搜索栏之前有效【注意翻译be valid until closed】
若默认非图标化,也就是默认展开,setIconified(true)只会清空文本而不关闭搜索栏
搞懂后,我的解决方案就很简单了:
<span style="font-size:18px;">svSearch.setIconifiedByDefault(true); svSearch.setIconified(false);</span>也就是,默认图标化(这样才能一直显示关闭按钮),然后展开。成功。
问题其实很简单,但是被英文的表达方式搞得有点绕。至于默认非图标化时,现象1怎么解决我就不深究了,能达到目的就好~~
在API14,SearchView有onActionViewCollapsed和onActionViewExpanded方法来控制搜索栏的展开与关闭,经过试验仍然不能有效解决我的问题。
好了就到这了。第一篇菜鸟文章,希望对大家有用~~~欢迎指正。