[英]SearchView in ActionBar — problems with the *Up* button
我在ListView
的ActionBar
中使用SearchView
。 可以觸摸放大鏡, 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" />
注意圖標和android:showAsAction
。 我相信,當SearchView
被展開時,默認情況下會出現向上按鈕(按向上我的意思是<
加上圖標 - 使用官方導航中的藍圖和后退和向上看到右圖)。 似乎默認處理程序實現只是折疊擴展的SearchView
(返回圖標狀態)。
在調試時,我發現當使用Up時,使用空文本觸發onQueryTextChange()
。 (我相信這不是Android 4.2.2的情況,因為它在操作系統更新之前按原樣運行。)這就是為什么列表項的過濾也被重置的原因 - 請參閱下面的onQueryTextChange()
。 我希望SearchView
折疊,過濾器文本顯示為操作欄中的副標題。
到目前為止,我與SearchView
相關的代碼如下所示:
@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;
}
重新啟動的加載程序調用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;
}
我想檢測在調用onQueryTextChange()
之前按下Up的情況。 這樣(比方說)我可以設置一個標志並通過清空的SearchView
內容阻止mCurFilter
分配。 此外,當再次展開搜索圖標時,我想在mCurFilter
之前從mCurFilter
初始化擴展的SearchView
的文本(即展開的視圖是使用過濾器文本預設的)。 怎么做?
更新: SearchView
的早期實現有......
@Override
public void onActionViewCollapsed() {
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
現在,它包含......
@Override
public void onActionViewCollapsed() {
setQuery("", false);
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
你知道將查詢設置為空字符串的原因是什么? 我應該用舊代碼覆蓋新的實現嗎? 或者,還有更好的方法?
我寫了一個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>
在SearchView
的源代碼中,它清楚地表明他們將文本更改為""
:
@Override
public void onActionViewCollapsed() {
setQuery("", false);
clearFocus();
updateViewsVisibility(true);
mQueryTextView.setImeOptions(mCollapsedImeOptions);
mExpandedInActionView = false;
}
/**
* {@inheritDoc}
*/
@Override
public void onActionViewExpanded() {
if (mExpandedInActionView) return;
mExpandedInActionView = true;
mCollapsedImeOptions = mQueryTextView.getImeOptions();
mQueryTextView.setImeOptions(mCollapsedImeOptions | EditorInfo.IME_FLAG_NO_FULLSCREEN);
mQueryTextView.setText("");
setIconified(false);
}
如果您有問題,請告訴我。
我不確定我是否理解你的問題,但你可以檢測到點擊的時間是這樣的:
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
doSOmething();
return true;
}
return super.onOptionsItemSelected(item);
}
如果您攔截向上點擊,您可以在這里做任何你想要的事情。 返回true將消耗該事件,並且應該阻止任何默認操作發生。 通過這種方式,您可以執行任何您想要的向上按鈕,同時消耗向上事件以防止清除過濾器。
在我找到解決方案之前,我有點掙扎。
像這樣聲明你的menuItem,檢查showAsAction屬性,只鍵入ifRoom,如果設置collapseActionView,小部件將折疊並顯示操作欄上的后退按鈕
<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>
像往常一樣設置SearchView,記得添加setIconifiedByDefault這將使圖標以圖標的形式啟動
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()));
在您的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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.