简单实现android炫酷注册页面动画
来源:互联网 发布:杭州电信网络缴费地点 编辑:程序博客网 时间:2024/05/19 16:21
最近比较闲,再加上以前懒惰的习惯,决定尽量保持几天一篇博客,这次简单实现一下这个效果.其实主要是在网上看到了一篇博客,里面的效果比较炫,只是我觉得那个之前那个博客的动画有些地方的衔接没有做好,并且没有真正还原原设计,所以这里重新写了一下,简单的实现.原博客地址:http://www.jianshu.com/p/3ff40a06bef6,可以看看之前的实现效果以及原设计的效果。
录制效果有点渣.轻喷!
接上个gif图:
接下来就开始一步一步分析吧.
首先就是一个比较简单过场动画,具体什么是过场动画我就不多说了,不懂的详细了解一下我这里不讲原因,只讲讲如何实现。这里有2个activtiy,主要的东西其实都在第二个activity里.第一个页面就一个texteview不多说,详细说说第二个activity吧。
http://androidwing.net/index.php/172 这一篇我觉得很不错,大家可以看看。
既然是要实现过场动画,那首先第二个activity就要设置这样的属性
<item name="android:windowIsTranslucent">true</item><item name="android:windowBackground">@android:color/transparent</item>
其中SIGNUP这个TextView是一个共享元素,在2个activity中具有一样的属性.在跳转到第二个activity之前.我们需要穿一些第一个activity中Textview的属性值过去.如下图:
public void singUp(View view){ //获取view在屏幕中的位置以及宽高做为参数传到第二个activity int[] location = new int[2]; view.getLocationOnScreen(location); Intent intent = new Intent(this, HomeActivity.class); intent.putExtra("left", location[0]); intent.putExtra("top", location[1]); intent.putExtra("width", view.getWidth()); intent.putExtra("height", view.getHeight()); startActivity(intent); overridePendingTransition(0, 0); }
记住一点要调用overridePendingTransition(0, 0),关闭系统默认的跳转动画。
在第二个activity中接受到这些参数.
tv_sign_up.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { layout_sign_up.getViewTreeObserver().removeOnGlobalLayoutListener(this); startRevel(); } });
由于第二个acitivity中还有个success和一个下划线line.所以这里我把他们放在一个布局里了.
<RelativeLayout android:id="@+id/layout_sign_up" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_centerInParent="true"> <TextView android:id="@+id/tv_sign_up" android:layout_width="100dp" android:layout_height="30dp" android:layout_marginBottom="20dp" android:gravity="center" android:text="@string/sign_up" android:textColor="@android:color/white" /> <TextView android:id="@+id/tv_success" android:layout_width="100dp" android:layout_height="30dp" android:layout_marginBottom="20dp" android:gravity="center" android:text="@string/success" android:textColor="@android:color/white" android:visibility="invisible" /> <View android:id="@+id/line_view" android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginTop="35dp" android:background="@android:color/white" android:visibility="gone" /> </RelativeLayout>
好了,写好了最基本的东西就开始实现动画了。
第一步,获取到上一个activity传过来的参数,然后计算出上一个activity中textview的位置及大小(如果大小不一样大需要缩放一下)。
//拿到上一个activity中textview的属性 Intent intent = getIntent(); int left = intent.getIntExtra("left", 0); int top = intent.getIntExtra("top", 0); int width = intent.getIntExtra("width", 0); int height =intent.getIntExtra("height", 0); //获取到当前控件的属性 int[] location = new int[2]; layout_sign_up.getLocationOnScreen(location); int curX = location[0]; int curY = location[1]; //计算出差值 int transX = left - curX; int transY = top - curY; //把当前的控件先移动到上一个activity中textview所处的位置 layout_sign_up.setX(layout_sign_up.getX() + transX); layout_sign_up.setY(layout_sign_up.getY() + transY);
然后就可以实现圆弧的扩散动画和textview的平移回原位的动画了.
这里圆弧的实现我们适用一个第三方的库,在gradle添加如下依赖:
compile('com.github.ozodrukh:CircularReveal:2.0.1@aar') { transitive = true; }
具体使用:
int cx = left + width / 2; int cy = top - height / 2; float radius = (float) Math.hypot(reveal_layout.getWidth(), reveal_layout.getHeight()); Animator animator; if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ animator = ViewAnimationUtils.createCircularReveal(reveal_layout, cx, cy, 0, radius); animator.setDuration(700); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { reveal_layout.setVisibility(View.VISIBLE); } }); animator.start(); }
首先cx,cy是计算出当前矩形的中心点.(从中心点开始扩散),radius是计算出最终扩散的圆弧半径。由于是整个屏幕所以这里其实就是勾股定理的公式。
效果如下:
ViewAnimationUtils.createCircularReveal(reveal_layout, cx, cy, 0, radius);
这里的几个参数其实就很简单了. 参数的意思依次是要控散的控件(不知道描述清楚没有),扩散中心的x坐标,扩散中心的y坐标,刚开始扩散的圆弧半径,最终扩散的圆弧的半径.(如果不熟悉的可以下载源码更改一下参数看看效果就知道了,很简单的.)这里平移和扩散动画是一起执行的,平移动画如下:
Point start = new Point(layout_sign_up.getX(), layout_sign_up.getY()); Point end = new Point(curX, curY - getStatusBarHeight(this)); ValueAnimator animator1 = ValueAnimator.ofObject(new PointEvaluator(), start, end); animator1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Point curPoint = (Point) animation.getAnimatedValue(); layout_sign_up.setX(curPoint.getX()); layout_sign_up.setY(curPoint.getY()); } }); animator1.setDuration(700); animator1.start();
多说一句,这里我使用view.getLocationOnScreen这个方法,不知道为什么获取的位置有误,没有算上标题栏.所以导致平移的位置没有回到中心,所以我减去了标题栏的高度.curY - getStatusBarHeight(this),让其又往上平移了一段距离。效果如下:
组合在一起就是如下效果了:
接下来就是实现后面的效果了:文字进入和离开的动画,以及line线的缩放动画:
final ObjectAnimator lineAnim = ObjectAnimator.ofFloat(line, "ScaleX", 0f, 0.6f, 0.9f, 1f); lineAnim.setDuration(1500); lineAnim.setInterpolator(new DecelerateInterpolator()); line.setPivotX(0);
这里利用setPivotX(0)方法把线条执行动画的起始点改为0,动画将以该坐标为中线开始缩放,(默认为view的中线点),这样扩大动画只会向一个方向发生,即可实现线条延长效果。动画播放数值”0, 0.6f, 0.9f, 1.0f”并不是等差排列,还是越来越小,这样即可实现减速效果。
线条效果如下:可以看到最后一点是以很慢的速度完成的。
接下来是文字的进入和离开的动画了.都是比较简单的平移和透明度渐变动画,只不过组合再了一起.
//success进入 private void successEnter() { if(tv_success.getVisibility() != View.VISIBLE){ tv_success.setVisibility(View.VISIBLE); } //得到success的宽度,然后设置起始位置以及终点位置 ObjectAnimator sucessTran = ObjectAnimator.ofFloat(tv_success, "TranslationX", -measuredWidth*1.2f, -measuredWidth*0.2f, 0f); //透明度渐变从0-1 ObjectAnimator sucessAlpha = ObjectAnimator.ofFloat(tv_success, "Alpha", 0.1f, 0.8f, 1f); //此处同理 ObjectAnimator signupTran = ObjectAnimator.ofFloat(tv_sign_up, "TranslationX", 0, measuredWidth*0.7f, measuredWidth* 1.5f); signupTran.setInterpolator(new AccelerateInterpolator()); ObjectAnimator signupAplha = ObjectAnimator.ofFloat(tv_sign_up, "Alpha", 1.0f, 1.0f, 0.4f, 0f); AnimatorSet set = new AnimatorSet(); set.setDuration(1000); set.playTogether(sucessTran, sucessAlpha, signupTran, signupAplha); set.start(); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); handler.sendEmptyMessageDelayed(0, 800); } }); } private void singupEnter() { ObjectAnimator signupTran = ObjectAnimator.ofFloat(tv_sign_up, "TranslationX", -measuredWidth*1.2f, -measuredWidth*0.2f, 0f); ObjectAnimator signupAplha = ObjectAnimator.ofFloat(tv_sign_up, "Alpha", 0.1f, 0.8f, 1f); ObjectAnimator successTran = ObjectAnimator.ofFloat(tv_success, "TranslationX", 0, measuredWidth*0.7f, measuredWidth* 1.5f); successTran.setInterpolator(new AccelerateInterpolator()); ObjectAnimator successAlpha = ObjectAnimator.ofFloat(tv_success, "Alpha", 1.0f, 1.0f, 0.4f, 0f); AnimatorSet set = new AnimatorSet(); set.setDuration(1000); set.playTogether(signupTran, signupAplha, successTran, successAlpha); set.start(); set.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); handler.sendEmptyMessageDelayed(0, 1000); } }); }
上面的2个动画都是很简单的动画,这里就不多说了.以下是动画循环:
int index = 0; private void loopAnim() { if(index % 2 == 0){ successEnter(); }else{ singupEnter(); } index++; } private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); //此处模拟网络请求,5次之后执行最后一个背景收起的动画 if(index >= 5){ enterHome(); }else { loopAnim(); } } };
剩下 最后的背景收起动画我同样使用了属性动画,代码如下:
private void enterHome() { im.setVisibility(View.VISIBLE); rl_title.setVisibility(View.VISIBLE); scale_layout.setVisibility(View.VISIBLE); reveal_layout.setVisibility(View.GONE); layout_sign_up.setVisibility(View.GONE); ValueAnimator valueAnimator = ValueAnimator.ofInt(scale_layout.getHeight(), 0); valueAnimator.setInterpolator(new DecelerateInterpolator()); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { scale_layout.getLayoutParams().height = (int) animation.getAnimatedValue(); scale_layout.requestLayout(); } }); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(valueAnimator, ObjectAnimator.ofFloat(iv_me, "Alpha", 0.1f, 1.0f), ObjectAnimator.ofFloat(iv_menu, "Alpha", 0.1f, 1.0f)); animatorSet.setDuration(1200); animatorSet.start(); }
在属性动画中,我监听了addUpdateListener,这里的animation参数可以获取到当前改变的值:
animation.getAnimatedValue();当然变化的范围就是从layout的高度减小到0,所以这里我拿到改变的值,直接设置给layout的布局参数中的height相当于动态的改编其高度.(这个技巧其实很实用,我写的第一篇博客也实用到这个技巧)。最后就是对title的2个view进行透明度的渐变:
其实在平常的看到的很多例子里,有些看上去很炫的效果其实都是一些比较基本的东西组合起来的.我们平常写代码也是一样,都是用最基本的东西通过对代码不同的组合,以此来实现不同的需求,动画也是一样,最重要的就是要分析出来每个动画都是由什么方式实现的,最后加以组合。源码在这里:
https://github.com/wxkkwxxx/MyAnim
- 简单实现android炫酷注册页面动画
- MVC实现简单注册页面
- android中注册页面实现
- android 简单动画实现
- Android 动画简单实现
- Android开发-UI控件:实现登陆页面并跳转和简单的注册页面
- 超简单的登陆注册页面实现
- Storyboard学习五(简单注册页面实现)
- JavaScript 注册登录页面的简单实现
- android -简单注册登录页面应用
- 【Android初学者】超简单的注册页面,填写完整信息实现 跳转 和 传参
- Android实现简单移动动画
- Android登录注册页面实现分享
- 小KING教你做android项目(二)---实现登陆页面并跳转和简单的注册页面
- 小KING教你做android项目(二)---实现登陆页面并跳转和简单的注册页面
- 小KING教你做android项目(二)---实现登陆页面并跳转和简单的注册页面
- Android炫酷动画实现
- 简单注册页面
- MTK sensor 框架
- java-List去重得到的经验
- 软件测试使用到的网站
- 为tomcat制作sha-256自签名证书
- Ubiquitous Religions POJ
- 简单实现android炫酷注册页面动画
- Linux GPIO驱动
- (转)FFmpeg 基本用法
- 【图像处理】FujiFilm Tags
- 问题 : 分苹果【博弈】
- Linux一键安装web环境全攻略phpstudy版
- 【图像处理】DJI Tags
- Swig实现将C、C++编译成Python动态链接库
- Windows下Android Studio长时间停留在Building "Project Name" Gradle project info画面的解决方法