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

今天讲的就是一个很简单的具体开始时候遇到的需求,在标题栏中实现搜索功能,而且美工要求需要实现下面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的点击事件即可。

  1. 同样在是在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;
   }
  1. 在AndroidManifest.xml中对当前Activity中添加<meta>,声明该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"属性即可,加上该属性后,我们可以看到如下的布局了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,636评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,890评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,680评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,766评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,665评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,045评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,515评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,182评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,334评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,274评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,319评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,002评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,599评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,675评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,917评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,309评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,885评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,263评论 25 707
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,684评论 22 664
  • 直到《犯罪心理》第十三季都已经出了3集了,我才知道。本着铁粉的自我定位,立即放下了目前猛追不舍的《白夜追凶》和《无...
    差点叫冬梅的lily阅读 135评论 0 0
  • 我的妻: 见字如面。 许久不曾给你写字,博客也未更新。是的,答案依旧,生活过于忙碌,连黯然神伤的时间都要想方设法地...
    347fcf714e61阅读 390评论 0 0
  • 接触化妆行业多久,就认识小景老师多久。 第一次见她就被她的专业及执着深深地折服了。 先爆一组她的照片,然后进入今天...
    韩梅梅爱化妆阅读 531评论 0 3