失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > android打印动画 Android 中的转场动画及兼容处理

android打印动画 Android 中的转场动画及兼容处理

时间:2021-12-01 03:09:26

相关推荐

android打印动画 Android 中的转场动画及兼容处理

Android 中的动画有很多,除了在一个界面上使用帧动画、属性动画将一个或多个 View 进行动画处理以外,还可以用于两个界面之间过渡、跳转。在 Android 5.0 之前,我们已经有了 overridePendingTransition() 方法来实现一些转场效果。然而,在 Android 5.0 以后,转场效果更加炫酷。 比如下面的动画:

本篇文章,主要就是解说如何实现上述的效果。主要内容包括:

o Android 5.0+ 的转场动画

o Android 4.X 模拟实现 Android 5.0+ 转场效果。

Android 5.0+ 中的转场动画

实现转场动画只需三步:

o 在res/目录下创建transition文件夹,在该文件夹下定义界面转场动画和共享元素的动画。

o 在res/value/style文件中为每个 Activity 指定转场动画的 style ,并在AndroidManifest.xml文件中为每个 Activity 设置对应的android:theme。

o 在 Activity 调用startActivity()切换动画前,使用ActivityOptionsCompat来创建转场动画时的共享对象。

下面就来对这三步进行详细讲解。

定义转场动画

在res/目录下创建了transition资源文件夹后,就可以在该文件夹下对每一种动画进行定义。

一般来说,对 Activity 定义一个过渡动画可以写成下面的形式:123456

其中是动画效果的名称,Android 5.0(API 级别 21)支持这些进入与退出转换:

o 分解(explode):从场景中心移入或移出视图。

o 滑动(slide):从场景边缘移入或移出视图。

o 淡入淡出(fade):通过调整透明度在场景中增添或移除视图。

而每一种动画效果,都有额外的属性。比如滑动 slide,可以使用android:slideEdge="top"设置滑动的方向;淡入淡出(fade)可以使用android:fadingMode="fade_in"设置具体是淡入(fade_in)还是淡出(fade_out)等。

标签里面定义需要转场(或者不需要转场)的目标 id ,这个 id 可以使系统自带的,也可以是我们自己视图中的 view 的 id,每一个 id 需要单独在标签中定义,android:targetId表示目标ID需要进行过渡转换的 view,而android:excludeId表示我们不需要该 ID 的 view 进行过渡转场。上面的那段代码的意思是说,除了状态栏和导航栏以外所有的 view,都执行 explode 动画。

如果我们想要在同一个过渡状态中实现两种或多种动画效果怎么办?也简单,将根标签替换为,然后定义每一种动画效果,最后记得在根标签中使用android:transitionOrdering注明这几种动画的演示顺序,sequential表示顺序执行,而together表示同时执行。比如像下面的代码:123456789101112131415

这段代码的意思就很简单了,该 xml 定义了两个过渡动画,并且同时执行。第一个动画是针对 id 为 cardView 的 view 进行滑动,第二个动画将除了状态栏、导航栏和 cardview 以外的 view,进行淡入淡出。

为每个 Activity 定义转场样式

这里的每一种动画,指的是在进行界面跳转过渡时,两个界面的状态。比如对于 Activity A 和 Activity B 这两个界面,可能的状态如下:

o 界面 A 跳转至界面 B :这时界面 A 是退出(exit )过渡状态,而对应的界面B是进入(enter)过渡状态。

o 界面 B 返回到界面 A :这时界面 A 是重新进入(reenter)过渡,而对应的界面B则是返回(return)过渡。

一般来说,所有的 Activity 过渡动画都可以定义成如下的形式:1234567891011121314

当然,你可以不用写全,比如在我的 Demo 中一个界面的转场动画文件如下:1234567

调用 ActivityOptionsCompat

转场动画是在两个界面的跳转返回时发生的,所以,当使用 intent 跳转界面时,需要调用ActivityOptionsCompat来指定动画的运行。

一般来说,调用ActivityOptionsCompat的模板代码如下:123456//创建一个包含过渡动画信息的ActivityOptions对象ActivityOptionsoptions=ActivityOptions.makeSceneTransitionAnimation(this,view,getString(R.string.image_transition_name));//使用Intent跳转界面,并传递共享对象信息Intentintent=newIntent(this,DetailActivity.class);startActivity(intent,optionsCompat.toBundle());

ActivityOptionsCompat 是在support v4 包里面的,其实它是 ActivityOptions 的一个兼容(ActivityOptions是API 16引入的)。

然后,我们需要在第二个 Activity 中,将转场的图片获取并显示到界面中。

多个共享元素的过渡实现

有时候我们需要让多个元素产生动画效果,可以使用 Pair<> 来实现:1ActivityOptionsoptions=ActivityOptions.makeSceneTransitionAnimation(this,Pair.create(view1,"agreedName1"),Pair.create(view2,"agreedName2"));

手动实现一个转场动画

现在市面上,Android 5.0 以下的手机系统还有一定的市场份额,所以为了照顾这些用户,我们只能手动实现一下共享元素的转场动画效果。

实现的思路也比较简单,大概的步骤如下:

o 确定第一个界面的共享元素,将其信息传递个第二个界面

o 第二个界面接收信息,开始的时候将界面设置为透明,并只显示共享元素。

o 将第二个界面的共享元素进行动画处理。

那么我们开始一步步实现上面的步骤。

获取共享元素位置信息

在第一个界面中,我们需要获取到共享元素的位置信息,并将其传递给下一个界面。于是乎,我们可以在第一个界面元素点击事件中,这么写:1234567891011121314publicvoidimageClick(Viewview){Intentintent=newIntent(AnimeActivity.this,AnimeDetailActivity.class);//创建一个rect对象来存储共享元素位置信息Rectrect=newRect();//获取元素位置信息view.getGlobalVisibleRect(rect);//将位置信息附加到intent上intent.setSourceBounds(rect);CustomImagecustomImage=(CustomImage)view;intent.putExtra(AnimeDetailActivity.EXTRA_IMAGE,customImage.getImageId());startActivity(intent);//屏蔽Activity默认转场效果overridePendingTransition(0,0);}

其中getGlobalVisibleRect()方法的含义是,获取可见的状态栏高度+可见的标题栏高度+Rect左上角到标题栏底部的距离,如果标题栏被隐藏了,那么可见标题栏高度为0。

接下来,就在在第二个界面接收位置信息并将该图片展示出来了。

模拟转场动画

在第二个界面中,我们需要做如下的操作:

o 获取上共享元素信息。

o 计算共享元素缩放比例和位移距离。

o 调用动画,完成模拟转场效果。

我将上面三个步骤的代码如下,你也可以下载我完整的Demo来查看。1234567891011121314151617181922232425262728293031privatevoidinitial(){//获取上一个界面传入的信息mRect=getIntent().getSourceBounds();mRescourceId=getIntent().getExtras().getInt(EXTRA_IMAGE);//获取上一个界面中,图片的宽度和高度mOriginWidth=mRect.right-mRect.left;mOriginHeight=mRect.bottom-mRect.top;//设置ImageView的位置,使其和上一个界面中图片的位置重合FrameLayout.LayoutParamsparams=newFrameLayout.LayoutParams(mOriginWidth,mOriginHeight);params.setMargins(mRect.left,mRect.top-getStatusBarHeight(),mRect.right,mRect.bottom);mImageView.setLayoutParams(params);//设置ImageView的图片和缩放类型mImageView.setImageResource(mRescourceId);mImageView.setScaleType(ImageView.ScaleType.CENTER_CROP);//根据上一个界面传入的图片资源ID,获取图片的Bitmap对象。BitmapDrawablebitmapDrawable=(BitmapDrawable)getResources().getDrawable(mRescourceId);Bitmapbitmap=bitmapDrawable.getBitmap();//计算图片缩放比例和位移距离getBundleInfo(bitmap);//创建一个Pallette对象mImagePalette=Palette.from(bitmap).generate();//使用Palette设置背景颜色mContainer.setBackgroundColor(mImagePalette.getVibrantColor(ContextCompat.getColor(this,android.R.color.black)));}

在12行,通过设置 Margin 的形式来确定图片的位置,需要注意的是,由于状态栏是在父控件 FramLayout 之外的,因此我们要将 Rect.top 的值减去状态栏的高度,这样才是相对于屏幕的绝对位置。然后,getBundleInfo() 方法的代码如下:12345678910111213privatevoidgetBundleInfo(Bitmapbitmap){//计算图片缩放比例,并存储在bundle中if(bitmap.getWidth()>=bitmap.getHeight()){mScaleBundle.putFloat(SCALE_WIDTH,(float)mScreenWidth/mOriginWidth);mScaleBundle.putFloat(SCALE_HEIGHT,(float)bitmap.getHeight()/mOriginHeight);}else{mScaleBundle.putFloat(SCALE_WIDTH,(float)bitmap.getWidth()/mOriginWidth);mScaleBundle.putFloat(SCALE_HEIGHT,(float)mScreenHeight/mOriginHeight);}//计算位移距离,并将数据存储到bundle中mTransitionBundle.putFloat(TRANSITION_X,mScreenWidth/2-(mRect.left+(mRect.right-mRect.left)/2));mTransitionBundle.putFloat(TRANSITION_Y,mScreenHeight/2-(mRect.top+(mRect.bottom-mRect.top)/2));}

动画处理

最后我们需要使用动画来模拟转场效果,代码如下:12345678910privatevoidrunEnterAnim(){mImageView.animate().setInterpolator(DEFAULT_INTERPOLATOR).setDuration(DURATION).scaleX(mScaleBundle.getFloat(SCALE_WIDTH)).scaleY(mScaleBundle.getFloat(SCALE_HEIGHT)).translationX(mTransitionBundle.getFloat(TRANSITION_X)).translationY(mTransitionBundle.getFloat(TRANSITION_Y)).start();}

很简单,自此,入场动画效果基本模拟完毕。

而退场动画就更简单了,直接上代码:1234567891011121314151617privatevoidrunExitAnim(){mImageView.animate().setInterpolator(DEFAULT_INTERPOLATOR).setDuration(DURATION).scaleX(1).scaleY(1).translationX(0).translationY(0).withEndAction(newRunnable(){@Overridepublicvoidrun(){finish();overridePendingTransition(0,0);}}).start();}

所以,是不是很简单?

如果觉得《android打印动画 Android 中的转场动画及兼容处理》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。