Android高级UI开发(十四)之Toolbar + SearchView

举报
yd_57386892 发表于 2020/12/29 01:18:37 2020/12/29
【摘要】        今天公司暖气来了,意味着又到了年末。我们日夜重复着昨天的生活像白开水一样的活着,忙碌着却无成绩的挣扎着。没关系,有些人还是很快乐因为它们从中得到了充实,自乐其中。可是我们不要忘了这个世界上只有活的有意义才是最大的幸福。通过博客来记录生活与技术,只有把一些东西写下来,才能让我看得更明白,才能不断发现迷失的自己。今天我们就来讲一下Android开发中的寻找(Sear...

       今天公司暖气来了,意味着又到了年末。我们日夜重复着昨天的生活像白开水一样的活着,忙碌着却无成绩的挣扎着。没关系,有些人还是很快乐因为它们从中得到了充实,自乐其中。可是我们不要忘了这个世界上只有活的有意义才是最大的幸福。通过博客来记录生活与技术,只有把一些东西写下来,才能让我看得更明白,才能不断发现迷失的自己。今天我们就来讲一下Android开发中的寻找(SearchView)。首先,我们看一下今天要实现的SearchView的展示效果:

     上一节我们已经讲了SearchView是显示在ToolBar上的一个搜、索控件,这节我们就详细讲解下它的用法,为了故事的完整性我们还是从ToolBar开始。

一、ToolBar的展示与菜单(包括SearchView)

1. activity_main.xml(后面MainActivity的布局)


  
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. xmlns:app="http://schemas.android.com/apk/res-auto"
  5. android:orientation="vertical">
  6. <android.support.v7.widget.Toolbar
  7. android:id="@+id/toolbar"
  8. style="@style/Toolbar.MyStyle"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:background="?attr/colorPrimary"
  12. app:title="我的Tool"
  13. app:titleTextColor="@color/colorWhite"
  14. app:navigationIcon="@mipmap/gongzhong_fanhui"
  15. app:titleTextAppearance="@style/Toolbar.TitleText"
  16. >
  17. </android.support.v7.widget.Toolbar>
  18. </LinearLayout>

activity_main.xml里声明了一个ToolBar,android:background背景色为主题颜色,app:title标题为“我的Tool”,app:titleTextColor标题颜色为白色,app:navigationIcon返回箭头,app:titleTextAppearance="@style/Toolbar.TitleText"标题的字体样式在values-styles样式文件里定义如下(字体大小为15sp):


  
  1. <!--Toolbar标题文字大小-->
  2. <style name="Toolbar.TitleText" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
  3. <item name="android:textSize">15sp</item>
  4. </style>

 style="@style/Toolbar.MyStyle"整个ToolBar的样式在values-styles样式文件里定义如下:


  
  1. <style name="Toolbar.MyStyle" parent="Base.Widget.AppCompat.Toolbar">
  2. <item name="contentInsetStart">0dp</item>
  3. <item name="contentInsetStartWithNavigation">0dp</item>
  4. </style>

其中      <item name="contentInsetStart">0dp</item> 与<item name="contentInsetStartWithNavigation">0dp</item>的作用是让标题“我的ToolBar”离 返回箭头更贴近一些,因为默认标题与返回箭头间的空隙太大。截至目前整个styles.xml文件内容如下:


  
  1. <resources>
  2. <!-- Base application theme. -->
  3. <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
  4. <!-- Customize your theme here. -->
  5. <item name="colorPrimary">@color/colorPrimary</item>
  6. <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  7. <item name="colorAccent">@color/colorAccent</item>
  8. </style>
  9. <!--标题与NavigationIcon的距离-->
  10. <style name="Toolbar.MyStyle" parent="Base.Widget.AppCompat.Toolbar">
  11. <item name="contentInsetStart">0dp</item>
  12. <item name="contentInsetStartWithNavigation">0dp</item>
  13. </style>
  14. <!--Toolbar标题文字大小-->
  15. <style name="Toolbar.TitleText" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
  16. <item name="android:textSize">15sp</item>
  17. </style>
  18. </resources>

2. 菜单定义menu---main.xml


  
  1. <menu xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. tools:context="com.ricky.materialdesign.toolbar.MainActivity"
  4. xmlns:app="http://schemas.android.com/apk/res-auto">
  5. <item
  6. android:id="@+id/action_search"
  7. android:orderInCategory="100"
  8. app:actionViewClass="android.support.v7.widget.SearchView"
  9. app:showAsAction="always"
  10. android:title="查找"/>
  11. <item
  12. android:id="@+id/action_settings"
  13. android:orderInCategory="100"
  14. app:showAsAction="never"
  15. android:title="设置"/>
  16. <item
  17. android:id="@+id/action_share"
  18. android:orderInCategory="100"
  19. app:showAsAction="always"
  20. android:title="分享"
  21. android:icon="@android:drawable/ic_menu_share"/>
  22. <item
  23. android:id="@+id/action_edit"
  24. android:orderInCategory="100"
  25. app:showAsAction="ifRoom"
  26. android:title="编辑"
  27. android:icon="@android:drawable/ic_menu_edit"/>
  28. </menu>

main.xml里定义了4个菜单项,第一个菜单项就是我们定义的SearchView,  app:showAsAction="always"表示这个搜索控件总会显示在ToolBar表面,第二个菜单项是设置菜单 app:showAsAction="never"意味着它将隐藏在右上角三个...的菜单里。第三个是分享菜单项,它与SearchView一样也会显示在ToolBar表面。第四个菜单项—编辑菜单,app:showAsAction="ifRoom"属性表示如果ToolBar表面还有空间的话那么它也将显示在ToolBar表面。

3. MainActivity.java

加载activity_main.xml与menu--main.xml来显示ToolBar和它附带的菜单项。


  
  1. package com.example.administrator.toolbarstudy;
  2. import android.graphics.Color;
  3. import android.os.Bundle;
  4. import android.support.v4.view.MenuItemCompat;
  5. import android.support.v7.app.AppCompatActivity;
  6. import android.support.v7.widget.SearchView;
  7. import android.support.v7.widget.SearchView.OnCloseListener;
  8. import android.support.v7.widget.SearchView.OnQueryTextListener;
  9. import android.support.v7.widget.Toolbar;
  10. import android.text.TextUtils;
  11. import android.util.Log;
  12. import android.view.KeyEvent;
  13. import android.view.Menu;
  14. import android.view.MenuItem;
  15. import android.view.View;
  16. import android.view.View.OnClickListener;
  17. import android.view.View.OnFocusChangeListener;
  18. import android.view.ViewGroup;
  19. import android.widget.Adapter;
  20. import android.widget.EditText;
  21. import android.widget.ImageView;
  22. import android.widget.LinearLayout;
  23. import android.widget.ListAdapter;
  24. import android.widget.ListView;
  25. import android.widget.TextView;
  26. import android.widget.Toast;
  27. import java.lang.reflect.Method;
  28. import java.util.ArrayList;
  29. import java.util.List;
  30. public class MainActivity extends AppCompatActivity {
  31. SearchView.SearchAutoComplete mSearchAutoComplete;
  32. SearchView mSearchView;
  33. MyAdapter adapter;
  34. String TAG = "MainActivity";
  35. ListView lvAutoText;
  36. List<String> namesCollection = new ArrayList<>();
  37. List<String> names = new ArrayList<>();
  38. @Override
  39. protected void onCreate(Bundle savedInstanceState) {
  40. super.onCreate(savedInstanceState);
  41. setContentView(R.layout.activity_main);
  42. Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
  43. setSupportActionBar(toolbar);
  44. getSupportActionBar().setDisplayShowTitleEnabled(true);
  45. //返回键
  46. toolbar.setNavigationOnClickListener(new OnClickListener() {
  47. @Override
  48. public void onClick(View v) {
  49. clickBack();
  50. }
  51. });
  52. }
  53. /**
  54. * 点击返回(包括手机物理按键)
  55. */
  56. public void clickBack()
  57. {
  58. if (mSearchAutoComplete.isShown()) {
  59. try {
  60. //折叠搜索框
  61. mSearchAutoComplete.setText("");
  62. Method method = mSearchView.getClass().getDeclaredMethod("onCloseClicked");
  63. method.setAccessible(true);
  64. method.invoke(mSearchView);
  65. } catch (Exception e) {
  66. e.printStackTrace();
  67. }
  68. } else {
  69. finish();
  70. }
  71. return;
  72. }
  73. /**
  74. * 让菜单同时显示图标和文字
  75. * @param featureId
  76. * @param menu
  77. * @return
  78. */
  79. @Override
  80. public boolean onMenuOpened(int featureId, Menu menu) {
  81. if (menu != null) {
  82. if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
  83. try {
  84. Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
  85. method.setAccessible(true);
  86. method.invoke(menu, true);
  87. } catch (Exception e) {
  88. e.printStackTrace();
  89. }
  90. }
  91. }
  92. return super.onMenuOpened(featureId, menu);
  93. }
  94. /**
  95. * 根据menu--main.xml加载菜单
  96. * @param menu
  97. * @return
  98. */
  99. @Override
  100. public boolean onCreateOptionsMenu(Menu menu) {
  101. getMenuInflater().inflate(R.menu.main, menu);
  102. MenuItem item = menu.findItem(R.id.action_search);
  103. mSearchView = (SearchView) MenuItemCompat.getActionView(item);
  104. //通过id得到搜索框控件
  105. mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);
  106. return true;
  107. }
  108. @Override
  109. public boolean onOptionsItemSelected(MenuItem item) {
  110. int id = item.getItemId();
  111. if (id == R.id.action_settings) {
  112. Toast.makeText(MainActivity.this,"您点击了设置",Toast.LENGTH_SHORT).show();
  113. return true;
  114. }
  115. else if(id == R.id.action_share)
  116. {
  117. Toast.makeText(MainActivity.this,"您点击了分享",Toast.LENGTH_SHORT).show();
  118. return true;
  119. }
  120. return super.onOptionsItemSelected(item);
  121. }
  122. /**
  123. * 按系统返回键与按标题栏上的返回产生相同的效果
  124. * @param keyCode
  125. * @param event
  126. * @return
  127. */
  128. @Override
  129. public boolean onKeyDown(int keyCode, KeyEvent event) {
  130. if(keyCode == KeyEvent.KEYCODE_BACK)
  131. {
  132. clickBack();
  133. return true;
  134. }
  135. return super.onKeyDown(keyCode, event);
  136. }
  137. }

代码分析

3.1  折叠搜索控件(SearchView)

在上述代码里我们定义了返回键的响应处理


  
  1. //返回键
  2. toolbar.setNavigationOnClickListener(new OnClickListener() {
  3. @Override
  4. public void onClick(View v) {
  5. clickBack();
  6. }
  7. });

clickBack函数实现了一个功能,就是当搜索框展开显示的时候,折叠SearchView(搜索框),如果SearchView本来就是折叠的则点返回键直接关闭当前页面。同时,我们在Activity的onKeyDown里也调用的clickBack函数。其中mSearchAutoComplete.就是搜索文本框,它是一个自动完成文本框,mSearchView就是SearchView控件实例,它们都在onCreateOptionsMenu函数里创建。

3.2 加载SearchView

onCreateOptionsMenu函数从menu--main.xml里加载出各菜单,并从中得到了mSearchView 与mSearchASutoComplete,这两个控件实例分别是SearchView控件与 SearchView控件中的搜索文本框,这两个变量在3.1中的clickBack函数中有使用。

3.3 菜单项的点击事件

 onOptionsItemSelected函数里处理了菜单的点击事件。

3.4  onMenuOpened

让菜单项同时显示图标与文本,例如下图中的“编辑”菜单项:

4. 界面效果

4.1 截止目前,运行效果如下:

点击搜索图标展开SearchView控件,输入文本后点右边的叉号删除文本,当SearchView展开的时候点返回箭头则折叠SearchView搜索文本框,当SearchView已经折叠的时候,然后继续按返回键则关闭当前页面(这种情况以下动画中没有演示)。

4.2 改进UI

我们从上述运行效果图中可以看出:

“搜索图标”、“搜索文字”、“X号”、“三个点点”的颜色都是黑色,能不能让它们变成白色。答案是可以的!为AppTheme添加一个配置android:textColorSecondary将其设置为白色可以改变菜单项图标的颜色。


  
  1. <!-- Base application theme. -->
  2. <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
  3. <!-- Customize your theme here. -->
  4. <item name="colorPrimary">@color/colorPrimary</item>
  5. <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  6. <item name="colorAccent">@color/colorAccent</item>
  7. <!--设置menu中item的图标颜色-->
  8. <item name="android:textColorSecondary">@color/colorWhite</item>-->
  9. </style>

同时在MainActivity.java代码中onCreateOptionsMenu函数里添加代码:

int colorWhite = this.getResources().getColor(R.color.colorWhite);
mSearchAutoComplete.setTextColor(colorWhite);

其中mSearchAutoComplete就是那个搜索文本框。

这样再运行效果如下:

这下界面颜色一致了都是白色的了,漂亮多了。这只是个UI,接下来我们研究一下与SearchView相关的事件处理函数以及结合ListView实现  “搜索自动提示” 功能。

二、SearchView相关代码

1. SearchView相关代码:


  
  1. /**
  2. * 根据menu--main.xml加载菜单
  3. * @param menu
  4. * @return
  5. */
  6. @Override
  7. public boolean onCreateOptionsMenu(Menu menu) {
  8. getMenuInflater().inflate(R.menu.main, menu);
  9. MenuItem item = menu.findItem(R.id.action_search);
  10. mSearchView = (SearchView) MenuItemCompat.getActionView(item);
  11. //设置最大宽度mSearchView.setMaxWidth
  12. //通过id得到搜索文本框控件
  13. mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);
  14. int color = this.getResources().getColor(R.color.colorWhite);
  15. mSearchAutoComplete.setTextColor(color);
  16. /*------------------ SearchView有三种默认展开搜索框的设置方式,区别如下: ------------------*/
  17. //1.设置搜索框直接展开显示。左侧有放大镜(在搜索框外) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
  18. //searchView.setIconifiedByDefault(false);
  19. //2.设置搜索框直接展开显示。左侧有放大镜(在搜索框中) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
  20. mSearchView.onActionViewExpanded();
  21. //3.false设置搜索框直接展开显示,true缩减为一个搜索图标。左侧有放大镜(在搜索框中) 右侧有叉叉 可以关闭搜索框
  22. mSearchView.setIconified(true);
  23. //SearchView用到了一个布局,在V7compat里面找到abc_search_view.xml,在里面可以找到SearchView各组成部分的资源ID
  24. //设置"提交搜索"按钮的图标,就是那个">"右箭头提交按钮
  25. //ImageView icon = (ImageView) mSearchView.findViewById(R.id.search_go_btn);
  26. //icon.setImageResource(R.mipmap.voice_search);
  27. //设置搜索框文本的hint,与mSearchAutoComplete.setHint功能一样
  28. mSearchView.setQueryHint("搜索本地歌曲by code");
  29. //设置搜索文本框的字体
  30. mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.darker_gray));
  31. mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.background_light));
  32. mSearchAutoComplete.setTextSize(14);
  33. //修改搜索框控件间的间隔(这样只是为了在细节上更加接近网易云音乐的搜索框)
  34. LinearLayout search_edit_frame = (LinearLayout) mSearchView.findViewById(R.id.search_edit_frame);
  35. ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) search_edit_frame.getLayoutParams();
  36. params.leftMargin = 0;
  37. params.rightMargin = 0;
  38. search_edit_frame.setLayoutParams(params);
  39. //设置提交按钮是否可用(可见)
  40. mSearchView.setSubmitButtonEnabled(true);
  41. //searchView.setSuggestionsAdapter(adapter)
  42. //监听mSearchAutoComplete文本框焦点改变,例如点返回键后SearchView折叠mSearchAutoComplete失去了焦点时执行
  43. mSearchView.setOnQueryTextFocusChangeListener(new OnFocusChangeListener() {
  44. @Override
  45. public void onFocusChange(View v, boolean hasFocus) {
  46. Log.i(TAG,"onFocusChange");
  47. }
  48. });
  49. //searchView折叠监听,当前项目中点击返回键时执行
  50. mSearchView.setOnCloseListener(new OnCloseListener() {
  51. @Override
  52. public boolean onClose() {
  53. Log.i(TAG,"OnCloseListener");
  54. return false;
  55. }
  56. });
  57. 搜索图标按钮(打开搜索框的按钮)的点击事件
  58. mSearchView.setOnSearchClickListener(new OnClickListener() {
  59. @Override
  60. public void onClick(View v) {
  61. Toast.makeText(MainActivity.this, "点击了搜索图标按钮", Toast.LENGTH_SHORT).show();
  62. }
  63. });
  64. //监听文本变化,调用查询
  65. mSearchView.setOnQueryTextListener(new OnQueryTextListener() {
  66. //X右边的"搜索提交"按钮
  67. @Override
  68. public boolean onQueryTextSubmit(String text) {
  69. Toast.makeText(MainActivity.this, "点击了提交按钮:"+text, Toast.LENGTH_SHORT).show();
  70. return false;
  71. }
  72. @Override
  73. public boolean onQueryTextChange(String text) {
  74. // 文本改变的时候回调
  75. Log.i(TAG,"文本变化~~~~~"+text);
  76. return false;
  77. }
  78. });
  79. return true;
  80. }

注释还是比较全的。在 这里我们主要看一下setOnQueryTextListener,它包含2个回调函数onQueryTextSubmit与onQueryTextChange,其中onQueryTextChange检测文本变化,例如当你输入字母a时就会调用这个函数,这个正好可以用来实现那种边输入边搜索的效果。

2.  SearchView结合Listviews实现自动提示

   我们可以结合Listview来实现边搜索边提示的功能。例如输入a,则请求服务器,服务器会返回abc, aaa,acd ...等包含a的搜索提示列表。在这里我们不请求服务器,为了演示方便我们把“搜索提示文本的集合”放在本地,如一个字符串数组:


  
  1. List<String> namesCollection = new ArrayList<>();
  2. namesCollection.add("abcd");
  3. namesCollection.add("adc");
  4. namesCollection.add("bbc");
  5. namesCollection.add("bac");
  6. namesCollection.add("cab");
  7. namesCollection.add("ccb")

到时候我们在搜索文本框里输入a,ListView将显示abcd, adc, bac,cab. 输入d将显示adc.  那我们在何处去从集合里筛选呢,答案是从onQueryTextChange里监听输入文本的变化,每输入一个字符会去从集合中筛选出与输入匹配的字符串,最终显示在Listview里。好了原理分析完了,我们看具体如何实现:

2.1 布局


  
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent"
  4. xmlns:app="http://schemas.android.com/apk/res-auto"
  5. android:orientation="vertical">
  6. <android.support.v7.widget.Toolbar
  7. android:id="@+id/toolbar"
  8. style="@style/Toolbar.MyStyle"
  9. android:layout_width="match_parent"
  10. android:layout_height="wrap_content"
  11. android:background="?attr/colorPrimary"
  12. app:title="我的Tool"
  13. app:titleTextColor="@color/colorWhite"
  14. app:navigationIcon="@mipmap/gongzhong_fanhui"
  15. app:titleTextAppearance="@style/Toolbar.TitleText"
  16. >
  17. </android.support.v7.widget.Toolbar>
  18. <ListView
  19. android:layout_gravity="center_horizontal"
  20. android:divider="@color/colorPrimary"
  21. android:dividerHeight="0.3dp"
  22. android:id="@+id/lvAutoText"
  23. android:layout_width="300dp"
  24. android:layout_height="wrap_content">
  25. </ListView>
  26. </LinearLayout>

2.2 MainActivity.java代码


  
  1. package com.example.administrator.toolbarstudy;
  2. import android.graphics.Color;
  3. import android.os.Bundle;
  4. import android.support.v4.view.MenuItemCompat;
  5. import android.support.v7.app.AppCompatActivity;
  6. import android.support.v7.widget.SearchView;
  7. import android.support.v7.widget.SearchView.OnCloseListener;
  8. import android.support.v7.widget.SearchView.OnQueryTextListener;
  9. import android.support.v7.widget.Toolbar;
  10. import android.text.TextUtils;
  11. import android.util.Log;
  12. import android.view.KeyEvent;
  13. import android.view.Menu;
  14. import android.view.MenuItem;
  15. import android.view.View;
  16. import android.view.View.OnClickListener;
  17. import android.view.View.OnFocusChangeListener;
  18. import android.view.ViewGroup;
  19. import android.widget.Adapter;
  20. import android.widget.EditText;
  21. import android.widget.ImageView;
  22. import android.widget.LinearLayout;
  23. import android.widget.ListAdapter;
  24. import android.widget.ListView;
  25. import android.widget.TextView;
  26. import android.widget.Toast;
  27. import java.lang.reflect.Method;
  28. import java.util.ArrayList;
  29. import java.util.List;
  30. public class MainActivity extends AppCompatActivity {
  31. SearchView.SearchAutoComplete mSearchAutoComplete;
  32. SearchView mSearchView;
  33. MyAdapter adapter;
  34. String TAG = "MainActivity";
  35. ListView lvAutoText;
  36. List<String> namesCollection = new ArrayList<>();
  37. List<String> filterNames = new ArrayList<>();
  38. @Override
  39. protected void onCreate(Bundle savedInstanceState) {
  40. super.onCreate(savedInstanceState);
  41. setContentView(R.layout.activity_main);
  42. Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
  43. setSupportActionBar(toolbar);
  44. getSupportActionBar().setDisplayShowTitleEnabled(true);
  45. //返回键
  46. toolbar.setNavigationOnClickListener(new OnClickListener() {
  47. @Override
  48. public void onClick(View v) {
  49. clickBack();
  50. }
  51. });
  52. lvAutoText = this.findViewById(R.id.lvAutoText);
  53. namesCollection.add("abcd");
  54. namesCollection.add("adc");
  55. namesCollection.add("bbc");
  56. namesCollection.add("bac");
  57. namesCollection.add("cab");
  58. namesCollection.add("ccb");
  59. filterNames.addAll(namesCollection);
  60. adapter = new MyAdapter(filterNames,this);
  61. lvAutoText.setAdapter(adapter);
  62. }
  63. /**
  64. * 点击返回(包括手机物理按键)
  65. */
  66. public void clickBack()
  67. {
  68. if (mSearchAutoComplete.isShown()) {
  69. try {
  70. //如果搜索框中有文字,则会先清空文字,但网易云音乐是在点击返回键时直接关闭搜索框
  71. mSearchAutoComplete.setText("");
  72. Method method = mSearchView.getClass().getDeclaredMethod("onCloseClicked");
  73. method.setAccessible(true);
  74. method.invoke(mSearchView);
  75. } catch (Exception e) {
  76. e.printStackTrace();
  77. }
  78. } else {
  79. finish();
  80. }
  81. return;
  82. }
  83. /**
  84. * 让菜单同时显示图标和文字
  85. * @param featureId
  86. * @param menu
  87. * @return
  88. */
  89. @Override
  90. public boolean onMenuOpened(int featureId, Menu menu) {
  91. if (menu != null) {
  92. if (menu.getClass().getSimpleName().equalsIgnoreCase("MenuBuilder")) {
  93. try {
  94. Method method = menu.getClass().getDeclaredMethod("setOptionalIconsVisible", Boolean.TYPE);
  95. method.setAccessible(true);
  96. method.invoke(menu, true);
  97. } catch (Exception e) {
  98. e.printStackTrace();
  99. }
  100. }
  101. }
  102. return super.onMenuOpened(featureId, menu);
  103. }
  104. /**
  105. * 根据menu--main.xml加载菜单
  106. * @param menu
  107. * @return
  108. */
  109. @Override
  110. public boolean onCreateOptionsMenu(Menu menu) {
  111. getMenuInflater().inflate(R.menu.main, menu);
  112. MenuItem item = menu.findItem(R.id.action_search);
  113. mSearchView = (SearchView) MenuItemCompat.getActionView(item);
  114. //设置最大宽度mSearchView.setMaxWidth
  115. //通过id得到搜索框控件
  116. mSearchAutoComplete = (SearchView.SearchAutoComplete) mSearchView.findViewById(R.id.search_src_text);
  117. int color = this.getResources().getColor(R.color.colorWhite);
  118. mSearchAutoComplete.setTextColor(color);
  119. /*------------------ SearchView有三种默认展开搜索框的设置方式,区别如下: ------------------*/
  120. //1.设置搜索框直接展开显示。左侧有放大镜(在搜索框外) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
  121. //searchView.setIconifiedByDefault(false);
  122. //2.设置搜索框直接展开显示。左侧有放大镜(在搜索框中) 右侧无叉叉 有输入内容后有叉叉 不能关闭搜索框
  123. mSearchView.onActionViewExpanded();
  124. //3.false设置搜索框直接展开显示,true缩减为一个搜索图标。左侧有放大镜(在搜索框中) 右侧有叉叉 可以关闭搜索框
  125. mSearchView.setIconified(true);
  126. //SearchView用到了一个布局compat里面找到abc_search_view.xml,该里面的控件的属性
  127. //设置提交搜索按钮的图标
  128. //ImageView icon = (ImageView) mSearchView.findViewById(R.id.search_go_btn);
  129. //icon.setImageResource(R.mipmap.voice_search);
  130. //设置搜索文本的hint,与mSearchAutoComplete.setHint功能一样
  131. mSearchView.setQueryHint("搜索本地歌曲by code");
  132. //设置搜索文本框的字体
  133. mSearchAutoComplete.setHintTextColor(getResources().getColor(android.R.color.darker_gray));
  134. mSearchAutoComplete.setTextColor(getResources().getColor(android.R.color.background_light));
  135. mSearchAutoComplete.setTextSize(14);
  136. //修改搜索框控件间的间隔(这样只是为了在细节上更加接近网易云音乐的搜索框)
  137. LinearLayout search_edit_frame = (LinearLayout) mSearchView.findViewById(R.id.search_edit_frame);
  138. ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) search_edit_frame.getLayoutParams();
  139. params.leftMargin = 0;
  140. params.rightMargin = 0;
  141. search_edit_frame.setLayoutParams(params);
  142. //设置提交按钮是否可用(可见)
  143. mSearchView.setSubmitButtonEnabled(true);
  144. //searchView.setSuggestionsAdapter(adapter)
  145. //监听mSearchAutoComplete文本框焦点改变,例如点返回键后SearchView折叠mSearchAutoComplete失去了焦点时执行
  146. mSearchView.setOnQueryTextFocusChangeListener(new OnFocusChangeListener() {
  147. @Override
  148. public void onFocusChange(View v, boolean hasFocus) {
  149. Log.i(TAG,"onFocusChange");
  150. }
  151. });
  152. //searchView折叠监听,当前项目中点击返回键时执行
  153. mSearchView.setOnCloseListener(new OnCloseListener() {
  154. @Override
  155. public boolean onClose() {
  156. Log.i(TAG,"OnCloseListener");
  157. return false;
  158. }
  159. });
  160. 搜索图标按钮(打开搜索框的按钮)的点击事件
  161. mSearchView.setOnSearchClickListener(new OnClickListener() {
  162. @Override
  163. public void onClick(View v) {
  164. Toast.makeText(MainActivity.this, "点击了搜索图标按钮", Toast.LENGTH_SHORT).show();
  165. }
  166. });
  167. //监听文本变化,调用查询
  168. mSearchView.setOnQueryTextListener(new OnQueryTextListener() {
  169. //X右边的"搜索提交"按钮
  170. @Override
  171. public boolean onQueryTextSubmit(String text) {
  172. Toast.makeText(MainActivity.this, "点击了提交按钮:"+text, Toast.LENGTH_SHORT).show();
  173. return false;
  174. }
  175. @Override
  176. public boolean onQueryTextChange(String text) {
  177. // 文本改变的时候回调
  178. Log.i(TAG,"文本变化~~~~~"+text);
  179. List<String> queryResult = QueryNames(namesCollection,text);
  180. filterNames.clear();
  181. if(queryResult != null && queryResult.size() > 0)
  182. {
  183. filterNames.addAll(queryResult);
  184. }
  185. setAdapter(adapter);
  186. return false;
  187. }
  188. });
  189. return true;
  190. }
  191. /**
  192. * 从namesCollection集合中筛选与输入的文本想匹配的字符串
  193. * @param namesCollection 提示文本(关键字)的集合,一般存在服务器数据库
  194. * @param text 搜索框里输入的文本
  195. * @return
  196. */
  197. private List<String> QueryNames(List<String> namesCollection,String text) {
  198. if(TextUtils.isEmpty(text))
  199. {
  200. return null;
  201. }
  202. List<String> temp = new ArrayList<>();
  203. for(String name: namesCollection)
  204. {
  205. if(name.contains(text))
  206. {
  207. temp.add(name);
  208. }
  209. }
  210. return temp;
  211. }
  212. /**
  213. * 为ListView配置数据
  214. * @param adapter
  215. */
  216. public void setAdapter(ListAdapter adapter)
  217. {
  218. if(adapter == null)
  219. {
  220. adapter = new MyAdapter(filterNames,MainActivity.this);
  221. lvAutoText.setAdapter(adapter);
  222. }
  223. else
  224. {
  225. if(adapter instanceof MyAdapter)
  226. {
  227. ((MyAdapter)adapter).notifyDataSetChanged();
  228. }
  229. }
  230. return;
  231. }
  232. @Override
  233. public boolean onOptionsItemSelected(MenuItem item) {
  234. // Handle action bar item clicks here. The action bar will
  235. // automatically handle clicks on the Home/Up button, so long
  236. // as you specify a parent activity in AndroidManifest.xml.
  237. int id = item.getItemId();
  238. if (id == R.id.action_settings) {
  239. Toast.makeText(MainActivity.this,"您点击了设置",Toast.LENGTH_SHORT).show();
  240. return true;
  241. }
  242. else if(id == R.id.action_share)
  243. {
  244. Toast.makeText(MainActivity.this,"您点击了分享",Toast.LENGTH_SHORT).show();
  245. return true;
  246. }
  247. return super.onOptionsItemSelected(item);
  248. }
  249. /**
  250. * 按系统返回键与按标题栏上的返回产生相同的效果
  251. * @param keyCode
  252. * @param event
  253. * @return
  254. */
  255. @Override
  256. public boolean onKeyDown(int keyCode, KeyEvent event) {
  257. if(keyCode == KeyEvent.KEYCODE_BACK)
  258. {
  259. clickBack();
  260. return true;
  261. }
  262. return super.onKeyDown(keyCode, event);
  263. }
  264. }

我们主要看以下代码片段:


  
  1. public boolean onQueryTextChange(String text) {
  2. // 文本改变的时候回调
  3. Log.i(TAG,"文本变化~~~~~"+text);
  4. List<String> queryResult = QueryNames(namesCollection,text);
  5. filterNames.clear();
  6. if(queryResult != null && queryResult.size() > 0)
  7. {
  8. filterNames.addAll(queryResult);
  9. }
  10. setAdapter(adapter);
  11. return false;
  12. }

  
  1. /**
  2. * 从namesCollection集合中筛选与输入的文本想匹配的字符串
  3. * @param namesCollection 提示文本(关键字)的集合,一般存在服务器数据库
  4. * @param text 搜索框里输入的文本
  5. * @return
  6. */
  7. private List<String> QueryNames(List<String> namesCollection,String text) {
  8. if(TextUtils.isEmpty(text))
  9. {
  10. return null;
  11. }
  12. List<String> temp = new ArrayList<>();
  13. for(String name: namesCollection)
  14. {
  15. if(name.contains(text))
  16. {
  17. temp.add(name);
  18. }
  19. }
  20. return temp;
  21. }

  onQueryTextChange监听搜索文本框里的text变化,同时调用QueryNames函数从 集合中筛选出与text匹配的子集合,然后调用setAdapter展示子集合到ListView里。这样就模拟实现了自动提示文本,即一边输入一边提示“搜索关键字”的功能。就这么Easy!最终效果如图所示:

最后按照惯例给出源码下载地址:https://download.csdn.net/download/gaoxiaoweiandy/10789571

文章来源: blog.csdn.net,作者:冉航--小虾米,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/gaoxiaoweiandy/article/details/83999117

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。