模仿Airbnb的悬浮搜索框动画

观察Airbnb搜索框动画的原理

先看看airbnb的效果把。

看了几遍,发现是这么一个原理:

最初搜索框是展开的

稍微向下滑动一点,搜索框收起

当搜索框已经收起后再向下滑,搜索框一直保持收起状态

在向上滑动时,只有滑动到顶部,搜索框才展开

探索实现方法

觉得这个搜索框的展开与收起跟顶部有着很大的关系,到达顶部才会展开,离开顶部就收起。

查阅Api发现,Listview OnScrollListener onScroll中有这几个参数:

/**
         * Callback method to be invoked when the list or grid has been scrolled. This will be
         * called after the scroll has completed
         * @param view The view whose scroll state is being reported
         * @param firstVisibleItem the index of the first visible cell (ignore if
         *        visibleItemCount == 0)
         * @param visibleItemCount the number of visible cells
         * @param totalItemCount the number of items in the list adaptor
         */
        public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
                int totalItemCount);

firstVisibleItem这个参数就可以判断当前第一个显示的item是不是列表中第一个item。

而RecyclerView LinearLayoutManager中有这两个方法:

 public int findFirstVisibleItemPosition() {
        View child = this.findOneVisibleChild(0, this.getChildCount(), false, true);
        return child == null?-1:this.getPosition(child);
    }

    public int findFirstCompletelyVisibleItemPosition() {
        View child = this.findOneVisibleChild(0, this.getChildCount(), true, false);
        return child == null?-1:this.getPosition(child);
    }

所以可以肯定的是,不管是Listview还是RecyclerView,都能够很容易的判断当前是否在列表的顶部。

实现过程

了解了原理,找到啦响应的API,下面就是实现了。

鉴于大家现在使用更多的是RecyclerView,所以我就以RecycleView为例来实现这个功能。

判断何时收起展开

很简单,无非就是一个列表,实现了OnScrollListener,在onScrolled中判断当前显示的item中的第一个,是不是就是列表中的第一个,如果是,表明已经到达了顶部,展开搜索框;如果不是,表明离开了顶部,收起搜索框。

 isExpand = true;
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);
                int firstPosition = mLayoutManager.findFirstCompletelyVisibleItemPosition();
                if (firstPosition != 0 && isExpand) {
                    search.updateShow(false);
                    isExpand = false;
                }
                if (firstPosition == 0 && !isExpand) {
                    search.updateShow(true);
                    isExpand = true;
                }
            }
        });

这里增加了一个isExpand标志位,用处在于当搜索框已经收起了,而用户继续向下滑动时,不再收起搜索框,反之向上滑也是一样,只是不再重复而已。

执行收起展开

写到这里时发现一个问题

ios上的airbnb每次收起搜索框时:

从一个圆角矩形变成弧形边角的长柱形,然后长柱形水平缩短直到成为一个圆形。

ios上的airbnb每次展开搜索框时:

先从一个圆形变成正方形,然后正方形水平拉伸,成为一个圆角矩形。

从一个圆形渐变成为一个正方形,从一个正方形,渐变成为一个圆,这确实想不到好的办法。

跟设计师商量之后,改成了不用圆角矩形了,把圆角边直接改成弧形。

这样就靠一张9patch图就可以实现展开跟收起的效果,只需要做水平方向的scaleX变换就好。

收起展开遇到的问题

然而跟想象的不一样

虽然我指定了9patch的拉伸区域,但是发现根本跟你预想的两码事,你指定的9patch只能是view静态的一种变化,而这种动态的变化确实没有办法指定拉伸哪部分,或者是我不知道改用什么办法。

后来就打算使用障眼法了,一个圆形,一个圆柱形

最初时,圆形隐藏状态,圆柱形初始化为展开状态,使用9patch。

在收起时,渐渐的显示出圆形,scaleX圆柱形由大变小,然后隐藏圆柱形(因为圆柱形已经变形,只能隐藏掉)。

在展开时,隐藏圆形,scaleX圆柱形由小变大,由于圆柱形原本就是展开的,现在由收起恢复到展开,不会变形。

实现

 private void expandSearch() {

        circle.setVisibility(View.VISIBLE);
        ObjectAnimator anim1 = ObjectAnimator.ofFloat(circle, "alpha", 1f, 0f);
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(round, "alpha", 0f, 1f);
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(round, "scaleX", scale, 1f);
        round.setPivotX(0);
        AnimatorSet animSet2= new AnimatorSet();
        animSet2.play(anim1).with(anim2).with(anim3);
        animSet2.setDuration(100);
        animSet2.start();

    }

    private void closeSearch() {
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(round, "scaleX", 1f, scale);
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(circle, "alpha", 0f, 1f);
        circle.setVisibility(View.VISIBLE);
        ObjectAnimator anim4 = ObjectAnimator.ofFloat(round, "alpha", 1f, 0f);
        round.setPivotX(0);
        round.setPivotY(round.getHeight() / 2);
        AnimatorSet animSet1 = new AnimatorSet();
        animSet1.play(anim2).with(anim3).with(anim4);
        animSet1.setDuration(100);
        animSet1.start();
    }

就不贴出来全部的代码了,一会给出Github地址。

效果

注意

如果你使用的ListView,并且是可以下拉刷新的Listview,那么你要注意了,因为你下拉刷新如果使用的是addHeaderView,然后通过控制header的padding的形式,那么你会发现在下拉刷新时,这个搜索框会不停的收起展开。

为什么会这样呢?

其实想一下就能明白,在可以下拉刷新的Listvew中,header在一般情况下是隐藏状态,那么当前列表的顶部就是列表数据的第一个item,然而一旦下拉,header露出来后,列表的顶部就变成header了,所以就会出现问题。

只要需要在下拉刷新时,屏蔽掉搜索框的变化就可以了。

源码下载地址:

https://github.com/nicewarm/AirbnbSearchAnimation/tree/master

希望能帮到你。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-17 03:31:57

模仿Airbnb的悬浮搜索框动画的相关文章

html css 模仿小米官网搜索框

写网页效果,掌握html,css,唯一的捷径就是多模仿,多练习.小米官网的搜索框效果看似简单,实际写代码的时候才发现要掌握好多css知识才能完成效果.浮动.导航条.鼠标经过.定位.文字框效果实现.js效果实现等等.下面这段代码仅仅用html.css写出了基本的样子,js效果,鼠标经过.点击事件,光标定位效果都还没有实现. 效果原图见小米官网:http://www.mi.com 搜索效果切换图: 最终效果: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1

[iOS]过渡动画之高级模仿 airbnb

注意:我为过渡动画写了两篇文章:第一篇:[iOS]过渡动画之简单模仿系统,主要分析系统简单的动画实现原理,以及讲解坐标系.绝对坐标系.相对坐标系,坐标系转换等知识,为第二篇储备理论基础.最后实现 Mac 上的文件预览动画.第二篇:[iOS]过渡动画之高级模仿 airbnb,主要基于第一篇的理论来实现复杂的界面过渡,包括进入和退出动画的串联.最后将这个动画的实现部分与当前界面解耦,并封装为一个普适(其他类似界面也适用)的工具类. 这两篇文章将会带你学到如何实现下图 airbnb 首页类似的过渡动画

7款基于jquery的动画搜索框

无论是电商网站,还是媒体网,还是个人博客,每个网站都有属于自己个性化的搜索框.今天小编给大家带来7款基于jquery的动画搜索框.每个搜索框都采用了动画效果,一起看下效果图吧. 在线预览   源码下载 实现的代码. html代码: <h1> CSS Animated Search Boxes</h1> <p> (with occasional help from javascript to assign focus)</p> <div class=&q

饿了么 顶部搜索框下拉动画小效果

效果描述:当下拉的时候渐变产生对固定的搜索框 import React, { Component } from "react"; import { connect } from "react-redux"; import { Container, Header, Title, Content, Button, Icon, Left, Right, Body, FlatList, } from "native-base"; import { Dim

WPF—QQ界面(三):联系人搜索框和个性签名一栏的效果实现

由于过年回家,家里没网,好几个月没写了.昨晚刚回实验室,今天接着写. 首先分析搜索框和个性签名一栏的效果: 1.搜索框平常时框内有一行文字用来提示搜索的内容,当鼠标左键单击会使框内文字清空,并有光标闪烁: 2.个性签名一栏平常时也有一行文字,内容就是你的个性签名啦,当鼠标单击时,会使整个框的文字内容全选,此时可以随意更改你的个性签名. 3.两者还有一个共同特点:当鼠标移到搜索框和个性签名框,都会在鼠标的下方出现一行提示文字. 先贴搜索框的代码: 前台: <TextBox x:Name="t

android浮动搜索框的使用

引言 在我们的应用程序中经常需要提供搜索服务,比如搜索联系人, 搜索商品信息等等.我们可以自己在布局中自定义我们的搜索框,实现我们的搜索逻辑.但是还有一种更简单的方法:使用android系统给我们提供的搜索功能框架. 在android中,提供两种实现搜索功能的方式:search dialog 和 searchView. search dialog类似于普通的dialog,悬浮于我们的窗体之上.示例图如下: searchView通常被嵌套在我们的布局之中,最典型的案例就是在actionBar中使用

用jsonp实现搜索框功能的实现

用jsonp实现搜索框功能的实现 前面的话: 在上周本来想发一篇模仿必应搜索的界面.但是在准备写文章之前突然想到前面学习了ajax技术,在这里我也让我的页面有一种不需要手动刷新就能获取到数据.但是发现用前面的方法并不能获取到我想要的效果.无奈前几天电脑换系统,把之前的源码丢了(前面有个不好的习惯就是把最近在做的东西放桌面).今天想彻底把这个问题搞明白. 用jquery和ajax进行初步的尝试: (本代码是参考慕课网,搜索框制作视频制作,有关具体详情请参考视频.自己之前的代码找不到了,之前最先的想

3种精美Web前端搜索框展示(附源码)

1.  jQuery按栏目搜索框代码 赶紧来体验一下. 源码下载/  在线演示 2.  CSS3带凹槽搜索框 这个插件集成了一些非常好的 JavaScript 库,提供一个方便使用的文本动画插件. 源码下载/  在线演示 3.jQuery视频侧边隐藏搜索框 jquery实现的,会在当鼠标光标移动到接近(或通过)视口(viewport)的顶部的时候触发. 源码下载 /   在线演示 3种精美Web前端搜索框展示(附源码)

java简单的实现搜索框的下拉显示相关搜索功能

最近做了一个简单的搜索框下面下拉显示相关搜索的功能,有点模仿百度的下拉展示相关搜索 先上个展示图 : 点击进入演示地址,大家可以输入长点的搜索,点击搜索,再输入之前搜索词的前面部分,看是否能展示出来 搜索框相关搜索的展示很简单,就是根据你的搜索词,去数据库中匹配,是否有类似的搜索词存在,按照搜索词被搜索的次数进行排序显示出来 我设计的是每次搜索一个词,提交之后都会去数据库进行查询,看是否存在这个搜索词的搜索,若存在,则对数据库中的这个搜索词对象进行次数加1,不存在,则创建这个新搜索词对象,保存在