Android中SearchView的使用

亲爱的同窗们我又来了,搬好小板凳准备开车了。。。android

不知道你们平时都用什么听音乐,我我的比较喜欢网易云音乐 (不是作广告,可是我这是干啥呢?),不过如今网易云音乐不能停周董的歌了,实在有些。。。那天忽然想起最近研究的MaterialDesign,就想到的网易云音乐的标题栏是怎么实现的。后来我就各类百度,中于功夫不负有心人,总算是被我刨出来了!其实网易云音乐使用的就是标题上面说的SearchView,其实就是一个搜索的View。那么怎么实现的呢?请听下回分解!bash

开玩笑啊!!!

开个玩笑,同窗们准备好,立刻开车了。。。app

本文知识点

  • SearchView的介绍
  • 实现网易云音乐的搜索功能
    • 基本的搜索功能实现
    • 页面的美化问题
    • 一些常见的问题

先简单说明一下,这里主要是讲解SearchView怎么实现网易云音乐的标题栏,可是都是以来Toolbar的,若是你对Toolbar和menu不是很了解的话!ide

请看我公众号的这两篇文章(强势输出一波)布局

上面很详细的讲解了关于Toolbar和menu的使用方法和注意事项!!!this

1. SearchView的介绍

SearchView是和Toolbar联动,经过menu进行设置的搜索的控件(不知道我这么归纳你能不能懂)。会在Toolbar的右侧出现一个搜索的按钮(系统自带的,也能够进行替换)。当你点击搜索按钮的时候,会出现相应的编辑框进行搜索。当你点击叉号的时候,本次搜索取消,还原成搜索按钮。google

2. 网易云音乐的搜索功能

2.1 基本的搜索功能实现

这里针对menu作了一些修改,因此可能和你出现的基本效果不太同样,可是我会把相应的内容贴出来,这样便于像我同样的懒癌患者,能很快的实现效果。毕竟开发项目紧的时候我是不会管是怎么实现的!!!先看一下基本功能的效果图spa

原谅个人配色

相信你看了以前的那两篇文章的话,很快就能写出下面这个标题栏的。

  • menu文件的代码
<?xml version="1.0" encoding="utf-8"?>
<!--仿网易云音乐的menu实现-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <item
        android:id="@+id/search"
        android:icon="@drawable/ic_search_black_24dp"
        android:title="搜索"
        app:actionViewClass="android.support.v7.widget.SearchView"
        app:showAsAction="always" />

    <item
        android:id="@+id/other"
        android:title="其余内容"
        app:showAsAction="never" />
</menu>
复制代码
  • 布局文件的代码
<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.jinlong.newmaterialdesign.toolbar.YunActivity">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="#ff0000"
        app:popupTheme="@style/ToolbarTheme"
        app:navigationIcon="@mipmap/back_icon">

        <TextView
            android:id="@+id/tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:text="云Toolbar的实现"
            android:textColor="@android:color/white"
            android:textSize="18sp" />
    </android.support.v7.widget.Toolbar>

</LinearLayout>
复制代码
  • Activity中的代码
public class YunActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_yun);

        initToolbar();
    }

    private void initToolbar() {
        Toolbar toolbar = findViewById(R.id.toolbar);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.menu_yun,menu);
        return super.onCreateOptionsMenu(menu);
    }
}
复制代码

上面代码跑一下,紧接着就能够看见上面的内容了!

2.1.1 搜索按钮的初始化和监听问题

  • 初始化SearchView

    由于在初始化SearcheView,须要对相应的menu进行操做,因此通常都会在onCreateOptionsMenu(Menu menu)中进行获取。具体代码以下:

//获取SearchView对象
        MenuItem searchItem = menu.findItem(R.id.search);
        mSearchView = (SearchView) searchItem.getActionView();
复制代码

这里注意一点,就是在初始化SearchView的时候,也可使用MenuItemCompat.getActionView(searchItem);进行获取的,只不过是过期了。。。因此见到了不要说不知道就行

  • 相应的监听setOnQueryTextListener(OnQueryTextListener listener)
setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                //在文字改变的时候回调,query是改变以后的文字
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                //文字提交的时候哦回调,newText是最后提交搜索的文字
                return false;
            }
        });
复制代码

上面的内容能够实现简单的搜索了?其实我我的以为这一个监听还不够?为何这么说呢?由于你想要控制Fragment的切换,没有相应的时间点,或者说是没找到时机进行Fragment的切换问题,当时我想了很久,后来看见源码的时候,我才发现,其实这种时机google工程是早就替咱们想好了,其实我以为咱们能想到的,google工程师会替咱们实现的!

  • setOnSearchClickListener(OnClickListener listener) 在点击Search那个图标的时候回调的方法。
  • setOnCloseListener(OnCloseListener listener) 在点击搜索后那个叉号的时候回调的方法。

这样就存在相应的时间点了,你在进来的时候开启一个事物,放进去一个Fragment(这里若是你想加动画效果的话,你可使用ViewPager,而后经过设置显示那个的方法进行切换.其实事物也是能够设置动画的,看你怎么选择吧)。当你点击关闭的时候。再将以前的Fragment替换掉就能够了。这里为了你们能更好的理解,我仍是用代码实现一下吧!先看下效果(虚拟机录得有点渣!)

展现效果

  • 其实xml中没有什么变化,就不贴了!
  • Activity中的代码是最主要的,代码以下:
public class YunActivity extends AppCompatActivity {

    private static final String TAG = YunActivity.class.getSimpleName();
    private SearchView mSearchView;
    private ViewPager mVpContent;
    private SearchFragment mSearchFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_yun);

        Log.e(TAG, "onCreate: ");

        initToolbar();
        initViewPager();
    }


    private void initToolbar() {
        Toolbar toolbar = findViewById(R.id.toolbar);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);
    }

    private void initViewPager() {
        mVpContent = findViewById(R.id.vp_content);

        List<Fragment> list = new ArrayList<>();
        DefaultFragment defaultFragment = new DefaultFragment();
        list.add(defaultFragment);
        mSearchFragment = new SearchFragment();
        list.add(mSearchFragment);

        MainVPAdapter adapter = new MainVPAdapter(getSupportFragmentManager(), list);

        mVpContent.setAdapter(adapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        Log.e(TAG, "onCreateOptionsMenu: ");
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.menu_yun, menu);

        //获取SearchView对象
        MenuItem searchItem = menu.findItem(R.id.search);
        mSearchView = (SearchView) searchItem.getActionView();

        //设置相应的监听,文字变化的监听
        mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                //在文字改变的时候回调,query是改变以后的文字
                mSearchFragment.setSearchStr(query);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                //文字提交的时候哦回调,newText是最后提交搜索的文字
                return false;
            }
        });

        mSearchView.setOnSearchClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //开始搜索的时候,设置显示搜索页面
                mVpContent.setCurrentItem(1);
            }
        });


        mSearchView.setOnCloseListener(new SearchView.OnCloseListener() {
            @Override
            public boolean onClose() {
                //关闭搜索按钮的时候,设置显示默认页面
                mVpContent.setCurrentItem(0);
                return false;
            }
        });

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

这里最主要的就是那几个监听,只要你理解了那几个监听的话基本上就没有问题了。

  • Fragment中的代码:
public class SearchFragment extends Fragment {


    private TextView mTvSearch;

    public SearchFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        View rootView = inflater.inflate(R.layout.fragment_search, container, false);

        mTvSearch = rootView.findViewById(R.id.tv_search);
        return rootView;
    }
    
    /**
     * 搜索的内容
     */
    public void setSearchStr(String query) {
        if (!TextUtils.isEmpty(query))
            mTvSearch.setText("搜索的内容是" + query);
    }
}
复制代码

这样就能实现相应的效果了。怎么样?不错吧!!!

2.2 界面的美化问题

2.2.1 默认的提示文字

没有提示文字的样式

上面的图是没有提示文字时候显示的样子,怎么添加提示文字呢?

searchView.setQueryHint("相应的提示内容");
复制代码

经过上面的代码就能够添加搜索的提示文字了。

2.2.2 搜索按钮不消失

这个搜索按钮是在输入框的内部,当你设置内容的时候,搜索按钮会消失。这个我感受我描述的不太正确,管他呢?大家理解就好。。。

  • setIconifiedByDefault(boolean iconified) 这个Api主要是控制搜索按钮是否在输入框内部的,true表明在内部显示,false表明在外部显示

2.2.3 搜索按钮取消关闭图标的问题

有的产品经理总会有奇葩的需求,想要去掉那个搜索后面的叉号。说不人性。。。只能默默的改了。。。其实个人心里是崩溃的。。。

  • onActionViewExpanded() 设置关闭图标不显示的Api

虽然你能关闭这个图标,可是这样就存在一个问题了,以前写好的关闭切换Fragment的操做在这里就会失效了。怎么解决呢?想了半天,只有处理返回事件了,要不我根本就没有办法知道用户真么时候搜索完成啊?那就只有何时执行返回操做何时算他结束了呗!

toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mSearchAutoComplete.isShown()) {
                    try {
                        mSearchAutoComplete.setText("");//清除文本
                        //利用反射调用收起SearchView的onCloseClicked()方法
                        Method method = mSearchView.getClass().getDeclaredMethod("onCloseClicked");
                        method.setAccessible(true);
                        method.invoke(mSearchView);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                } else {
                    finish();
                }
            }
        });
复制代码

加上这段代码的话,经过反射拿到SearchView的onDloseClicked(),调用一下就能够了

2.2.4 搜索栏的默认展开问题

产品又说了,进到这个页面,默认应该是显示搜索对话框的,用户少操做一步,用户体验好,当时我就说了。那用户就要那样呢?产品说那样的奇葩用户不用管。。。(当时的我啊!满脑壳黑线)

  • setIconified(boolean iconify) 设置搜索输入框是不是展开的,这里注意啊!false表明展开,true表明关闭状态

2.2.5 修改搜索图标或者去掉图标

老根产品过不去也不行吧!这里本身看了看搜索图标以为小了,想更改一下!怎么办呢?

就是在页面的Activity的主题中,添加相应的searchViewStyle属性,这个属性能够本身设置的。

<!--SearchView的主题设置-->
    <item name="searchViewStyle">@style/SearchViewStyle</item>
        
    <!--SearchView的主题设置-->
    <style name="SearchViewStyle" parent="Widget.AppCompat.SearchView">
        <!--修改图标的图片-->
        <item name="searchIcon">@mipmap/ic_directions_bike_white_24dp</item>
        <!--去掉图标-->
        <!--<item name="searchHintIcon">@null</item>-->
    </style>        
复制代码

这里的图片就看你发挥了。。。

2.2.6 修改文字颜色

当你以为输入框的文字或者提示的文字是黑色比较难看的时候,那么你能够像下面这样修改

//修改searchView的文字颜色
        SearchView.SearchAutoComplete mSearchAutoComplete = mSearchView.findViewById(R.id.search_src_text);
        //设置输入框内提示文字样式
        mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.white));//设置提示文字颜色
        mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.white));//设置内容文字颜色
复制代码

不知道还有没有什么其余的了,我感受有了这些对付大家产品经理就已经足够了,不行桌子上放把刀、要不放个二维码啥的就能够了。。。

但愿个人文章对你有帮助!但愿咱们共同进步。。。see you!

若是你感兴趣,请关注个人二维码

笔墨Android
相关文章
相关标签/搜索