项目需求讨论-标题栏上的搜索功能

今天讲的就是一个很简单的具体开始时候遇到的需求,在标题栏中实现搜索功能,而且美工要求需要实现下面GIF图的效果,我就实现了下,可能不是最好的,有哪里可以更方便请大家指出。正好仔细的讲解了下SearchView和Toolbar。希望大家看看我哪里是不是讲错了。哈哈。

1.先抛开搜索功能,我们看如何单纯实现下图的标题栏的界面:

标题栏

因为我平常项目中的标题栏使用的是Toolbar。当然大家在这个需求上面,用个其他类型的ViewGroup也是一样的。大家知道,Toolbar也是继承ViewGroup的,

public class Toolbar extends ViewGroup {

}复制代码

所以使用方法也是和一般的ViewGroup一样。

<android.support.v7.widget.Toolbar
        android:id="@+id/common_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/colorPrimary">

    <TextView
        android:id="@+id/tool_bar_choose"
        style="@style/TabTitleStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="待审批" />

    <ImageView
        android:id="@+id/start_search"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:src="@drawable/search_icon" />    


</android.support.v7.widget.Toolbar>复制代码

没错,我们就是直接在Toolbar中放置子元素,为了把标题TextView放置在正中间,使用android:layout_gravity="center",然后因为搜索按钮是在右边,对ImageView使用android:layout_gravity="right"

这时候有人会问了,那左边的返回按钮呢。怎么没写在布局中。 因为返回按钮有二种方式来进行处理显示,我们分别来说明:

  1. 在Activity中写上代码: Toolbar toolbar = (Toolbar) findViewById(R.id.common_toolbar); if(toolbar != null){ toolbar.setNavigationIcon(R.drawable.toolbar_back_icon); toolbar.setNavigationOnClickListener(v -> finish()); }复制代码 在Activity中获取到了Toolbar的对象,然后设置Navigation图标及Navigation的点击事件即可。
  2. 同样在是在Activity中写上代码: //先让返回箭头出现 Toolbar toolbar = (Toolbar) findViewById(R.id.common_toolbar); setSupportActionBar(toolbar); ActionBar bar = getSupportActionBar(); bar.setDisplayHomeAsUpEnabled(true);复制代码 这时候出现的返回箭头是系统原生的,是这样的:

跟我们原来的需求的返回图标不同,所以我们也有二种方法来进行修改:

  1. 在我们引入的Appbar的theme中添加一个Item,将设计师给我们的图放进去 <item name="android:homeAsUpIndicator">@drawable/web_detail_back</item>
  2. 在我们的Toolbar中添加属性 app:navigationIcon="@drawable/web_detail_back" 记得要在根布局中添加xmlns:app="http://schemas.android.com/apk/res-auto"

我们添加了返回图标后,我们就需要给他点击事件,这里也有二种实现方式:

  1. 覆写onOptionsItemSelected方法:@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case android.R.id.home: finish(); break; } return true; }复制代码
  2. 在AndroidManifest.xml中对当前Activity中添加,声明该Activity的父Activity是哪个,然后按返回的时候就跳到那个父Activity中。<activity android:name=".modules.view.activity.ApproveActivity"> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".modules.view.activity.LoginActivity" /> </activity>复制代码

2.实现搜索框功能

我们上面说过Toolbar实际上就是一个ViewGroup,所以我就想到可以让Toolbar中包含一个FragmentLayout,然后在这个上面的标题的标题及搜索图标按钮上面,覆盖了一层我们要的SearchView,然后默认是隐藏的,点击搜索图标按钮后让SearchView显示就可以了。其实的确很简单。

我们的布局代码就变成了:(ps:因为我用的是百分比布局,所以Framelayout变为了PercentFrameLayout,LinearLayout变为了PercentLinearLayout)

<android.support.v7.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@color/colorPrimary">

    <android.support.percent.PercentFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <TextView
            android:id="@+id/tool_bar_choose"
            style="@style/TabTitleStyle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:drawablePadding="10dp"
            android:drawableRight="@drawable/more_unfold"
            android:text="待审批" />

        <ImageView
            android:visibility="gone"
            android:id="@+id/start_search"
            android:layout_width="40dp"
            android:layout_height="match_parent"
            android:layout_gravity="right"
            android:scaleType="center"
            android:src="@drawable/search_icon" />

        <com.chint.pay.widget.PercentLinearLayout
            android:id="@+id/search_group"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center_vertical"
            android:visibility="gone"
            >

            <android.support.v7.widget.SearchView
                android:id="@+id/search_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/search_view_background"
                app:layout_heightPercent="70%"
                android:queryHint="请输入姓名或者手机号"
                app:layout_widthPercent="85%" />

            <TextView
                android:id="@+id/cancel_search"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:text="取消"
                android:textColor="@android:color/white"
                android:textSize="14sp" />

        </com.chint.pay.widget.PercentLinearLayout>
    </android.support.percent.PercentFrameLayout>

</android.support.v7.widget.Toolbar>复制代码

好的,看布局代码,就知道在第一步中的标题栏的布局的上面,覆盖了一层横向布局,用来显示SearchView和取消按钮,该界面默认是隐藏的,只有当按了搜索图标按钮,再让这个横向布局显示,盖在上面,(当然同时也可以让原来的标题和搜索图标按钮隐藏)。


这本来是我们想要的效果,但是当我运行了代码后,我看到生成的界面是这样的:

原来,Toolbar自带的左边的按钮,是默认先占了它的位置,然后剩下的面积再是放我们自己定义的FrameLayout,所以我们的FrameLayout总体就先往右边偏移了。这时候又因为我们的标题是FrameLayout的中间,所以标题也整体往右边便宜了。那岂不是都不能实现了??该怎么处理呢??答案当然是有方法处理。(这B装的我好累。)


我们可以直接在ToolBar中,自己在左边添加一个ImageView,然后图片设为返回的图标,然后给这个ImageView添加点击事件就OK了。所以我们在上面的布局代码中的PercentFrameLayout中再添加一个ImageView元素:

<android.support.percent.PercentFrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/tool_back"
        android:layout_width="30dp"
        android:scaleType="center"
        android:layout_marginLeft="-5dp"
        android:layout_height="match_parent"
        android:src="@drawable/toolbar_back_icon"
        android:layout_gravity="center_vertical"
        />

    .....
    .....
    .....
    .....

</android.support.percent.PercentFrameLayout>复制代码

这下我们的布局整个都实现了。只要对相应的按钮实现点击事件,控制相关控件的显示及隐藏即可。


3.SearchView的显示及键盘弹出

SearchView基础我就不重复了,先附上其他大神写的SearchView的相关基础知识: 搜索框(SearchView)的功能与用法 详细解读Android中的搜索框(三)—— SearchView

我们看到,在GIF图中,当我点击了搜索图标按钮的时候,SearchView 的Visible设为显示状态,同时键盘出现,然后当我点击取消按钮的时候,SearchView 的Visible设为隐藏状态,同时键盘消失,SearView的显示和隐藏这个大家都只要,只要调用SearchView.setVisibility方法即可。那键盘呢,其实不用特意去设定键盘的弹出及隐藏。 我这边是使用了SearchView的onActionViewCollapsed及onActionViewExpanded方法

onActionViewExpanded方法: 初始SearchView是否已经是展开的状态 写上此句后searchView初始展开的,也就是是可以点击输入的状态,如果不写,那么就需要点击下放大镜,才能展开出现输入框。 同理,onActionViewCollapsed正好相反。

因为设置他们的展开与不展开,正好会自动调用键盘的显示和隐藏。所以我们这里正好调用这二个方法:

switch (view.getId()) {
    case R.id.start_search:
        searchGroup.setVisibility(View.VISIBLE);
        startSearch.setVisibility(View.GONE);
        searchView.onActionViewExpanded();
        break;

    case R.id.cancel_search:
        searchGroup.setVisibility(View.GONE);
        startSearch.setVisibility(View.VISIBLE);
        searchView.onActionViewCollapsed();
        break;
}复制代码

这里还要对SearchView 调用:

searchView.setIconifiedByDefault(false);复制代码

未调用setIconifiedByDefault(false)

调用setIconifiedByDefault(false)

从上面图片可以看到,设为false和true的区别在于输入的光标的显示位置,如果为true,设光标在放大镜的前面,而且,当你输入文字后,放大镜也会不见,设为false,则光标在放大镜后面,输入文字,放大镜也不会消失。

同时记得对SearchView设置搜索事件:

searchView.setOnQueryTextListener(this);复制代码

Activity 实现SearchView.OnQueryTextListener接口,覆写相关方法:

@Override
public boolean onQueryTextSubmit(String query) {
    Toast.makeText(aty, "你搜索了:" + query, Toast.LENGTH_SHORT).show();
    return false;
}

@Override
public boolean onQueryTextChange(String newText) {
    return false;
}复制代码

这样就结束了。哈哈,希望大家不要乱喷我。有错请留言。O(∩_∩)O


补充1:

感谢大家下面留言指出错误,说是标题并没有居中,我用AS的布局工具看了,没有居中的原因如下图所示:

Toolbar的自己本身左边padding的一部分值,所以我们只需要给Toolbar加上 app:contentInsetStart="0dp"属性即可,加上该属性后,我们可以看到如下的布局了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Python小屋

Python+tkinter动态创建与销毁组件小案例

本文代码演示了如何在tkinter窗体上动态创建组件以及销毁组件的方法。 import tkinter import tkinter.messagebox im...

6486
来自专栏我就是马云飞

随手一写就是一个侧滑关闭activity

实现原因 其实侧滑关闭activity在网上也有大量的文章去介绍他,我也有去看,要么是代码实在太多看不下去,要么就是跑了项目没有反应的。唯一的方法还是自己随手鲁...

2526
来自专栏分享达人秀

两分钟掌握数值选择器NumberPicker

上一期学习了日期选择器DatePicker和时间选择器TimePicker,是不是感觉非常简单,本期继续来学习数值选择器NumberPicker 。 一...

2166
来自专栏我就是马云飞

无需自定义View,彻底解放shape,selector吧

作为一个android程序员,对于shape、selector这两个标签一定不陌生。每当UI设计师给我们设计出一个个button背景的时候,我们就需要去draw...

1022
来自专栏分享达人秀

自定义ProgressBar打造酷炫进度条

Android系统默认的ProgressBar往往都不能满足实际开发需要,一般都会开发者自定义ProgressBar。 在Android开发中,...

1.1K5
来自专栏项勇

笔记82 | 在ScrollView中加载 需要全部展开ListView

wifi列表需要动态加载更新 所有的wifi列表需要全部展开显示 直接把listView放到一个scrollview中放的话,listView只会显示一个ite...

561
来自专栏学海无涯

Android开发之SwipeRefreshLayout实现下拉刷新

简介 SwipeRefreshLayout是Google官方推出的一款下拉刷新组件,位于v4兼容包下,android.support.v4.widget.Swi...

3224
来自专栏向治洪

关于Android PullTorefreshScrollview回到顶部实例

列表滑动下面显示按钮,点击按钮回到顶部的功能,一般scrollview会有滑动监听的事件,通过setOnScrollChangeListener()滑动监听滑动...

2099
来自专栏向治洪

Android优化之Hardware Layer

项目中越来越多的动画,越来越多的效果导致了应用性能越来越低。该如何提升。 ###简介 在View播放动画的过程中每一帧都需要被重绘。如果使用view l...

1965
来自专栏一直在跳坑然后爬坑

环形布局CircleLayout效果图用法链接

1.可以直接在布局文件中进行布局,类似LinearLayout,但是这里不需要关心布局方式,会自动将布局中的所有子view均匀分布到中心点四周,这里你可以设置自...

1932

扫码关注云+社区

领取腾讯云代金券