Android中导航栏之搜索框SearchView

Toolbar系列文章导航

Android中导航栏之Toolbar的使用

Android中导航栏之溢出菜单OverflowMenu

Android中导航栏之搜索框SearchView

Android中导航栏之自定义导航布局

Android中导航栏之标签导航暨TabLayout用法

当我们希望我们的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" />

猜你喜欢

转载自blog.csdn.net/weixin_38322371/article/details/114131673