Android ActionBar中的SearchView--“向上”按钮出现问题
我正在使用Android ActionBar中的SearchView--“向上”按钮出现问题,android,android-listview,Android,Android Listview,我正在使用列表视图的操作栏中的搜索视图。可以触摸放大镜,SearchView显示其编辑框,用户可以输入文本以过滤列表内容。它几乎起作用了。但是,当用户按下向上按钮时,SearchView折叠回图标,小部件内的文本被清除,过滤被重置。其效果(在我的例子中)是,只有当SearchView没有图标化时,才能过滤列表。想要的行为是在SearchView折叠后保留筛选文本 注意:Android 4.3可能会改变这种行为。在4.2.2中,它按预期运行。见下面的观察结果 详细信息:更具体地说,菜单包含以下项目
列表视图
的操作栏
中的搜索视图
。可以触摸放大镜,SearchView
显示其编辑框,用户可以输入文本以过滤列表内容。它几乎起作用了。但是,当用户按下向上按钮时,SearchView
折叠回图标,小部件内的文本被清除,过滤被重置。其效果(在我的例子中)是,只有当SearchView
没有图标化时,才能过滤列表。想要的行为是在SearchView
折叠后保留筛选文本
注意:Android 4.3可能会改变这种行为。在4.2.2中,它按预期运行。见下面的观察结果
详细信息:更具体地说,菜单包含以下项目:
<item android:id="@+id/menu_search_customers"
android:title="@string/menu_search_text"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="ifRoom|collapseActionView"
android:actionViewClass="android.widget.SearchView" />
重新启动的加载程序调用onCreateLoader
。请注意,mCurFilter
用于构建SQL查询:
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
String[] projection = { CustomerTable._ID,
CustomerTable.CODE,
CustomerTable.NAME,
CustomerTable.STREET,
CustomerTable.TOWN };
String selection = null; // init
String[] selectionArgs = null; // init
if ( ! mCurFilter.isEmpty()) {
selection = CustomerTable.NAME + " like ?";
selectionArgs = new String[]{ "%" + mCurFilter +"%" };
}
CursorLoader cursorLoader = new CursorLoader(this,
DemoContentProvider.CUSTOMERS_CONTENT_URI, projection,
selection, selectionArgs,
orderInfo);
return cursorLoader;
}
现在,它包含
@Override
public void onActionViewCollapsed() {
setQuery("", false);
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
您知道将查询设置为空字符串的原因吗?我应该用旧代码覆盖新的实现吗?或者有更好的方法吗?我不确定我是否理解您的问题,但您可以通过以下方式检测何时单击“向上”:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// MenuInflater adds the magnifying glass icon for the SearchView
// to the ActionBar as the always visible menu item.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.customers_menu, menu);
// Get the related SearchView widget.
SearchView sv = (SearchView) menu.findItem(R.id.menu_search_customers)
.getActionView();
// Get the changes immediately.
sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
// I am not sure whether the onQueryTextSubmit() is important
// for the purpose.
@Override
public boolean onQueryTextSubmit(String query) {
getActionBar().setSubtitle(mCurFilter);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
// The newText is stored into a member variable that
// is used when the new CursorLoader is created.
mCurFilter = newText;
getActionBar().setSubtitle(mCurFilter);
getLoaderManager().restartLoader(0, null,
CustomersOverviewActivity.this);
return true;
}
});
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
doSOmething();
return true;
}
return super.onOptionsItemSelected(item);
}
如果你拦截向上点击,你大概可以在这里做任何你想做的事情。返回true将消耗事件,这将阻止任何默认操作的发生。通过这种方式,您可以执行任何您希望向上按钮执行的操作,同时使用向上事件来防止清除过滤器。我编写了一个
StatefulSearchView
,其中保留了以下文本:
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
public class StatefulSearchView extends SearchView implements android.view.View.OnLayoutChangeListener, OnQueryTextListener,android.widget.SearchView.OnCloseListener{
private boolean mSaveText=true;
private OnQueryTextListener mQueryListener;
private String mQuery;
private OnCloseListener mCloseListener;
private boolean fromIconify = true;
public StatefulSearchView(Context context, AttributeSet attrs) {
super(context, attrs);
addOnLayoutChangeListener(this);
super.setOnCloseListener(this);
}
public StatefulSearchView(Context context) {
super(context);
// TODO Auto-generated constructor stub
addOnLayoutChangeListener(this);
super.setOnCloseListener(this);
}
public void setSaveSearchTextState(boolean save){
this.mSaveText = save;
this.setSaveEnabled(mSaveText);
}
public void setOnStatefulQueryTextListener(OnQueryTextListener listener) {
mQueryListener = listener;
super.setOnQueryTextListener(this);
}
@Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
if(super.isIconfiedByDefault() || !super.isIconified() && !TextUtils.isEmpty(mQuery) && mSaveText){
setSavedText(mQuery);
}
Log.i("onLayoutChanged()",""+mQuery);
}
@Override
public void setIconified(boolean iconify) {
mQuery = getQuery().toString();
Log.i("setIconified()",""+mQuery);
super.setOnCloseListener(null);
super.setIconified(iconify);
super.setIconified(iconify);
super.setOnCloseListener(this);
fromIconify = true;
}
@Override
public void setOnCloseListener(OnCloseListener listener) {
mCloseListener = listener;
super.setOnCloseListener(this);
}
@Override
protected Parcelable onSaveInstanceState() {
Parcelable state = super.onSaveInstanceState();
return new SearchQueryState(state, mQuery, mSaveText);
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
SearchQueryState sqs = (SearchQueryState)state;
super.onRestoreInstanceState(sqs.getSuperState());
mQuery = sqs.getSavedQuery();
mSaveText = sqs.getSaveText();
}
@Override
public boolean onQueryTextChange(String arg0) {
mQuery = arg0;
return mQueryListener.onQueryTextChange(mQuery);
}
@Override
public boolean onQueryTextSubmit(String arg0) {
// TODO Auto-generated method stub
return mQueryListener.onQueryTextSubmit(arg0);
}
private TextView getTextView(){
int searchTextViewId = getContext().getResources().getIdentifier("android:id/search_src_text", null, null);
return (TextView) this.findViewById(searchTextViewId);
}
private void setSavedText(String s){
super.setOnQueryTextListener(null);
Log.i("setSavedText()",""+s);
TextView t = getTextView();
t.setText(s);
if(!TextUtils.isEmpty(s))
((EditText)t).setSelection(s.length());
super.setOnQueryTextListener(mQueryListener);
}
private class SearchQueryState extends BaseSavedState{
private boolean mSaveText;
private String mQueryText;
public SearchQueryState(Parcel arg0) {
super(arg0);
this.mQueryText = arg0.readString();
this.mSaveText = arg0.readInt() == 1;
}
public SearchQueryState(Parcelable superState, String queryText, boolean saveText) {
super(superState);
this.mQueryText = queryText;
this.mSaveText = saveText;
}
public boolean getSaveText(){
return this.mSaveText;
}
public String getSavedQuery(){
return mQueryText;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// TODO Auto-generated method stub
super.writeToParcel(dest, flags);
dest.writeString(mQueryText);
dest.writeInt(mSaveText? 1: 0);
}
}
@Override
public boolean onClose() {
Log.i("onClose()", "Is from setIconified(): "+fromIconify);
if(!fromIconify){
mQuery = null;
fromIconify = false;
}
return mCloseListener == null ? false : mCloseListener.onClose();
}
}
在示范活动中:
public class MainActivity extends Activity{
private StatefulSearchView mSearchView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getActionBar().setHomeButtonEnabled(true);
}
@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
if(item.getItemId()==android.R.id.home) {
mSearchView.setIconified(true);
return true;
}
return super.onMenuItemSelected(featureId, item);
}
@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);
MenuItem item = menu.findItem(R.id.action_search);
mSearchView =(StatefulSearchView)item.getActionView();
mSearchView.setSaveSearchTextState(true);
mSearchView.setOnStatefulQueryTextListener(new OnQueryTextListener(){
@Override
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}});
return true;
}
在菜单xml中:
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_search"
android:orderInCategory="100"
android:showAsAction="always"
android:actionViewClass="com.nikola.despotoski.saveablesearchview.StatefulSearchView"
android:title="@string/action_settings"/>
</menu>
如果您有问题,请告诉我。在找到解决方案之前,我一直在努力解决这个问题 像这样声明菜单项,检查showAsAction属性,仅键入ifRoom,如果设置collapseActionView,小部件将折叠并显示actionbar上的后退按钮
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/search"
android:actionViewClass="android.widget.SearchView"
android:icon="@drawable/ic_2_action_search"
android:showAsAction="ifRoom"
android:title="@null"/>
</menu>
在QueryListener上,您可以这样处理搜索的结束,这里使用onActionViewCollapse()将ViewSearch向后折叠
@Override
public boolean onQueryTextSubmit(String query) {
makeSearchRequest(SEARCH_TYPE_KEYWORD, query);
searchView.setQuery("", false);
searchView.clearFocus();
searchView.onActionViewCollapsed();
buttonClearSearchResults.setVisibility(View.VISIBLE);
return false;
}
有趣的是,你开发的Android版本是什么?我想要这种效果,但无法实现,当我折叠searchview时,我的搜索没有清除…:/最新版本为4.3。我只是在学习,尝试构建演示应用程序。与较旧的Android版本兼容是以后计划的任务。很高兴得到您的确认,因为在我看来,当我使用4.2时,它很早就起作用了。但我不确定代码从那时起是否没有太多变化。是的,我相信这实际上是早期android中的一个bug。您是否查看过onActionViewCollapsed()以处理搜索结果的清除?(早期android中的一个bug意味着这个方法是无用的)请,公式化是答案。我会让它暂时不被接受,可能会更新问题并提供奖励以吸引注意。关于您的最新更新,
Stateful SearchView
的目标是防止onQueryListener仅在操作视图展开/折叠时被调用时才被空字符串调用。您可以注意到,我删除了您传递的侦听器,并在稍后再次读取它。慢慢看我的密码。同时,我会改进它,消除混乱。我已经更新了问题。请看一看。如果我正确理解了您的代码,这可能是了解SearchView
何时展开的方法。无论如何,我发现这个“技巧”只是作为保持向后兼容性的建议()。SearchView
中没有更好的方法吗?谢谢,我的+1提醒我,SearchView
仍然与案例中的菜单相关。你好,尼古拉。谢谢你的密码。我目前没有Android设备要测试。我还不太了解StatefulSearchView
的详细信息。无论如何,onActionViewCollapsed
不包含上一版本中的第一个setQuery(“,false)
。这似乎是痕迹…我现在看得更清楚了。因此,核心是覆盖onActionViewCollapsed
和onActionViewExpanded
方法。super.onActionViewXxxx()代码>执行默认代码并添加派生代码。mSaveText
是我在更新中提到的布尔标志。可能,我会选择在onQueryTextChange
中使用中的标志,而不是更改侦听器。是的,长话短说。@pepr我已经编辑了代码。它工作完美无瑕。当按下up项时,我尝试了一个场景。请尝试一下,让我知道。代码对我很有价值。谢谢无论如何,如果这个问题不能以与SearchView
更好地集成的方式解决,我将研究更多相关的内容。
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/search"
android:actionViewClass="android.widget.SearchView"
android:icon="@drawable/ic_2_action_search"
android:showAsAction="ifRoom"
android:title="@null"/>
</menu>
SearchManager searchManager = (SearchManager)getSystemService(Context.SEARCH_SERVICE);
searchView = (SearchView) menu.findItem(R.id.search).getActionView();
searchView.setIconifiedByDefault(true);
searchView.setOnQueryTextListener(new SearchViewOnQueryListener());
searchView.setOnCloseListener(new SearchViewOnCloseListener());
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
@Override
public boolean onQueryTextSubmit(String query) {
makeSearchRequest(SEARCH_TYPE_KEYWORD, query);
searchView.setQuery("", false);
searchView.clearFocus();
searchView.onActionViewCollapsed();
buttonClearSearchResults.setVisibility(View.VISIBLE);
return false;
}