Android中使用Fragments进行搜索

168

是否有教程或例子可以展示如何使用 Fragment 实现标准的Android搜索界面?换句话说,是否可以在一个 Fragment 中使用 SearchManager 实现标准搜索?


4
我很高兴我们最终得到了各种正确答案和解决方法! :) - Alex Lockwood
有人可以给我这个问题的答案吗?我在这里卡住了https://dev59.com/_mPVa4cB1Zd3GeqP9ttB - Rookie
1
我正在使用这种技术,在将SearchView添加到操作栏后,保持在片段内:https://dev59.com/H2w05IYBdhLWcg3w72M0#6939735。我的应用程序还没有完成,但希望它能正常工作。 - span
我已经成功地在Android Search Interface(SearchView in Action Bar)中使用自定义建议和结果显示,在片段中实现了搜索。每个片段从网络动态加载自己的建议(缓存在本地数据库中)。这需要很多工作,但它非常有效。如果您想让我解释得更详细,请添加评论.. :-) - Vinay S Shenoy
继续前进。这可能对其他人有用。谢谢。 - Blackbelt
显示剩余2条评论
12个回答

94

简而言之,你不能这样做。创建一个在Fragment中的搜索界面不可能是由于以下几个原因:

  1. 当创建一个可搜索的界面时,必须在Android清单中指定一个默认的“可搜索活动”。正如您所知,没有父Activity就无法存在Fragment,因此这种分离是不可能的。

  2. 如果您已经确定了第一点,则我认为您提出这个问题是希望有一些神奇的“黑科技”来完成工作。然而,文档说明如下:

    当用户在搜索对话框或小部件中执行搜索时,系统会启动您的可搜索活动并将搜索查询作为ACTION_SEARCH意图传递给它。您的可搜索活动从意图的QUERY额外检索查询,然后搜索数据并显示结果。

    负责提供搜索结果的底层内部系统需要一个Activity而不是Fragment。因此,实现一个完全独立于Activity的搜索界面是不可能的,因为这需要对底层系统本身进行更改。如果您不相信,请查看SearchableInfo类的源代码 :)。

话虽如此,似乎实现您所描述的类似功能并不是太困难。例如,您可以考虑实现可搜索活动,使其接受android.intent.action.SEARCH意图,并将搜索查询传递给您的Fragment。例如,考虑以下可搜索活动:

public class SearchableActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {
          String query = intent.getStringExtra(SearchManager.QUERY);
          doMySearch(query);
        }
    }

    /**
     * Performs a search and passes the results to the container
     * Activity that holds your Fragments.
     */
    public void doMySearch(String query) {
        // TODO: implement this
    }
}
当发起一个搜索请求时,系统将启动您的可搜索活动,在执行查询后,将结果传递给某个容器活动(基于您对doMySearch的实现)。然后,容器活动将这些结果传递给包含的可搜索Fragment,其中结果将被显示。该实现需要比您原本期望的更多的工作,但我相信有办法使它更加模块化,而且似乎这可能是您能做到的最好的。
附言:如果您使用此方法,则可能需要特别注意添加/删除回退堆栈中的活动。有关如何执行此操作的更多信息,请参阅此帖子
另外,您也可以完全忘记标准搜索界面,并像Raghav在下面的帖子中所述一样,在一个Fragment中实现简单的搜索。

@Alex,使用片段实现标准的Android搜索界面是完全可能的。但是需要大量的工作... :-) - Vinay S Shenoy
@VinaySShenoy 是的,我的意思是你需要重新实现整个“SearchManager”以适用于“Fragment”,对吧?(或者类似这样的东西) - Alex Lockwood
1
为了提供搜索结果,我实现了类似于您建议的东西,将意图传递给活动,如果它可见,则将其传递给正确的片段。最困难的部分是在片段加载时使用正确的数据重新填充建议表,以便我处理显示建议以及处理搜索提交和单击建议。但是,我现在已经有了一个很好的框架,可以用于未来的应用程序.. :-) - Vinay S Shenoy
我发现这是一个更好的答案:https://dev59.com/H2w05IYBdhLWcg3w72M0#6939735。这将允许在片段内进行“搜索”。确实,它不是由Google提供的官方搜索机制,但它完全可以正常工作。 - Kyle Falconer

79

以下是使用片段搜索的示例。希望能帮到你,这就是你要找的东西:

public class LoaderCursor extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        FragmentManager fm = getFragmentManager();

        // Create the list fragment and add it as our sole content.
        if (fm.findFragmentById(android.R.id.content) == null) {
            CursorLoaderListFragment list = new CursorLoaderListFragment();
            fm.beginTransaction().add(android.R.id.content, list).commit();
        }
    }

    public static class CursorLoaderListFragment extends ListFragment
            implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {

        // This is the Adapter being used to display the list's data.
        SimpleCursorAdapter mAdapter;

        // If non-null, this is the current filter the user has provided.
        String mCurFilter;

        @Override public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);

            // Give some text to display if there is no data.  In a real
            // application this would come from a resource.
            setEmptyText("No phone numbers");

            // We have a menu item to show in action bar.
            setHasOptionsMenu(true);

            // Create an empty adapter we will use to display the loaded data.
            mAdapter = new SimpleCursorAdapter(getActivity(),
                    android.R.layout.simple_list_item_2, null,
                    new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
                    new int[] { android.R.id.text1, android.R.id.text2 }, 0);
            setListAdapter(mAdapter);

            // Start out with a progress indicator.
            setListShown(false);

            // Prepare the loader.  Either re-connect with an existing one,
            // or start a new one.
            getLoaderManager().initLoader(0, null, this);
        }

        @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            // Place an action bar item for searching.
            MenuItem item = menu.add("Search");
            item.setIcon(android.R.drawable.ic_menu_search);
            item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
            SearchView sv = new SearchView(getActivity());
            sv.setOnQueryTextListener(this);
            item.setActionView(sv);
        }

        public boolean onQueryTextChange(String newText) {
            // Called when the action bar search text has changed.  Update
            // the search filter, and restart the loader to do a new query
            // with this filter.
            mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
            getLoaderManager().restartLoader(0, null, this);
            return true;
        }

        @Override public boolean onQueryTextSubmit(String query) {
            // Don't care about this.
            return true;
        }

        @Override public void onListItemClick(ListView l, View v, int position, long id) {
            // Insert desired behavior here.
            Log.i("FragmentComplexList", "Item clicked: " + id);
        }

        // These are the Contacts rows that we will retrieve.
        static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
            Contacts._ID,
            Contacts.DISPLAY_NAME,
            Contacts.CONTACT_STATUS,
            Contacts.CONTACT_PRESENCE,
            Contacts.PHOTO_ID,
            Contacts.LOOKUP_KEY,
        };

        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            // This is called when a new Loader needs to be created.  This
            // sample only has one Loader, so we don't care about the ID.
            // First, pick the base URI to use depending on whether we are
            // currently filtering.
            Uri baseUri;
            if (mCurFilter != null) {
                baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                        Uri.encode(mCurFilter));
            } else {
                baseUri = Contacts.CONTENT_URI;
            }

            // Now create and return a CursorLoader that will take care of
            // creating a Cursor for the data being displayed.
            String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
                    + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
                    + Contacts.DISPLAY_NAME + " != '' ))";
            return new CursorLoader(getActivity(), baseUri,
                    CONTACTS_SUMMARY_PROJECTION, select, null,
                    Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
        }

        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
            // Swap the new cursor in.  (The framework will take care of closing the
            // old cursor once we return.)
            mAdapter.swapCursor(data);

            // The list should now be shown.
            if (isResumed()) {
                setListShown(true);
            } else {
                setListShownNoAnimation(true);
            }
        }

        public void onLoaderReset(Loader<Cursor> loader) {
            // This is called when the last Cursor provided to onLoadFinished()
            // above is about to be closed.  We need to make sure we are no
            // longer using it.
            mAdapter.swapCursor(null);
        }
    }
}

OP 要求“标准搜索界面”,但这确实在 Fragment 中实现了简单的“搜索”,所以我不会抱怨。恭喜!:P - Alex Lockwood
31
下次您可能希望引用您的来源 - Adrian Monk
请参阅开发者网站上的“创建搜索界面”(http://developer.android.com/guide/topics/search/search-dialog.html)。 OP问是否可以创建一个“可搜索片段”,并与文档中描述的标准Android搜索一起使用。 - Alex Lockwood
一些陷阱:1-使用自定义搜索图标无效。2-SearchView需要一些管理代码,例如禁用内容、处理返回等。 - AlikElzin-kilaka
在我的情况下,onQueryTextChange 方法没有被调用。 - Shajeel Afzal

58

使用标准ActionBar SearchView ActionView API可以很容易地在片段中进行搜索。这也适用于Android 2.1(API level 7),使用AppCompat支持类v7。

在您的片段中:

@Override
public void onCreateOptionsMenu (Menu menu, MenuInflater inflater){
    inflater.inflate(R.menu.search, menu);
    MenuItem item = menu.findItem(R.id.action_search);
    SearchView sv = new SearchView(((YourActivity) getActivity()).getSupportActionBar().getThemedContext());
    MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
    MenuItemCompat.setActionView(item, sv);
    sv.setOnQueryTextListener(new OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            System.out.println("search query submit");
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            System.out.println("tap");
            return false;
        }
    });
}
在您的菜单 XML 中。
<item
    android:id="@+id/action_search"
    android:icon="@drawable/ic_action_search"
    android:title="Search Waste Items"
    android:showAsAction="ifRoom|collapseActionView"
    nz.govt.app:actionViewClass="android.support.v7.widget.SearchView"
    nz.govt.app:showAsAction="ifRoom|collapseActionView" />

1
读了被采纳的答案,我失去了希望...其他的答案都很复杂,但是我读了你的答案!!!太简单了!就是这样...非常感谢你。 - MBH
那个工作得很好,谢谢!你有关于“最近查询建议”实现的任何建议吗? - hornet2319
2
我认为我们必须在onActivityCreated中添加setHasOptionsMenu(true)。正如@MBH所指出的那样。 - Raymond Lukanta
2
@GowthamanM 如果你能的话,只需使用MenuItem.SHOW_AS_ACTION....,因为AppCompat在后期API中已被弃用。 - David
1
嘿 @GowthamanM,使用如下: item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItem.SHOW_AS_ACTION_IF_ROOM); item.setActionView(searchView); - Rod Lima
显示剩余6条评论

17

使用 AppCompat 支持类 v7。为了以一种简单的方式使其正常工作,只需在@David的解决方案中添加一些内容,然后按照@Rookie的解决方案进行操作,这是我的片段代码:

MyFragment:

public class MyFragment extends Fragment implements SearchView.OnQueryTextListener {

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // What i have added is this
        setHasOptionsMenu(true);
    }

    @Override
    public void onCreateOptionsMenu (Menu menu, MenuInflater inflater) {

        //inflater.inflate(R.menu.main, menu); // removed to not double the menu items
        MenuItem item = menu.findItem(R.id.action_search);
        SearchView sv = new SearchView(((MainActivity) getActivity()).getSupportActionBar().getThemedContext());
        MenuItemCompat.setShowAsAction(item, MenuItemCompat.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW | MenuItemCompat.SHOW_AS_ACTION_IF_ROOM);
        MenuItemCompat.setActionView(item, sv);
        sv.setOnQueryTextListener(this);
        sv.setIconifiedByDefault(false);
        sv.setOnSearchClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Utils.LogDebug("Clicked: ");
            }
        });

        MenuItemCompat.setOnActionExpandListener(item, new MenuItemCompat.OnActionExpandListener() {
            @Override
            public boolean onMenuItemActionCollapse(MenuItem item) {
                // Do something when collapsed
                Utils.LogDebug("Closed: ");
                return true;  // Return true to collapse action view
            }

            @Override
            public boolean onMenuItemActionExpand(MenuItem item) {
                // Do something when expanded
                Utils.LogDebug("Openeed: ");
                return true;  // Return true to expand action view
            }
        });

        super.onCreateOptionsMenu(menu,inflater);
    }

    @Override
    public boolean onQueryTextSubmit(String query) {
        Utils.LogDebug("Submitted: "+query);
        return true;
    }

    @Override
    public boolean onQueryTextChange(String newText) {
        Utils.LogDebug("Changed: "+newText);
        return false;
    }
}
我添加了 onActivityCreated ,因为如果不调用setHasOptionsMenu(true);,系统将不知道这个片段需要与菜单进行交互。
然后我删除了 inflater.inflate(R.menu.main, menu); 这行,因为它会使菜单项翻倍,因为 Activity 填充了一个菜单,而 Fragment 又填充了另一个菜单。
感谢 @David 和 @Rookie。

7
使用Fragments时,仍需要使用Activity来控制和分配Fragments。这个Activity可以像以前一样具有搜索功能。
我最近从基于“普通”Activity的应用程序切换到基于Fragment的应用程序,对我来说搜索功能仍然有效。
你尝试过这个功能,但没有成功吗?如果是,请在问题中提供更多详细信息。
编辑:
如果您想要特定于片段的搜索,请让所有的Fragments扩展一个名为MyFragment的接口,并具有一个startSearch方法。然后,让您的ActivitystartSearch方法调用当前片段的startSearch方法。

要求是Android搜索绑定到特定的片段,而不是活动。所以,我还没有尝试过。 - Blackbelt
我还没有尝试过,但这听起来正是我要找的东西。我有一个带有片段的导航抽屉,每个片段都包含不相关的搜索功能。我不想完全绕过Android搜索系统,所以我需要像这样的东西。 - Bassinator

5
我认为我已经做到了:您实际上可以使用片段并将搜索图标添加到操作栏中,以便在片段内进行搜索。窍门是使用操作栏、操作视图、监听器、加载器和适配器,当然还有一些工作来找到@Alex Lockwood描述的内容,并将搜索传递给片段。尽管它完全绕过了Android平台的搜索机制(但可以通过一些工作完成),它仍然可以很好地工作。它不会像活动一样按预期对意图作出反应,但它可以让用户在片段内搜索。
以下是代码:

SearchInFragmentActivity

package com.sof.test.searchfragment;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.View;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.ActionBar.TabListener;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.sof.test.searchfragment.SearchFragment;
import com.sof.test.R;


public class SearchInFragmentActivity extends SherlockFragmentActivity implements TabListener {

    private SearchFragment tab1 = new SearchFragment();
    private SearchFragment tab2 = new SearchFragment();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView( R.layout.search_in_fragments );

        getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        createTab( R.string.tab1, R.drawable.ic_menu_search );
        createTab( R.string.tab2, R.drawable.ic_menu_search );
        getSupportActionBar().setSelectedNavigationItem( 0 );
        invalidateOptionsMenu();
    }

    private void createTab(int tabNameResId, int tabIconResId) {
        ActionBar.Tab tab = getSupportActionBar().newTab();
        tab.setText( tabNameResId );
        tab.setTabListener(this);
        getSupportActionBar().addTab(tab);
    }// met

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        if( ft == null ) {
            return;
        }//if
        View fragmentSlot = findViewById( R.id.fragment );
        Fragment newFragment = null;
        if( fragmentSlot != null ) {
            newFragment = (tab.getPosition() == 0) ? tab1 : tab2;
            ft.replace(R.id.fragment, newFragment );
            ft.setTransition( FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        }//if
    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

}//class

搜索Fragment类(我在上面的活动中使用了2个实例)。

package com.sof.test.searchfragment;


import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.SearchView;
import android.widget.TextView;

import com.sof.test.R;
import com.actionbarsherlock.app.SherlockListFragment;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;

public class SearchFragment extends SherlockListFragment {

    private StringLoader loader = null;
    private StringAdapter adapter = null;
    private List<String> listData = new ArrayList<String>();
    private String query;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        createListData();

        loader = new StringLoader( getActivity(), this );
        adapter = new StringAdapter(listData);
        setListAdapter(adapter);

        getLoaderManager().initLoader(0, null,  new LoaderCallBacks() );
        loader.forceLoad();
        setHasOptionsMenu( true );
        return view;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater ) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate( R.menu.menu_search, menu);
        System.out.println( "inflating menu");

        final SearchView searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
        final SearchView.OnQueryTextListener queryTextListener = new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextChange(String newText) {
                showFilteredItems( newText );
                return true;
            }

            @Override
            public boolean onQueryTextSubmit(String query) {
                return true;
            }
        };

        searchView.setOnQueryTextListener(queryTextListener);

        return;
    }//met

    private void showFilteredItems( String query ) {
        this.query = query;
        loader.onContentChanged();
    }

    private void createListData() {
        for( int i = 0; i < 100 ; i ++ ) {
          listData.add( "String "+ i ); 
        }
    }

    public List<String> getData() {
        List<String> listFilteredData = new ArrayList<String>();
        for( String string : listData ) {
            if( query == null || string.contains( query ) ) {
                listFilteredData.add( string );
            }
        }
        return listFilteredData;
    }//met

    private class LoaderCallBacks implements LoaderCallbacks< List<String>> {
        @Override
        public void onLoadFinished(Loader<List<String>> loader,
                List<String> listData) {
            adapter.setListData( listData );
        }// met

        @Override
        public void onLoaderReset(Loader<List<String>> listData) {
            adapter.setListData( new ArrayList<String>() );
        }// met

        @Override
        public Loader<List<String>> onCreateLoader(int arg0,
                Bundle arg1) {
            return loader;
        }// met
    }//class

    private class StringAdapter extends ArrayAdapter< String > {

        private List<String> listDataToDisplay = new ArrayList<String>();
        private LayoutInflater mInflater;

        public StringAdapter( List<String> listData ) {
            super( getActivity(), android.R.layout.simple_list_item_1, android.R.id.text1, listData );
            listDataToDisplay = listData;
            mInflater = (LayoutInflater)getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }//cons

        private void setListData( List<String> newListData ) {
            this.listDataToDisplay.clear();
            this.listDataToDisplay.addAll( newListData );
            notifyDataSetChanged();
        }//met

          /**
         * Populate new items in the list.
         */
        @Override public View getView(int position, View convertView, ViewGroup parent) {
            View view;

            if (convertView == null) {
                view = mInflater.inflate(android.R.layout.simple_list_item_1, parent, false);
            } else {
                view = convertView;
            }

            ((TextView)view.findViewById( android.R.id.text1)).setText( listDataToDisplay.get( position ) );

            return view;
        }
    }//inner class
}//class

class StringLoader extends AsyncTaskLoader<List<String>> {

    SearchFragment fragment = null;

    public StringLoader(Context context, SearchFragment fragment) {
        super(context);
        this.fragment = fragment;
    }// cons

    @Override
    public List<String> loadInBackground() {
        return fragment.getData();
    }// met
}// class

搜索片段菜单的xml文件位于res/menu/menu_search.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal" >
    <FrameLayout
        android:id="@+id/fragment"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="1" />
</LinearLayout>

而 XML 布局文件位于 res/layout/search_in_fragments.xml 中。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:baselineAligned="false"
    android:orientation="horizontal" >
    <FrameLayout
        android:id="@+id/fragment"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="1" />
</LinearLayout>

我还想指出,Jake Wharton决定不为他的ActionBarSherlock库实现SearchView,因为它太复杂了(在这里看到他的评论)。正如你所看到的(并且正如我在我的答案中描述的那样),Android的搜索实现一点也不简单...它深深地融入了底层系统,这使得即使是第三方库也很难编写(这说明了什么... Jake Wharton就像第三方库的Chuck Norris!:D)。 - Alex Lockwood
在这里查看SearchView.java源代码。 - Alex Lockwood
2
Alex,看起来Jake Wharton改变了主意:https://twitter.com/JakeWharton/status/221169921235755009 - Jose_GD
这两个 XML 文件是一样的吗? - Clocker
@Clocker,看起来是这样。老实说,经过两年我不能确定。 - Snicolas

5

使用ActionBarSearchView。您将能够处理搜索,而无需连接到Activity。只需将OnQueryTextListener设置到SearchView即可。

MenuItem item = menu.add("Search");
SearchView sv = new SearchView(getActionBar().getThemedContext());
item.setActionView(sv);
item.setIcon(R.drawable.ic_search);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW
        | MenuItem.SHOW_AS_ACTION_IF_ROOM);
sv.setOnQueryTextListener(new OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String query) {
        //...
        return false;
    }
    @Override
    public boolean onQueryTextChange(String newText) {
        //...
        return false;
    }
});

更多关于自定义搜索的详细信息,请参见文章。


3

其他的解决方案我不太喜欢,这个更容易。但这只是我的想法。我在等待你的意见。

public interface SearchImpl {
    public void searchQuery(String val);
}

片段


public class MyFragment extends Fragment implements SearchImpl {
    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_almanca, container, false);
        return view;
    }

    @Override
    public void searchQuery(String val) {
        Log.e("getted", val);
    }
}

活动

 @Override
public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.main, menu);

    SearchView searchView = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.action_search));

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            Log.e("setted", "" + query);
            try {
                MyFragment myFGM=new MyFragment();
                myFGM.searchQuery(query);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            return false;
        }
    });
    return super.onCreateOptionsMenu(menu);
}

1
在ViewPager中出现Fragment时,我可以通过在我不想要搜索栏的片段上阻止搜索按钮来实现。在activity内:
@Override
public boolean onSearchRequested() {

    if (mPager.getCurrentItem() == mAdapter.getPosition(FragmentType.VIDEO))
        return super.onSearchRequested();
    else
        return false;
}

如果没有物理搜索按钮,我会在片段中添加一个操作项,触发此代码:

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    if (item.getItemId() == R.id.search_item) {

        return getSherlockActivity().onSearchRequested();
    }
    return super.onOptionsItemSelected(item);
}

1
一个Fragment不能存在于Activity之外,也不能与android.intent.action.SEARCH或任何其他intent-filter相关联。

因此,如果不使用Activity来包装Fragment,你所要求的是不可能实现的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接