Android模仿知乎的回答详情页的动画效果

废话不多说,咱们第一篇文章就是模仿“知乎”的回答详情页的动画效果,先上个原版的效果图,咱们就是要做出这个效果

在实现之前,我们先根据上面的动画效果,研究下需求,因为gif帧数有限,所以不是很连贯,推荐你直接下载一个知乎,找到这个界面自己玩玩
☞当文章往上移动到一定位置之后,最上面的标题栏Bar和问题布局Title是会隐藏的,回答者Author布局不会隐藏
☞当文章往下移动移动到一定位置之后,原先隐藏的标题栏Bar和问题布局Title会下降显示
☞当文章往上移动的时候,下部隐藏的Tools布局会上升显示
☞当文章往下移动的时候,如果Tools布局是显示的,则隐藏
☞当标题栏Bar和问题布局Title下降显示的时候,Title是从Bar的下面出来的,有个遮挡的效果
☞当快速滑动内容到达底部的时候,隐藏的Tools会显示出来
☞当快速滑动内容到顶部的时候,隐藏的Bar和Title也会显示出来

不分析不知道,这样一个简单地效果,经过分析需要完成不少东西呢,那么下面根据要实现的需求,咱们分析一下解决方案。
    在做这种仿界面之前,我们可以使用ADT带的View Hierarchy工具看一下“知乎”原生是怎么实现的

从右边的分析图可以看出,知乎的这个界面,内容用的WebView,这很正常,因为用户的回答里面格式比较复杂,用WebView是最好的解决方案,而标题栏是一个VIew,是ActionBar还是自定义View呢,不得而知,下面是就是一个LinearLayout包了4个ToggleButton,布局很简单,我们没有WebView,所以使用ScrollView代替,上面的布局直接ImageView了,设置个src,模拟一个布局。
    其实布局很简单,咱们一个效果一个效果的来实现。
    首先是下面的Tools如何显示和隐藏呢?当然是用动画了!什么动画呢?能实现的有属性动画和帧动画,属性动画能够真实的改变View的属性,帧动画只是视觉上移动了,View的实际属性并不改变,这两种都可以,我们这里使用属性动画

/** * 显示工具栏 */ private void showTools() { ObjectAnimator anim = ObjectAnimator.ofFloat(img_tools, "y", img_tools.getY(), img_tools.getY() - img_tools.getHeight()); anim.setDuration(TIME_ANIMATION); anim.start(); isToolsHide = false; } /** * 隐藏工具栏 */ private void hideTools() { ObjectAnimator anim = ObjectAnimator.ofFloat(img_tools, "y", img_tools.getY(), img_tools.getY() + img_tools.getHeight()); anim.setDuration(TIME_ANIMATION); anim.start(); isToolsHide = true; }

那么什么时候调用呢?从上面的需求分析中,我们知道,用户手指下拉的时候,Tools显示,反之隐藏,那么我们就可以监听ScrollView的onTouch,判断手指方向,实现动画效果的调用

mScroller.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastY = event.getY(); break; case MotionEvent.ACTION_MOVE: float disY = event.getY() - lastY; //垂直方向滑动 if (Math.abs(disY) > viewSlop) { //是否向上滑动 isUpSlide = disY < 0; //实现底部tools的显示与隐藏 if (isUpSlide) { if (!isToolsHide) hideTools(); } else { if (isToolsHide) showTools(); } } break; } return false; } });

用变量isToolsHide放置代码重复调用。

下面的Tools的问题解决了,我们再看一下上面的布局动画如何来实现。上面的思路和下面一样,也是通过属性动画,完成位置的移动,移动的布局有Bar、Title和根布局。为什么答题人布局Author不移动呢?因为根布局必须移动,否则就会挡住下面的文字内容,根布局的移动会让子布局都跟着移动,所以只移动根布局即可。
    对了,为了更大范围的现实文本,“知乎”的WebView是占据整个布局的,其他布局都是在根布局FrameLayout里面,所以,在首次加载的时候,下面的文本在开头需要留出一定的间隔,防止被遮挡,当上面的布局隐藏之后,就没有问题了。
    在简单分析之后,我再给出实现的布局的代码

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/white" > <com.socks.zhihudetail.MyScrollView android:id="@+id/scroller" android:layout_width="match_parent" android:layout_height="wrap_content" > <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:textSize="16sp" android:textColor="@android:color/black" android:text="@string/hello_world"/> </com.socks.zhihudetail.MyScrollView> <FrameLayout android:id="@+id/ll_top" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/white" android:orientation="vertical" android:layout_gravity="top"> <ImageView android:id="@+id/img_author" android:layout_width="match_parent" android:layout_height="80dp" android:scaleType="fitXY" android:src="@drawable/bg_author"/> <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="55dp" android:text="为什么美国有那么多肌肉极其强大的肌肉男?" android:textSize="18sp" android:background="#DBDBDB" android:gravity="center|left" android:paddingLeft="15dp" android:paddingRight="15dp" android:paddingTop="5dp" android:paddingBottom="5dp" android:textColor="@android:color/darker_gray" /> <ImageView android:id="@+id/img_bar" android:layout_width="match_parent" android:layout_height="55dp" android:scaleType="fitXY" android:src="@drawable/bg_actionbar"/> </FrameLayout> <ImageView android:id="@+id/img_tools" android:layout_width="match_parent" android:layout_height="wrap_content" android:scaleType="fitXY" android:layout_gravity="bottom" android:src="@drawable/bg_bottom"/> </FrameLayout>

效果图如下,文本留了一些空行,保证不被遮挡。

有的同学看了上面的效果图可能会疑惑,这里为什么没有答题人的布局呢?
    其实是这样的,为了模拟上部的布局显示时,Title从Bar下面出现的效果,所以特意这样设计的。我试过用linearLayout实现,效果也是可以实现的,但是当Title往下移动显示的时候,会覆盖在Bar上面,这也很好理解,LinearLayout没有层次顺序,所以会遮挡。我试过View.bringToFront(),试图把Bar的布局提高层次,但是这样会导致布局的紊乱,在首次加载的时候,Bar会显示在最下面,是因为提高层次之后,Bar的布局重新计算,所以不按照LinearLayout的布局规则来了。无奈之下,换成了Framelayout,但是又出现了问题,Bar的高度可以设置,但是Title的高度会随着文本的增加而改变,这样一来,最下面Author的布局的位置就不能设置了,因为不知道距离上面多远,所以我们只能在代码里面动态的计算Bar和Title的高度,然后在界面加载的时候,动态的给Author的布局设置MargenTop,保证位置的正确。
    因为在onCreate里面,还没有开始View的绘制,所以得不到控件的真实高度,我们可以用下面的方法,获取这个时期的高度

//获取Bar和Title的高度,完成auther布局的margenTop设置 ViewTreeObserver viewTreeObserver = fl_top.getViewTreeObserver(); viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { if (!hasMeasured) { FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(FrameLayout .LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT); layoutParams.setMargins(0, img_bar.getHeight() + tv_title.getHeight(), 0, 0); img_author.setLayoutParams(layoutParams); hasMeasured = true; } return true; } });

获取了高度之后,我们就可以正确地设置位置了。但是,如果保证上面的布局随着我们的内容的移动,而改变现实状态呢?
    经过我手动直观测试,知乎的这个界面是根据一个固定的值,来改变显示状态的,因此,我们可以监听ScrollView的滑动距离,来判断。但是ScrollView并没有给我们这样一个监听器,咋办?重写!

/** * Created by zhaokaiqiang on 15/2/26. */ public class MyScrollView extends ScrollView { private BottomListener bottomListener; private onScrollListener scrollListener; public MyScrollView(Context context) { this(context, null); } public MyScrollView(Context context, AttributeSet attrs) { super(context, attrs); } protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); if (getScrollY() + getHeight() >= computeVerticalScrollRange()) { if (null != bottomListener) { bottomListener.onBottom(); } } if (null != scrollListener) { scrollListener.onScrollChanged(l, t, oldl, oldt); } } public void setBottomListener(BottomListener bottomListener) { this.bottomListener = bottomListener; } public void setScrollListener(onScrollListener scrollListener) { this.scrollListener = scrollListener; } public interface onScrollListener { public void onScrollChanged(int l, int t, int oldl, int oldt); } public interface BottomListener { public void onBottom(); } }

我们只需要重写onScrollChange()方法即可,在里面不光可以时时的得到位置的变化,还添加了一个BottomListener接口来监听滑动到底部的事件,写好之后就很简单了

mScroller.setBottomListener(this); mScroller.setScrollListener(this);
/** * 显示上部的布局 */ private void showTop() { ObjectAnimator anim1 = ObjectAnimator.ofFloat(img_bar, "y", img_bar.getY(), 0); anim1.setDuration(TIME_ANIMATION); anim1.start(); ObjectAnimator anim2 = ObjectAnimator.ofFloat(tv_title, "y", tv_title.getY(), img_bar.getHeight()); anim2.setInterpolator(new DecelerateInterpolator()); anim2.setDuration(TIME_ANIMATION + 200); anim2.start(); ObjectAnimator anim4 = ObjectAnimator.ofFloat(fl_top, "y", fl_top.getY(), 0); anim4.setDuration(TIME_ANIMATION); anim4.start(); isTopHide = false; } /** * 隐藏上部的布局 */ private void hideTop() { ObjectAnimator anim1 = ObjectAnimator.ofFloat(img_bar, "y", 0, -img_bar.getHeight()); anim1.setDuration(TIME_ANIMATION); anim1.start(); ObjectAnimator anim2 = ObjectAnimator.ofFloat(tv_title, "y", tv_title.getY(), -tv_title.getHeight()); anim2.setDuration(TIME_ANIMATION); anim2.start(); ObjectAnimator anim4 = ObjectAnimator.ofFloat(fl_top, "y", 0, -(img_bar.getHeight() + tv_title.getHeight())); anim4.setDuration(TIME_ANIMATION); anim4.start(); isTopHide = true; } @Override public void onBottom() { if (isToolsHide) { showTools(); } } @Override public void onScrollChanged(int l, int t, int oldl, int oldt) { if (t <= dp2px(TOP_DISTANCE_Y) && isTopHide && isAnimationFinish) { showTop(); Log.d(TAG, "显示"); } else if (t > dp2px(TOP_DISTANCE_Y) && !isTopHide && isAnimationFinish) { hideTop(); Log.d(TAG, "隐藏"); } }

我们只需要根据当前的位置,来实现布局的显示和隐藏就可以啦!

OK,这篇文章就到这里,希望对大家的学习有所帮助。

时间: 2024-09-29 00:09:44

Android模仿知乎的回答详情页的动画效果的相关文章

Android模仿知乎的回答详情页的动画效果_Android

 废话不多说,咱们第一篇文章就是模仿"知乎"的回答详情页的动画效果,先上个原版的效果图,咱们就是要做出这个效果     在实现之前,我们先根据上面的动画效果,研究下需求,因为gif帧数有限,所以不是很连贯,推荐你直接下载一个知乎,找到这个界面自己玩玩 ☞当文章往上移动到一定位置之后,最上面的标题栏Bar和问题布局Title是会隐藏的,回答者Author布局不会隐藏 ☞当文章往下移动移动到一定位置之后,原先隐藏的标题栏Bar和问题布局Title会下降显示 ☞当文章往上移动的时候,下部隐藏

安卓(android)仿电商app商品详情页按钮浮动效果_Android

1.效果图如下: 这效果用户体验还是很酷炫,今天我们就来讲解如何实现这个效果. 2.分析 为了方便理解,作图分析 如图所示,整个页面分为四个部分:      1.悬浮内容,floatView      2.顶部内容,headView      3.中间内容,与悬浮内容相同,middleView      4.商品详情展示页面,detailView 因为页面内容高度会超出屏幕,所以用Scrollview实现滚动,悬浮view与scrollview同级,都在一个帧布局或者相对布局中. 当y方向的滚动

安卓(android)仿电商app商品详情页按钮浮动效果

1.效果图如下: 这效果用户体验还是很酷炫,今天我们就来讲解如何实现这个效果. 2.分析 为了方便理解,作图分析 如图所示,整个页面分为四个部分: 1.悬浮内容,floatView 2.顶部内容,headView 3.中间内容,与悬浮内容相同,middleView 4.商品详情展示页面,detailView 因为页面内容高度会超出屏幕,所以用Scrollview实现滚动,悬浮view与scrollview同级,都在一个帧布局或者相对布局中. 当y方向的滚动距离小于中间的内容middleView到

Android仿“知乎”隐藏标题栏、回答详情页动画效果

转载请注明出处:http://blog.csdn.net/zhaokaiqiang1992      2014已经远去,2015年的目标很简单,就是继续熟悉Android的上层API,虽然偶尔会为了某个问题去研究下FrameWork的代码,但是对于我们这种新手来说,只有对上层的API用的熟练了,才能更好的往下研究原理.所以,今年的任务就是继续学习和研究Android的上层API的使用,顺便写一篇毕业论文,然后毕个业.     OK,从这篇开始,咱们就开始[凯子哥带你夯实应用层]系列,如果你有想要

Android编程实现ViewPager多页面滑动切换及动画效果的方法_Android

本文实例讲述了Android编程实现ViewPager多页面滑动切换及动画效果的方法.分享给大家供大家参考,具体如下: 一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式, 白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了,接下来我们就来实现它. 二.在开始前,我们先要认识一个控件,ViewPager.它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换. 这个附加包是and

Android编程实现ViewPager多页面滑动切换及动画效果的方法

本文实例讲述了Android编程实现ViewPager多页面滑动切换及动画效果的方法.分享给大家供大家参考,具体如下: 一.首先,我们来看一下效果图,这是新浪微博的Tab滑动效果.我们可以手势滑动,也可以点击上面的头标进行切换.与此同方式, 白色横条会移动到相应的页卡头标下.这是一个动画效果,白条是缓慢滑动过去的.好了,接下来我们就来实现它. 二.在开始前,我们先要认识一个控件,ViewPager.它是google SDk中自带的一个附加包的一个类,可以用来实现屏幕间的切换. 这个附加包是and

android 动画 不同-如何实现 android 顺序播放图片时,每张图片不同动画效果?

问题描述 如何实现 android 顺序播放图片时,每张图片不同动画效果? 已经定义了几种动画效果如 slide_out_left.xml. slide_out_right.xml. zoom_in.xml. zoom_out.xml. shake.xml等, 并实现了多张图片使用同一种动画效果(如shake)自动的顺序播放.现在想实现的效果大致是: picture1 执行slide_out_left, picture2 执行slide_out_right, picture3 执行zoom_in

Android实现游戏中的渐隐和渐现动画效果_Android

1实现渐隐的动画 在程序中实现可以通过如下方式 View view = new View(context);//执行动画的View AlphaAnimation aa = new AlphaAnimation(1.0f, 0.0f);//创建一个AlphaAnimation 对象,渐变从1->0 aa.setDuration(1500);//设置持续时间 aa.setFillAfter(true);//设置这个View最后的状态,由于是从1->0,所以最后的是消失状态(最后是看不到见这个Vie

Android自定义LinearLayout实现淘宝详情页

1.简单说明 淘宝详情页就不用我一一介绍了,昨天逛淘宝看到这个效果时,让我想起了去年刚学习Android只会使用现成的时候,当时在网上找了一个这种效果的使用了,并不懂怎么实现的.现在就看到一种效果就想自己实现一下,我想这就是刚接触某个知识时的好奇心吧 说走咱就走啊,本文只是介绍一种实现思路,网上也已经有了很多种实现方式,有问题请指正 效果图(我有很用心的找美女图的) 2.实现思路 继承LinearLayout,设置方向为垂直 控件中有两个ScrollView,至于为什么要使用ScrollView