Toolbar系列文章导航
当我们希望我们的Toolbar带有搜索功能的时候,我们可以按照下面的步骤来进行编写。
1.创建menu
在我们的res-->menu包下创建menu_search.xml类,并写入如下代码
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" >
<item
android:id="@+id/menu_search"
android:orderInCategory="1"
android:icon="@mipmap/ic_search"
app:showAsAction="ifRoom"
android:title="搜索"
app:actionViewClass="androidx.appcompat.widget.SearchView" />
<item
android:id="@+id/menu_refresh"
android:orderInCategory="2"
android:icon="@mipmap/ic_refresh"
app:showAsAction="never"
android:title="刷新"/>
<item
android:id="@+id/menu_about"
android:orderInCategory="8"
android:icon="@mipmap/ic_about"
app:showAsAction="never"
android:title="关于"/>
<item
android:id="@+id/menu_quit"
android:orderInCategory="9"
android:icon="@mipmap/ic_quit"
app:showAsAction="never"
android:title="退出"/>
</menu>
2.引入我们需要的图片资源,这里主要是溢出菜单中用到的图片和我们的返回图片。
3.在res-->xml中创建设置搜索框样式的代码
searchable.xml
<searchable xmlns:android="http://schemas.android.com/apk/res/android"
android:label="@string/app_name"
android:hint="@string/please_input"
android:inputType="text"
android:searchButtonText="@string/search" />
4.添加字符串资源
<string name="please_input">请输入</string>
<string name="search">搜索</string>
5.创建一个搜索结果页,也就是点击软键盘上的开始按钮后跳转到的页面
SearchResultActvity.java
@SuppressLint("SetTextI18n")
public class SearchResultActvity extends AppCompatActivity {
private static final String TAG = "SearchResultActvity";
private TextView tv_search_result;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search_result);
// 从布局文件中获取名叫tl_result的工具栏
Toolbar tl_result = findViewById(R.id.tl_result);
// 设置工具栏的背景
tl_result.setBackgroundResource(R.color.blue_light);
// 设置工具栏的标志图片
tl_result.setLogo(R.mipmap.ic_launcher);
// 设置工具栏的标题文字
tl_result.setTitle("搜索结果页");
// 设置工具栏的导航图标
tl_result.setNavigationIcon(R.mipmap.ic_back);
// 使用tl_result替换系统自带的ActionBar
setSupportActionBar(tl_result);
tv_search_result = findViewById(R.id.tv_search_result);
// 执行搜索查询操作
doSearchQuery(getIntent());
}
// 解析搜索请求页面传来的搜索信息,并据此执行搜索查询操作
private void doSearchQuery(Intent intent) {
if (intent != null) {
// 如果是通过ACTION_SEARCH来调用,即为搜索框来源
if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
// 获取额外的搜索数据
Bundle bundle = intent.getBundleExtra(SearchManager.APP_DATA);
String value = bundle.getString("hi");
// 获取实际的搜索文本
String queryString = intent.getStringExtra(SearchManager.QUERY);
tv_search_result.setText("您输入的搜索文字是:"+queryString+", 额外信息:"+value);
}
}
}
}
activity_search_result.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/tl_result"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_search_result"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:textColor="#000000"
android:textSize="17sp" />
</LinearLayout>
6.添加颜色资源,这个主要是在结果页用到了
<color name="blue_light">#aaaaff</color>
7.接着将我们添加的结果页配置到AndroidManifest.xml中,和平时配置不一样,大家注意一下
<activity android:name=".SearchResultActvity">
<intent-filter>
<action android:name="android.intent.action.SEARCH"/>
</intent-filter>
<meta-data android:name="android.app.searchable" android:resource="@xml/searchable"/>
</activity>
8.在显示搜索框的页面添加代码,如下
public class MainActivity extends AppCompatActivity {
private SearchView.SearchAutoComplete sac_key; // 声明一个搜索自动完成的编辑框对象
private String[] hintArray = {"iphone", "iphone8", "iphone8 plus", "iphone7", "iphone7 plus"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 从布局文件中获取名叫tl_head的工具栏
Toolbar tl_head = findViewById(R.id.tl_head);
// 设置工具栏左边的导航图标
tl_head.setNavigationIcon(R.mipmap.ic_back);
// 设置工具栏的标题文本
tl_head.setTitle("工具栏页面");
// 设置工具栏的标题文字颜色
tl_head.setTitleTextColor(Color.RED);
tl_head.setTitleMargin(0,0,0,0);
// 设置工具栏的背景
tl_head.setBackgroundResource(R.color.blue_light);
// 使用tl_head替换系统自带的ActionBar
setSupportActionBar(tl_head);
// 给tl_head设置导航图标的点击监听器
// setNavigationOnClickListener必须放到setSupportActionBar之后,不然不起作用
tl_head.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish(); // 结束当前页面
}
});
}
// 根据菜单项初始化搜索框
@SuppressLint("RestrictedApi")
private void initSearchView(Menu menu) {
MenuItem menuItem = menu.findItem(R.id.menu_search);
// 从菜单项中获取搜索框对象
SearchView searchView = (SearchView) menuItem.getActionView();
// 设置搜索框默认自动缩小为图标
searchView.setIconifiedByDefault(getIntent().getBooleanExtra("collapse", true));
// 设置是否显示搜索按钮。搜索按钮只显示一个箭头图标,Android暂不支持显示文本。
// 查看Android源码,搜索按钮用的控件是ImageView,所以只能显示图标不能显示文字。
searchView.setSubmitButtonEnabled(true);
// 从系统服务中获取搜索管理器
SearchManager sm = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
// 创建搜索结果页面的组件名称对象
ComponentName cn = new ComponentName(this, SearchResultActvity.class);
// 从结果页面注册的activity节点获取相关搜索信息,即searchable.xml定义的搜索控件
SearchableInfo info = sm.getSearchableInfo(cn);
if (info == null) {
return;
}
// 设置搜索框的可搜索信息
searchView.setSearchableInfo(info);
// 从搜索框中获取名叫search_src_text的自动完成编辑框
sac_key = searchView.findViewById(R.id.search_src_text);
// 设置自动完成编辑框的文本颜色
sac_key.setTextColor(Color.WHITE);
// 设置自动完成编辑框的提示文本颜色
sac_key.setHintTextColor(Color.WHITE);
// 给搜索框设置文本变化监听器
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
// 搜索关键词完成输入
public boolean onQueryTextSubmit(String query) {
return false;
}
// 搜索关键词发生变化
public boolean onQueryTextChange(String newText) {
doSearch(newText);
return true;
}
});
Bundle bundle = new Bundle(); // 创建一个新包裹
bundle.putString("hi", "hello"); // 往包裹中存放名叫hi的字符串
// 设置搜索框的额外搜索数据
searchView.setAppSearchData(bundle);
}
// 自动匹配相关的关键词列表
private void doSearch(String text) {
if (text.indexOf("i") == 0) {
// 根据提示词数组构建一个数组适配器
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
R.layout.search_list_auto, hintArray);
// 设置自动完成编辑框的数组适配器
sac_key.setAdapter(adapter);
// 给自动完成编辑框设置列表项的点击监听器
sac_key.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// 一旦点击关键词匹配列表中的某一项,就触发点击监听器的onItemClick方法
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
sac_key.setText(((TextView) view).getText());
}
});
}
}
@Override
public boolean onMenuOpened(int featureId, Menu menu) {
// 显示菜单项左侧的图标
setOverflowIconVisible(featureId, menu);
return super.onMenuOpened(featureId, menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// 从menu_search.xml中构建菜单界面布局
getMenuInflater().inflate(R.menu.menu_search, menu);
// 初始化搜索框
initSearchView(menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) { // 点击了工具栏左边的返回箭头
finish();
} else if (id == R.id.menu_refresh) { // 点击了刷新图标
Toast.makeText(this,"刷新了",Toast.LENGTH_SHORT).show();
return true;
} else if (id == R.id.menu_about) { // 点击了关于菜单项
Toast.makeText(this, "这个是工具栏的演示demo", Toast.LENGTH_LONG).show();
return true;
} else if (id == R.id.menu_quit) { // 点击了退出菜单项
finish();
}
return super.onOptionsItemSelected(item);
}
// 显示OverflowMenu的Icon
public static void setOverflowIconVisible(int featureId, Menu menu) {
// ActionBar的featureId是8,Toolbar的featureId是108
if (featureId % 100 == Window.FEATURE_ACTION_BAR && menu != null) {
if (menu.getClass().getSimpleName().equals("MenuBuilder")) {
try {
// setOptionalIconsVisible是个隐藏方法,需要通过反射机制调用
Method m = menu.getClass().getDeclaredMethod(
"setOptionalIconsVisible", Boolean.TYPE);
m.setAccessible(true);
m.invoke(menu, true);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
布局文件如下
<?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">
<androidx.appcompat.widget.Toolbar
app:contentInsetStartWithNavigation="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tl_head"/>
</LinearLayout>
9.最后我们需要一个输入提示下拉的样式
search_list_auto.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:singleLine="true"
android:ellipsize="marquee"
android:textSize="17sp"
android:textColor="@android:color/black" />