7

の で を使用してSearchViewActionBarますListView。虫めがねに触れると、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。展開すると、デフォルトでUpボタンが表示されると思いますSearchViewUpとは、アイコンとアイコンを意味します-公式のNavigation with Back and Up<のブルーブックの右の画像を参照してください)。デフォルトのハンドラーの実装は、展開されたものを折りたたむだけのようです(アイコンの状態に戻ります)。SearchView

右の画像の *Up* ボタンの例

デバッグ中に、 UponQueryTextChange()を使用すると が空のテキストで起動されることがわかりました。(Android 4.2.2 には当てはまらないと思います。OS の更新前は希望どおりに機能していたからです。)これが、リスト項目のフィルタリングもリセットされる理由です。以下を参照してください。折りたたまれ、フィルタ テキストがアクション バーにサブタイトルとして表示されます。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()mCurFilterSearchViewSearchViewmCurFilter

更新: hadの以前の実装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;
}

クエリを空の文字列に設定する理由を知っていますか? 新しい実装を古いコードでオーバーライドする必要がありますか? それとももっと良い方法がありますか?

4

3 に答える 3

7

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

問題がある場合はお知らせください。

于 2013-08-15T02:01:30.563 に答える
1

解決策が見つかるまで、これに少し苦労します。

このように 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 では、検索の最後をそのように処理する場所です。ここでは、ViewSearch を折りたたむ onActionViewCollapse() を使用します。

@Override
public boolean onQueryTextSubmit(String query) {
            makeSearchRequest(SEARCH_TYPE_KEYWORD, query);
        searchView.setQuery("", false);
        searchView.clearFocus();
        searchView.onActionViewCollapsed();
        buttonClearSearchResults.setVisibility(View.VISIBLE);
        return false;
    }
于 2014-04-25T18:41:47.433 に答える
1

あなたの問題を理解しているかどうかはわかりませんが、次のようにクリックされたときに検出できます。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            doSOmething();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

アップクリックをインターセプトすると、おそらくここでやりたいことを何でもできます。true を返すとイベントが消費され、デフォルト アクションが実行されなくなります。このようにして、フィルターのクリアを防ぐためにアップ イベントを消費しながら、アップ ボタンで実行したいことを実行できます。

于 2013-08-15T00:44:37.187 に答える