MaterialDesign 之 SearchView 全面解锁

1、简述

SearchView是v7包中的一个兼容性控件,它能够单独使用,也能够配合menu+toolbar一块儿使用。本文将使用第二种方式,对SearchView进行探索。最后将经过代码实战,实现 “仿网易云音乐本地音乐搜索” 效果,带你全面解锁SearchView的UI定制及查询功能的实现。javascript

2、常规使用

*本文重点是SearchView,因此对Toolbar的使用及注意事项在本文中将不会有过多的体现,如需了解可自行百度或直接查看本Demo源码(源码在文末)。java

一、在menu的xml文件中配置

要跟menu一块儿使用,就必须在menu的xml文件中对其中的一个item进行actionViewClass属性配置,如:android

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> <item android:id="@+id/menu_search" android:orderInCategory="100" android:title="搜索" app:actionViewClass="android.support.v7.widget.SearchView" app:showAsAction="always" /> ... </menu>复制代码

这个item跟普通item的差异在于使用了app:actionViewClass属性(注意是app:开头的!!!),这里使用的是兼容性控件里的SearchView,因此取值"android.support.v7.widget.SearchView"。其中title的设置不会生效(通常设置了title的item,长按后会有弹出提示文字),这里去掉也无所谓。git

二、在onCreateOptionsMenu()中获得SearchView

咱们知道menu在建立时会回调Activity中的onCreateOptionsMenu(Menu menu)方法,经过该方法能够获得Menu对象,而SearchView是Menu中item的一个actionView,actionView能够经过MenuItemCompat获取,故,经过Menu对象能够获得SearchView。github

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_view, menu);
    MenuItem searchItem = menu.findItem(R.id.menu_search);
    //经过MenuItem获得SearchView
    mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    ...
    return super.onCreateOptionsMenu(menu);
}复制代码

到这里就能够看到效果了:数据库

三、对SearchView进行设置

默认展开搜索框

手淘的首页搜索框是默认展开的,使用SearchView能够作同样的效果。此外,SearchView有三种默认展开的设置,效果上有略微不一样,请结合注释与图片仔细观察。app

/*------------------ SearchView有三种默认展开搜索框的设置方式,区别以下: ------------------*/
//设置搜索框直接展开显示。左侧有放大镜(在搜索框中) 右侧有叉叉 能够关闭搜索框
mSearchView.setIconified(false);
//设置搜索框直接展开显示。左侧有放大镜(在搜索框外) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
mSearchView.setIconifiedByDefault(false);
//设置搜索框直接展开显示。左侧有无放大镜(在搜索框中) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
mSearchView.onActionViewExpanded();复制代码

按顺序效果依次以下:ionic

setIconified(false)

setIconifiedByDefault(false)

onActionViewExpanded()

SearchView的常规设置

//设置最大宽度
mSearchView.setMaxWidth(500);
//设置是否显示搜索框展开时的提交按钮
mSearchView.setSubmitButtonEnabled(true);
//设置输入框提示语
mSearchView.setQueryHint("hint");复制代码

比较容易,直接看下效果:ide

SearchView的事件监听

SearchView提供的事件监听仍是比较丰富的,通常经常使用的有打开搜索框按钮的点击事件、清空或关闭搜索框按钮的点击事件、搜索框文字变化事件等。布局

//搜索框展开时后面叉叉按钮的点击事件
mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
    @Override
    public boolean onClose() {
        Toast.makeText(getApplicationContext(), "Close", Toast.LENGTH_SHORT).show();
        return false;
    }
});
//搜索图标按钮(打开搜索框的按钮)的点击事件
mSearchView.setOnSearchClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(getApplicationContext(), "Open", Toast.LENGTH_SHORT).show();
    }
});
//搜索框文字变化监听
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String s) {
        Log.e("CSDN_LQR", "TextSubmit : " + s);
        return false;
    }

    @Override
    public boolean onQueryTextChange(String s) {
        Log.e("CSDN_LQR", "TextChange --> " + s);
        return false;
    }
});复制代码

这个也比较容易,直接看下效果:

以上就是SearchView给开发者提供的常规方法调用和属性设置,可是这并不能知足咱们的开发需求,由于开发中大部分设计师根据无论MaterialDesign的设计规范,因此大多数状况下须要根据UI设计稿自定义SearchView的样式了,这相对比较复杂,下面将经过实战来学习SearchView的样式自定义,以此来知足咱们的开发需求。

3、实战

仿网易云音乐本地音乐搜索,先看下效果,而后开始实战:

一、设置Toolbar

1)建立该界面的布局activity_search_view2.xml

指定Toolbar的高度、NaviagtionIcon、标题、字体等

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" style="@style/Toolbar.MyStyle" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:navigationIcon="@mipmap/lg" app:popupTheme="@style/ThemeOverlay.AppCompat.Light" app:title="本地音乐" app:titleTextAppearance="@style/Toolbar.TitleText" app:titleTextColor="@android:color/white"/> </LinearLayout>复制代码

其中style指向的Toolbar.MyStyle是设置标题与NavigationIcon的距离,titleTextAppearance指向的Toolbar.TitleText是设置标题文字大小。

在style.xml中建立Toolbar的自定义样式

<!--标题与NavigationIcon的距离-->
<style name="Toolbar.MyStyle" parent="Base.Widget.AppCompat.Toolbar"> <item name="contentInsetStart">0dp</item> <item name="contentInsetStartWithNavigation">0dp</item> </style>

<!--Toolbar标题文字大小-->
<style name="Toolbar.TitleText" parent="TextAppearance.Widget.AppCompat.Toolbar.Title"> <item name="android:textSize">15sp</item> </style>复制代码

若是不设置的话,效果很差,NavigationIcon和Toolbar的标题以前的间距看起来很大,下面看下设置先后的差异:

2)设置去除ActionBar的主题

在Style.xml中建立无ActionBar的主题,并设置主题背景色

<style name="AppTheme.NoActionBar2" parent="AppTheme">
    <item name="colorPrimary">#D33A31</item>
    <item name="colorPrimaryDark">#D33A31</item>
    <item name="windowActionBar">false</item>
    <item name="windowNoTitle">true</item>
    <!--设置menu中item的图标颜色-->
    <item name="android:textColorSecondary">#ffffff</item>
</style>复制代码

不设置textColorSecondary的话,默认menu的item图标是黑色,下面看下设置先后的差异:


为Activity设置主题

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lqr.materialdesigndemo"> <application ... android:theme="@style/AppTheme"> ... <activity android:name=".SearchViewActivity2" android:screenOrientation="portrait" android:theme="@style/AppTheme.NoActionBar2"/> </application> </manifest>复制代码

3)在Activity中设置Toolbar的代码以下:

public class SearchViewActivity2 extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search_view2);
        // 使用Toolbar代替actionbar
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
    }
    ...
}复制代码

二、设置Menu

1)建立菜单布局search_view.xml

跟以前的代码相比,只是多加了几个item而已。

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:tools="http://schemas.android.com/tools">
    <item
        android:id="@+id/menu_search"
        android:orderInCategory="100"
        android:title="搜索"
        app:actionViewClass="android.support.v7.widget.SearchView"
        app:showAsAction="always"
        />
    <item
        android:id="@+id/scan_local_music"
        android:icon="@mipmap/lv"
        android:orderInCategory="100"
        android:title="扫描本地音乐"
        app:showAsAction="never"
        />
    <item
        android:id="@+id/select_sort_way"
        android:icon="@mipmap/lt"
        android:orderInCategory="100"
        android:title="选择排序方式"
        app:showAsAction="never"
        />
    <item
        android:id="@+id/get_cover_lyrics"
        android:icon="@mipmap/lq"
        android:orderInCategory="100"
        android:title="获取封面歌词"
        app:showAsAction="never"
        />
    <item
        android:id="@+id/imporve_tone_quality"
        android:icon="@mipmap/lw"
        android:orderInCategory="100"
        android:title="升级音质"
        app:showAsAction="never"
        />
</menu>复制代码

2)在Activity中设置Menu的代码以下:

public class SearchViewActivity2 extends AppCompatActivity {

    private SearchView mSearchView;
    ...
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.search_view, menu);
        MenuItem searchItem = menu.findItem(R.id.menu_search);

        //经过MenuItem获得SearchView
        mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);

        return super.onCreateOptionsMenu(menu);
    }

    // 让菜单同时显示图标和文字
    @Override
    public boolean onMenuOpened(int featureId, Menu menu) {
        if (menu != null) {
            if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
                try {
                    Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
                    method.setAccessible(true);
                    method.invoke(menu, true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return super.onMenuOpened(featureId, menu);
    }
}复制代码

到这里,除了搜索框(SearchView)之外,整个布局的效果大致上都实现了:

三、定制SearchView样式

接下来要实现的样式自定义有:

重点来了,咱们先来分析一下。SearchView自己不向外提供 “关闭搜索框” 和 “设置搜索框左边的搜索图标” 等方法,因此须要经过其余的方式来实现样式自定义。

考虑:

若是SearchView的布局结构是经过xml布局文件来实现的,那么能够经过SearchView.findViewById()的方式获得其中的部分或全部的控件;若是是经过代码动态添加的话,那么能够经过反射的方式获得咱们须要的控件,进而对控件进行样式设置。

结论:

实现证实,SearchView的布局结构就是使用xml布局文件实现的,该xml文件名为abc_search_view.xml,且基本上每一个控件都有id,这样就能够拿到须要的控件来实现样式自定义了。

1)点击返回按钮,退出搜索框(若搜索框显示的话)

SearchView自己没有提供关闭搜索框的方法(反正我是没找到啊~~),不过SearchView中正好有一个onCloseClicked()方法是用来关闭搜索框,咱们能够经过反射来调用该方法,先来理解下该方法都作了什么,onCloseClicked()的代码以下:

void onCloseClicked() {
    Editable text = this.mSearchSrcTextView.getText();
    //若是搜索框中有文字,则清除其中的文字
    if(TextUtils.isEmpty(text)) {
        if(this.mIconifiedByDefault && (this.mOnCloseListener == null || !this.mOnCloseListener.onClose())) {
            this.clearFocus();
            this.updateViewsVisibility(true);
        }
    } 
    //不然关闭搜索框
    else {
        this.mSearchSrcTextView.setText("");
        this.mSearchSrcTextView.requestFocus();
        this.setImeVisibility(true);
    }
}复制代码

这里要考虑到,当搜索框显示时,按下Toolbar的返回按钮关闭搜索框,不然就关闭当前界面。由于搜索框也有id,因此咱们能够经过id能够获得搜索框控件,用来判断当前搜索框的显隐状态。结合SearchView内部的onCloseClicked()方法,最后Toolbar返回按钮的点击事件代码能够这么写:

public class SearchViewActivity2 extends AppCompatActivity {

    private SearchView mSearchView;
    private SearchView.SearchAutoComplete mSearchAutoComplete;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search_view2);
        ...
        //Toolbar返回按钮的点击事件
        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mSearchAutoComplete.isShown()) {
                    try {
                        //若是搜索框中有文字,则会先清空文字,但网易云音乐是在点击返回键时直接关闭搜索框
                        mSearchAutoComplete.setText("");
                        Method method = mSearchView.getClass().getDeclaredMethod("onCloseClicked");
                        method.setAccessible(true);
                        method.invoke(mSearchView);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    finish();
                }
            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.search_view, menu);
        MenuItem searchItem = menu.findItem(R.id.menu_search);

        //经过MenuItem获得SearchView
        mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
        //经过id获得搜索框控件
        mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);

        return super.onCreateOptionsMenu(menu);
    }

    ...
}复制代码

2)隐藏搜索框左边的搜索图标

搜索框中左边的搜索图标不是一个控件,因此没办法经过id获得,但好在能够经过设置style的方式来修改SearchView全部的图标。方法也很简单,只需建立一个style(这里取名Widget.SearchView)继承自Widget.AppCompat.SearchView,而后替换须要修改的属性便可。先看下Widget.AppCompat.SearchView的父级Base.Widget.AppCompat.SearchView吧:

能够看到,这个父级style提供了SearchView中几乎全部的Icon属性,这意味着在图标定制上能够有很大拓展性。其中,layout是指定SearchView的布局,原始布局就是abc_search_view.xml,咱们通常不会去动这个属性。
这里咱们只须要去掉搜索框左边的图标(即:searchHintIcon),直接设置为@null就行了,以下修改style文件中的Widget.SearchView主题:

<!--没有ActionBar主题,自定义SearchView样式-->
<style name="AppTheme.NoActionBar2" parent="AppTheme"> ... <!--引入SearchView的自定义样式--> <item name="searchViewStyle">@style/Widget.SearchView</item> </style>

<style name="Widget.SearchView" parent="Widget.AppCompat.SearchView">
    <!--修改搜索框提示文字--> <item name="defaultQueryHint">搜索本地歌曲</item> <!--修改打开搜索框的搜索按钮的图标--> <item name="searchIcon">@mipmap/m5</item> <!--修改搜索框左边的搜索按钮图标--> <item name="searchHintIcon">@null</item> </style>复制代码

3)设置搜索框的提示文字

修改提示文字内容

修改搜索框提示文字的方式有两种,一种就是修改SearchView的style,如上一步中,修改Widget.AppCompat.SearchView的defaultQueryHint属性;另外一种方式是调用SearchView的setQueryHint()来修改。这两种方式均可以,若是同时用这两种方式来设置搜索框的提示语,则最终的提示内容将以代码设置方式为主。

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_view, menu);
    MenuItem searchItem = menu.findItem(R.id.menu_search);

    //经过MenuItem获得SearchView
    mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);

    //经过代码方式修改提示文字内容
    mSearchView.setQueryHint("搜索本地歌曲by code");

}复制代码

修改提示文字样式

SearchView也没有提供任何直接修改搜索框提示文字样式的方法,但既然咱们能够经过id获得搜索框控件,那设置提示文字的样式便不是什么问题了,代码以下:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_view, menu);
    MenuItem searchItem = menu.findItem(R.id.menu_search);

    //经过MenuItem获得SearchView
    mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);
    mSearchView.setQueryHint("搜索本地歌曲by code");

    //设置输入框提示文字样式
    mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.darker_gray));
    mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.background_light));
    mSearchAutoComplete.setTextSize(14);

    return super.onCreateOptionsMenu(menu);
}复制代码

4)根据搜索框中有无文字,来显隐搜索框右边的叉叉

这个有点像searchView.onActionViewExpanded()的效果,惟一的区别就是搜索框不能是默认展开的,这要怎么办呢?经过观察onActionViewExpanded()的源码,能够发现该方法中调用了setIconified(false)!!!再联想到setIconified(false)自己就有让搜索框默认展开的效果,这是否是意味着,只要让onActionViewExpanded()的setIconified(false)改成setIconified(true)就行了呢?答案是是的。并且不须要重写SearchView,由于onActionViewExpanded()和setIconified(true)是能够搭配使用的,只要依次调用这两个方法就能够实现这种效果了,代码以下:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_view, menu);
    MenuItem searchItem = menu.findItem(R.id.menu_search);

    //经过MenuItem获得SearchView
    mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);
    mSearchView.setQueryHint("搜索本地歌曲by code");

    //设置输入框提示文字样式
    mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.darker_gray));
    mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.background_light));
    mSearchAutoComplete.setTextSize(14);

    //设置搜索框有字时显示叉叉,无字时隐藏叉叉
    mSearchView.onActionViewExpanded();
    mSearchView.setIconified(true);

    //修改搜索框控件间的间隔(这样只是为了在细节上更加接近网易云音乐的搜索框)
    LinearLayout search_edit_frame = (LinearLayout) mSearchView.findViewById(R.id.search_edit_frame);
    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) search_edit_frame.getLayoutParams();
    params.leftMargin = 0;
    params.rightMargin = 0;
    search_edit_frame.setLayoutParams(params);
    return super.onCreateOptionsMenu(menu);
}复制代码

四、实现搜索提示功能

上面咱们已经学习了SearchView的UI定制,下面将经过SearchView自身或结合ListView的方式(RecyclerView应该也同样吧,还没试过)直接学习SearchView搜索提示功能的实现,继续完善 “仿网易云音乐本地音乐搜索” 效果。

1)弹出式搜索提示

SearchView自己的搜索框就是AutoCompleteTextView的一个子类,有图有真相。

AutoCompleteTextView是能够经过设置适配器来实现文本补全提示功能的,因此,SearchView中的搜索框同样也能够,不过SearchView提供了setSuggestionsAdapter()方法能够直接为搜索框设置适配器,须要注意的是,这个适配器必须跟数据库的Cursor对象一块儿使用,例如:

mSearchView.setSuggestionsAdapter(new SimpleCursorAdapter(SearchViewActivity2.this, R.layout.item_layout, cursor, new String[]{"name"}, new int[]{R.id.text1}));复制代码

通常开发中遇到的需求是一边输入关键字一边显示搜索结果,因此须要监听搜索框的文字输入,一旦文字变化就查询数据库,更新搜索结果,因此代码能够这么写:

// 监听搜索框文字变化
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String s) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String s) {
        Cursor cursor = TextUtils.isEmpty(s) ? null : queryData(s);
        // 不要频繁建立适配器,若是适配器已经存在,则只须要更新适配器中的cursor对象便可。
        if (mSearchView.getSuggestionsAdapter() == null) {
            mSearchView.setSuggestionsAdapter(new SimpleCursorAdapter(SearchViewActivity2.this, R.layout.item_layout, cursor, new String[]{"name"}, new int[]{R.id.text1}));
        } else {
            mSearchView.getSuggestionsAdapter().changeCursor(cursor);
        }

        return false;
    }
});复制代码

对于SimpleCursorAdapter的使用,不熟悉的本身百度学习吧,下面看效果:

能够发现,当输入第一个文字"a"时,没有什么反应,当输入第二个文字"a"时,弹出了一个列表弹窗,这是因为AutoCompleteTextView自己默认触发查询动做的条件就是该控件中的文字至少要2个以上,若是咱们想修改为只要有一个文字就触发查询的话,则能够这么作:

  1. 拿到SearchView中搜索框控件
  2. 调用setThreshold()设置触发查询的字数

直接上代码:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.search_view, menu);
    MenuItem searchItem = menu.findItem(R.id.menu_search);

    //经过MenuItem获得SearchView
    mSearchView = (SearchView) MenuItemCompat.getActionView(searchItem);
    mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);
    ...
    //设置触发查询的最少字符数(默认2个字符才会触发查询)
    mSearchAutoComplete.setThreshold(1);
}复制代码

再看下效果:

好了,弹出式搜索功能作完了,下面贴出条目布局item_layout.xml和queryData()方法的代码实现:

① item_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <TextView android:id="@+id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:minHeight="?android:attr/listPreferredItemHeightSmall" android:paddingLeft="10dp" android:paddingRight="10dp" android:textAppearance="?android:attr/textAppearanceListItemSmall" android:textColor="@android:color/black"/> </LinearLayout>复制代码

② queryData()

只是简单的建立一个数据库(music.db),库中有一张tb_music表,表中有_id和name两个字段,而后填充数据,查询数据,相对比较简单,这里就不作过多解释了。

private Cursor queryData(String key) {
    SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(getFilesDir() + "music.db", null);
    Cursor cursor = null;
    try {
        String querySql = "select * from tb_music where name like '%" + key + "%'";
        cursor = db.rawQuery(querySql, null);
    } catch (Exception e) {
        e.printStackTrace();
        String createSql = "create table tb_music (_id integer primary key autoincrement,name varchar(100))";
        db.execSQL(createSql);

        String insertSql = "insert into tb_music values (null,?)";
        for (int i = 0; i < Cheeses.sCheeseStrings.length; i++) {
            db.execSQL(insertSql, new String[]{Cheeses.sCheeseStrings[i]});
        }

        String querySql = "select * from tb_music where name like '%" + key + "%'";
        cursor = db.rawQuery(querySql, null);
    }
    return cursor;
}复制代码

2)结合ListView实现搜索提示

虽然上面已经实现了搜索提示的功能,但网易云音乐本地搜索出来的结果并非弹出式的,而是在SearchView下方以列表的方式呈现,要作到这样的效果,就必需让SearchView结合ListView一块儿使用。其实这并不难,由于AutoCompleteTextView设置的适配器跟ListView要设置的适配器是同样的,直接将上边的适配器设置给ListView便可。

// 监听搜索框文字变化
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
    @Override
    public boolean onQueryTextSubmit(String s) {
        return false;
    }

    @Override
    public boolean onQueryTextChange(String s) {
        Cursor cursor = TextUtils.isEmpty(s) ? null : queryData(s);
        // 设置或更新ListView的适配器
        setAdapter(cursor);
        return false;
    }
});

private void setAdapter(Cursor cursor) {
    if (mLv.getAdapter() == null) {
        SimpleCursorAdapter adapter = new SimpleCursorAdapter(SearchViewActivity2.this, R.layout.item_layout, cursor, new String[]{"name"}, new int[]{R.id.text1});
        mLv.setAdapter(adapter);
    } else {
        ((SimpleCursorAdapter) mLv.getAdapter()).changeCursor(cursor);
    }
}复制代码

这样就完成了,虽然样式上是丑了点,但,那又怎样,呵呵~

最后附上Demo连接

github.com/GitLqr/Mate…

相关文章
相关标签/搜索