一直觉得bilibili的安卓客户端做的很不错,所以自己在项目中都会有意识或无意识地去模仿,最近觉得它的搜索框弹出收回的效果体验挺不错的,于是研究了一下模仿着做了一个:

(ps:模仿不是罪,罪过的是没有经过思考地抄袭)

bilibili搜索框效果图:

博主模仿版:

实现原理

这里的波纹动画需要使用的ViewAnimationUtils库来实现,但是该库是5.0以后才引入的,所以无法满足低版本。但是不用担心,已经有开源库为我们实现了低版本的动画,用法和ViewAnimationUtils一致。

这里首先要介绍一个开源库circularReveal,主要是提供了波浪式的展开和回缩动画,利用这个库提供的动画再自定义一下就很容易实现上面的效果了

有兴趣的朋友可以自动down下源码看一下:

CircularReveal libaray 源码下载

我这里就利用CircularReveal库,做了一个demo,就是上面的效果图的:

demo下载地址

整个搜索框是使用fragment实现的,弹出层是覆盖在activity上的一个fragment,具体搜索逻辑自己去实现,demo只提供出入场动画:

先贴出fragment的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/root"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><io.codetail.widget.RevealFrameLayout
        android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:layout_margin="7dp"><LinearLayout
            android:id="@+id/content"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><io.codetail.widget.RevealLinearLayout
                android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><LinearLayout
                    android:id="@+id/edit_lay"android:background="#ffffff"android:layout_width="match_parent"android:layout_height="wrap_content"><EditText
                    android:id="@+id/edit_search"android:layout_width="0dp"android:layout_height="40dp"android:layout_weight="1"android:ems="10"android:hint="search"android:inputType="textPersonName"android:layout_marginLeft="13dp"android:textColor="#333333"android:textColorHint="#cccccc"><requestFocus /></EditText><ImageView
                    android:id="@+id/img_search"android:padding="7dp"android:layout_width="40dp"android:layout_height="40dp"android:scaleType="fitXY"android:src="@drawable/icon_search" /></LinearLayout></io.codetail.widget.RevealLinearLayout><LinearLayout
                android:id="@+id/items"android:layout_width="match_parent"android:layout_height="400dp"android:background="#ffffff"android:orientation="vertical"android:paddingLeft="15dp"><TextView
                    android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="New Text"android:textColor="#333333" /><TextView
                    android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="New Text"android:textColor="#333333" /><TextView
                    android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="New Text"android:textColor="#333333" /><TextView
                    android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginTop="10dp"android:text="New Text"android:textColor="#333333" /></LinearLayout></LinearLayout></io.codetail.widget.RevealFrameLayout>
</LinearLayout>

布局很简单,根据自己需要更改,这里只是一个示例,要注意的一点就是:需要执行动画的视图必须有一个RevealLinearLayout或者RevealFrameLayout的父View。如上的布局,因为动画其实是由这个父View完成的
布局效果:

代码解析

首先,点击搜索按钮,弹出fragment并放入回退栈fragment:reveal中:

    @Overridepublic boolean onOptionsItemSelected(MenuItem item) {int id = item.getItemId();if (id == R.id.action_search) {getSupportFragmentManager().beginTransaction().add(android.R.id.content, new FragmentRevealExample(), "fragment_my").addToBackStack("fragment:reveal").commit();return true;}return super.onOptionsItemSelected(item);}

重点代码就在FragmentRevealExample中:

在fragment的onCreate()函数中添加一个绘制监听,在绘制渲染之前执行动画:

    edit_lay.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {@Overridepublic boolean onPreDraw() {//执行动画//......}});

下面是执行动画的主要代码:

 centerX = img_search.getLeft()+img_search.getWidth()/2;centerY = img_search.getTop()+img_search.getHeight()/2;SupportAnimator mRevealAnimator = ViewAnimationUtils.createCircularReveal(edit_lay, centerX, centerY, 20, PdUtil.hypo(edit_lay.getWidth(), edit_lay.getHeight()));mRevealAnimator.addListener(new SupportAnimator.AnimatorListener() {@Overridepublic void onAnimationStart() {edit_lay.setVisibility(View.VISIBLE);}@Overridepublic void onAnimationEnd() {new Handler().postDelayed(new Runnable() {@Overridepublic void run() {items.setVisibility(View.VISIBLE);edit_search.requestFocus();if (getActivity()!=null) {InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);imm.showSoftInput(edit_search, InputMethodManager.SHOW_IMPLICIT);}}}, 100);}@Overridepublic void onAnimationCancel() {}@Overridepublic void onAnimationRepeat() {}});mRevealAnimator.setDuration(200);mRevealAnimator.setStartDelay(100);mRevealAnimator.setInterpolator(new AccelerateDecelerateInterpolator());mRevealAnimator.start();

动画其实是模仿一个圆放大的过程,我们首要就有计算出圆心的坐标 centerX,centerY,就是放大镜的图标的中心点:

    centerX = img_search.getLeft()+img_search.getWidth()/2;centerY = img_search.getTop()+img_search.getHeight()/2;

然后通过library提供的ViewAnimationUtils的createCircularReveal方法获取一个动画对象执行mRevealAnimator,解释下createCircularReveal()方法的参数:

createCircularReveal(View view,int centerX,int centerY,float startRadius, float endRadius)
  • view:就是需要执行动画的对象,这里简单来说就是搜索框上的EditText,由于还有一个放大镜的图片,所以我用一个LinearLayout包围起来了,那我们需要的对象就是这个LinearLayout,这里要注意,要执行动画的话,那么选定的View必须有一个RevealLinearLayout或者RevealFrameLayout的父View,因为你选的View本身是没有动画效果的动画是由这两个拥有动画效果的父View来完成的。
  • centerX:动画中心点X坐标
  • centerY:动画中心点Y坐标
  • startRadius:动画开始时的圆半径
  • endRadius:动画结束时的圆半径

centerX和centerY已经计算出来了,startRadius我们默认20px,endRadius则取控件的最大宽度(对角线长度):

还记得勾股定理吗?

    public static float hypo(int a, int b){return (float) Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));}

动画配置完了,接下来就是动画监听器:

由于动画开始时会有闪动,所以在开始前隐藏需要动画的View,然后在开始时显示它,这样就不会有闪动了:

     @Overridepublic void onAnimationStart() {edit_lay.setVisibility(View.VISIBLE);}

在动画结束后延迟100毫秒,然后显示整个fragment,并弹出键盘:

     @Overridepublic void onAnimationEnd() {new Handler().postDelayed(new Runnable() {@Overridepublic void run() {items.setVisibility(View.VISIBLE);edit_search.requestFocus();if (getActivity()!=null) {InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);imm.showSoftInput(edit_search, InputMethodManager.SHOW_IMPLICIT);}}}, 100);}

最后设置动画时长和延迟,就可以执行动画了:

 mRevealAnimator.setDuration(200);mRevealAnimator.setStartDelay(100);mRevealAnimator.setInterpolator(new AccelerateDecelerateInterpolator());mRevealAnimator.start();

到这里,展开动画就完成了,接着是,回缩动画:

注意fragment并不能获取回退健点击事件,所以处理过程要放在activity中,fragment添加一个public的onBackPressed,在activity回退事件中获取fragment并调用fragment的自定义回退事件onBackPressed:

Activity:

    @Overridepublic void onBackPressed() {FragmentRevealExample fragment = (FragmentRevealExample) getSupportFragmentManager().findFragmentByTag("fragment_my");if(fragment!=null) {fragment.onBackPressed();}else {super.onBackPressed();}}

Fragment:
在fragment的onBackPressed中执行回缩动画:

    public boolean onBackPressed() {SupportAnimator mRevealAnimator = ViewAnimationUtils.createCircularReveal(content, centerX, centerY, 20, PdUtil.hypo(content.getWidth(), content.getHeight()));mRevealAnimator = mRevealAnimator.reverse();if (mRevealAnimator==null) return false;mRevealAnimator.addListener(new SupportAnimator.AnimatorListener() {@Overridepublic void onAnimationStart() {content.setVisibility(View.VISIBLE);}@Overridepublic void onAnimationEnd() {content.setVisibility(View.INVISIBLE);if (getActivity()!=null)getActivity().getSupportFragmentManager().popBackStack();}@Overridepublic void onAnimationCancel() {}@Overridepublic void onAnimationRepeat() {}});mRevealAnimator.setDuration(200);mRevealAnimator.setStartDelay(100);mRevealAnimator.setInterpolator(new AccelerateDecelerateInterpolator());mRevealAnimator.start();return true;}

回缩动画和开始动画类似,主要是调用了mRevealAnimator.reverse(),使动画方向反转,由放大变为回缩。注意在动画结束后把fragment实例从回退栈中移除(出栈):

getActivity().getSupportFragmentManager().popBackStack();

这样示例的部分就完成了。

如果需要弹出的键盘挤压布局视图的话。需要在AndroidManifest.xml给该Activity加上一个属性:

android:windowSoftInputMode="adjustResize"

如果不加的话,弹出的键盘是覆盖在视图之上的。是否需要这个效果看个人爱好了。

android开发游记:meterial design 使用circularReveal仿哔哩哔哩(bilibili)搜索框动画相关推荐

  1. android bilibili搜索框,仿bilibili搜索框效果(三句代码实现)

    SearchDialog 仿bilibili搜索框效果(只需要三句话即可实现) 先看预览图(转换后有一点点失真): 前言 1,支持搜索历史(已经做了数据库存储了) 2,基本与bilibili的搜索效果 ...

  2. 仿bilibili搜索框效果

    仿bilibili搜索框效果(只需要三句话即可实现) Usage With Gradle: compile 'com.wenwenwen888:searchbox:1.0.0' How to use ...

  3. 仿 bilibili 搜索框效果(三句代码实现)

    SearchDialog 项目地址:wenwenwen888/SearchDialog 简介:仿 bilibili 搜索框效果(三句代码实现) 更多:作者   提 Bug    标签: 搜索-搜索框- ...

  4. android开发常用工具类、高仿客户端、附近厕所、验证码助手、相机图片处理等源码...

    Android精选源码 android开发过程经常要用的工具类源码 Android类似QQ空间个人主页下拉头部放大的布局效果 Android高仿煎蛋客户端,Android完整项目 android帮你找 ...

  5. android开发常用工具类、高仿客户端、附近厕所、验证码助手、相机图片处理等源码

    Android精选源码 android开发过程经常要用的工具类源码 Android类似QQ空间个人主页下拉头部放大的布局效果 Android高仿煎蛋客户端,Android完整项目 android帮你找 ...

  6. android开发游记:仿支付宝余额数字累加滚动效果的实现

    支付宝更新9.0后,细心的朋友会发现新增了一个动画效果,就是进入我的钱包的时候,我的余额会有一段滚动显示的动画效果,比如说你有100块,余额就从0滚动到100,看到自己的钱在不断涨,让我们这些穷屌丝莫 ...

  7. Android开发-使用高德地图SDK实现仿钉钉打卡的功能

    前 言 LBS(基于地理位置服务)是当前移动互联网大部分应用不可或缺的功能,基于地理位置服务的Android平台的开发是主要用于Android系统作为载体,我们可以利用定位出的位置进行许多丰富多彩的操 ...

  8. android开发游记:集成百度定位SDK进行实时定位 获取当前城市地理信息

    定位功能在app开发中很常用,大多数企业都是不具备定位资质的,所有一般是通过接入第三方的sdk来进行定位,比较熟悉的有如:百度.高德.谷歌.腾讯等.而国内比较地图策划比较成熟的主要是百度和高德,这里就 ...

  9. Android开发学习之路-PopupWindow和仿QQ左滑删除

    这周作业,要做一个类似QQ的左滑删除效果的ListView,因为不想给每个item都放一个按钮,所以决定用PopupWindow,这里记录一下 先放一下效果图: 先说明一下这里面的问题: ①没有做到像 ...

最新文章

  1. C#从数据库导出数据[excel]
  2. 一个横空出世用于下载TCGA、GEO、ICGC数据于一体的工具
  3. 24. Swap Nodes in Pairs
  4. 今日工作总结及计划: 2022-02-14
  5. [ZJOI2007] 时态同步
  6. codeforces Labyrinth
  7. vue 实现瀑布流布局的 组件/插件总汇:vue-waterfall、vue-waterfall-easy、vue-virtual-collection、vue-grid-layout
  8. 6大设计原则之开闭原则
  9. ajax渲染的页面tp怎么赋值,【Vue】前后端不分离的情况下,TP5的视图页面中如何使用vue来接受和传递数据?...
  10. NG-ZORRO 7.3.0 发布,Ant Design 的 Angular 实现
  11. linux df 查看磁盘剩余空间,du查看文件占用多少空间,rm -rf 删除文件 mkdir -p创建目录(含父级)
  12. paip.SQL特殊字符转义字符处理
  13. 天宇优配|利好太多,写不下了!A股港股全线走高,股民嗨了
  14. vba set语句_零基础学VBA编程06:什么是变量?
  15. 61种u盘问题解决工具合集解决无法格式化,u盘写保护等问题。
  16. 三年java不会线程_Java后端开发三年多线程你都懂,问你异步编程你说你没听过???...
  17. 基于FPGA打地鼠游戏的设计与实现
  18. 试用了40+款日记APP,才知道好软件有多难求...
  19. ESP32开发2——新建项目
  20. 测试——水杯的测试用例

热门文章

  1. 浅谈CSS3动画的凌波微步--steps()
  2. jsp ul设置滚动条_定义设置滚动条
  3. Keras Sequential 模型
  4. 基于Web的疫情隔离区订餐系统
  5. fwrite和fread函数的用法小结(怎么样以二进制形式保存和读取文件)
  6. 编程之美里的挖雷游戏:
  7. z世代消费力白皮书_“Z世代”的世界 消费流里的商机
  8. 操作系统实践-预备知识-FAT12文件系统
  9. 【Android App 开发基础】
  10. OpenGL ES学习