Github项目解析(九)

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

转载请标明出处:一片枫叶的专栏

上一篇文章中我们讲解了在Activity启动过程中获取组件宽高的五种方式。在Activity的启动过程中如果我们直接在生命周期方法中通过view.getWidth()或者是view.getHeight()方法获取组件的宽度和高度其结果都是0,为什么会出现这个问题呢?

其实看过我以前写过的Activity启动流程  Activity布局加载流程  Activity布局绘制流程  的同学应该对Activity的启动流程和其布局加载绘制流程不陌生,Activity的启动流程和Activity的布局文件加载绘制流程,其实没有相关的关系的,其实两个异步的加载流程,这样我们在Activity的onCreate或者是onResume方法中调用textView.getHeight()或者是textView.getWidth()方法的时候,Activity对应的组件并没有执行完绘制流程,因此此时获取到的组件的宽高都是默认的0,所以这时候通过getWidth()和getHeight()方法也就是无法获取组件的宽和高了。

更多关于在Activity启动过程中获取组件宽高的知识,可参考我的:Activity启动过程中获取组件宽高的N种方式

文本中我们将讲解activity切换动画相关的知识点,这里的切换动画指的是是activity跳转时的动画效果。这里总结了一下,有五种方式实现activity切换时实现动画效果。下面我将依次介绍一下每种实现activity切换动画效果的实现方式。

在介绍activity的切换动画之前我们先来说明一下实现切换activity的两种方式:

  • 调用startActivity方法启动一个新的Activity并跳转其页面

  • 调用finish方法销毁当前的Activity返回上一个Activity界面

当调用startActivity方法的时候启动一个新的activity,这时候就涉及到了旧的Activity的退出动画和新的Activity的显示动画; 
当调用finish方法的时候,销毁当前Acitivity,就涉及到了当前Activity的退出动画和前一个Activity的显示动画;

所以我们的activity跳转动画是分为两个部分的:一个Activity的销毁动画与一个Activity的显示动画,明白了这一点之后我们开始看一下第一种实现Activity跳转动画的方式:通过overridePendingTransition方法实现Activity切换动画。

(一)使用overridePendingTransition方法实现Activity跳转动画

overridePendingTransition方法是Activity中提供的Activity跳转动画方法,通过该方法可以实现Activity跳转时的动画效果。下面我们就将通过一个简单的例子看一下如何通过overridePendingTransition方法实现Activity的切换动画。

demo例子中我们实现了Activity a中有一个点击按钮,点击按钮实现跳转Activity b的逻辑,具体代码如下:

1/** 2 * 点击按钮实现跳转逻辑 3 */ 4button1.setOnClickListener(new View.OnClickListener() { 5 @Override 6 public void onClick(View v) { 7 /** 8 * 在调用了startActivity方法之后立即调用overridePendingTransition方法 9 */ 10 Intent intent = new Intent(MainActivity.this, SecondActivity.class); 11 startActivity(intent); 12 overridePendingTransition(R.anim.slide_in_left, R.anim.slide_in_left); 13 } 14 });
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

可以看到我们在调用了startActivity方法之后又执行了overridePendingTransition方法,而在overridePendingTransition方法中传递了两个动画布局文件,我们首先看一下这里的动画文件具体是怎么实现的:

1<?xml version="1.0" encoding="utf-8"?> 2<set xmlns:Android="http://schemas.Android.com/apk/res/Android" 3 Android:shareInterpolator="false" 4 Android:zAdjustment="top"> 5 <translate 6 Android:duration="200" 7 Android:fromXDelta="-100.0%p" 8 Android:toXDelta="0.0" /> 9</set>
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

这里的overridePendingTransition方法传递的是两个动画文件id,第一个参数是需要打开的Activity进入时的动画,第二个参数是需要关闭的Activity离开时的动画。这样我们执行了这段代码之后在跳转Activity的时候就展示了动画效果: 
这里写图片描述

动画的效果是通过overridePendingTransition方法实现的,那么下面我们来看一下overridePendingTransition方法的定义,我们在overridependingTransition方法在定义的时候有这样的一段注释说明:

1/** 2 * Call immediately after one of the flavors of {@link #startActivity(Intent)} 3 * or {@link #finish} to specify an explicit transition animation to 4 * perform next. 5 */ 6 7/** 8 * @param enterAnim A resource ID of the animation resource to use for 9 * the incoming activity. Use 0 for no animation. 10 * @param exitAnim A resource ID of the animation resource to use for 11 * the outgoing activity. Use 0 for no animation. 12 */
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

好吧,这段注释,告诉通过注释我们能够知道:

  • overridePendingTransition方法需要在startAtivity方法或者是finish方法调用之后立即执行

  • 参数enterAnim表示的是从Activity a跳转到Activity b,进入b时的动画效果

  • 参数exitAnim表示的是从Activity a跳转到Activity b,离开a时的动过效果

  • 若进入b或者是离开a时不需要动画效果,则可以传值为0

好吧,本着批判的精神,我们来看一下是不是这样的,首先看一下如果我们在startActivity方法调用之后不立即执行overridePendingTransition方法,会有动画效果么?

若我们将overridePendingTransition延时1s执行呢?

1/** 2 * 点击按钮实现跳转逻辑 3 */ 4button1.setOnClickListener(new View.OnClickListener() { 5 @Override 6 public void onClick(View v) { 7 Intent intent = new Intent(MainActivity.this, SecondActivity.class); 8 startActivity(intent); 9 overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left); 10 /** 11 * 延时1s执行overridePendingTransition方法 12 */ 13 button1.postDelayed(new Runnable() { 14 @Override 15 public void run() { 16 overridePendingTransition(R.anim.slide_in_top, R.anim.slide_in_top); 17 } 18 }, 1000); 19 20 } 21 });
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

好吧,执行之后我们能够发现跳转动画没有了,所以overridePendingTransition只能在startActivity或者是finish方法之后执行。

还有一个问题,如果是在startActivity之后执行,只是在子线程中执行呢?activity的跳转动画能够执行么?

1/** 2 * 点击按钮实现跳转逻辑 3 */ 4button1.setOnClickListener(new View.OnClickListener() { 5 @Override 6 public void onClick(View v) { 7 Intent intent = new Intent(MainActivity.this, SecondActivity.class); 8 startActivity(intent); 9 overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left); 10 /** 11 * 在子线程中执行overridePendingTransition方法 12 */ 13 new Thread(new Runnable() { 14 @Override 15 public void run() { 16 overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_left); 17 } 18 }).start(); 19 20 } 21 });
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 21

好吧,你没有猜错,activity的切换效果还是执行,也就是说overridePendingTransition方法也是可以在子线程中执行的,当然这并没什么卵用。

好吧,在介绍完了使用overridePendingTransition方法实现Activity切换动画之后我们下面看一下使用style的方式定义实现Activity的切换动画。

(二)使用style的方式定义Activity的切换动画

(1)定义Application的style

1<!-- 系统Application定义 --> 2<application 3 Android:allowBackup="true" 4 Android:icon="@mipmap/ic_launcher" 5 Android:label="@string/app_name" 6 Android:supportsRtl="true" 7 Android:theme="@style/AppTheme">
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

(2)定义具体的AppTheme样式

其中这里的windowAnimationStyle就是我们定义Activity切换动画的style。而@anim/slide_in_top就是我们定义的动画文件,也就是说通过为Appliation设置style,然后为windowAnimationStyle设置动画文件就可以全局的为Activity的跳转配置动画效果。

1<!-- Base application theme. --> 2 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> 3 <!-- Customize your theme here. --> 4 <item name="colorPrimary">@color/colorPrimary</item> 5 <item name="colorPrimaryDark">@color/colorPrimaryDark</item> 6 <item name="colorAccent">@color/colorAccent</item> 7 <item name="Android:windowAnimationStyle">@style/activityAnim</item> 8 </style> 9 10 11<!-- 使用style方式定义activity切换动画 --> 12 <style name="activityAnim"> 13 <item name="Android:activityOpenEnterAnimation">@anim/slide_in_top</item> 14 <item name="Android:activityOpenExitAnimation">@anim/slide_in_top</item> 15 </style>
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

而在windowAnimationStyle中存在四种动画:

1activityOpenEnterAnimation // 用于设置打开新的Activity并进入新的Activity展示的动画 2activityOpenExitAnimation // 用于设置打开新的Activity并销毁之前的Activity展示的动画 3activityCloseEnterAnimation // 用于设置关闭当前Activity进入上一个Activity展示的动画 4activityCloseExitAnimation // 用于设置关闭当前Activity时展示的动画
  • 1

  • 2

  • 3

  • 4

  • 1

  • 2

  • 3

  • 4

(3)测试代码,实现activity切换操作

1/** 2 * 点击按钮,实现Activity的跳转操作 3 * 通过定义style的方式实现activity的跳转动画 4 */ 5 button2.setOnClickListener(new View.OnClickListener() { 6 @Override 7 public void onClick(View v) { 8 /** 9 * 普通的Intent跳转Activity实现 10 */ 11 Intent intent = new Intent(MainActivity.this, SecondActivity.class); 12 startActivity(intent); 13 } 14 });
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

这时候我们我们执行diamante逻辑之后就能发现activity在切换的时候出现了动画效果,说明我们设置的style起作用了。

(三)使用ActivityOptions切换动画实现Activity跳转动画

上面我们讲解的通过overridePendingTransition方法基本上可以满足我们日常中对Activity跳转动画的需求了,但是MD风格出来之后,overridePendingTransition这种老旧、生硬的方式怎么能适合我们的MD风格的App呢?好在google在新的sdk中给我们提供了另外一种Activity的过度动画——ActivityOptions。并且提供了兼容包——ActivityOptionsCompat。ActivityOptionsCompat是一个静态类,提供了相应的Activity跳转动画效果,通过其可以实现不少炫酷的动画效果。

(1)在跳转的Activity中设置contentFeature

1@Override 2 protected void onCreate(Bundle savedInstanceState) { 3 super.onCreate(savedInstanceState); 4 5 // 设置contentFeature,可使用切换动画 6 getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS); 7 Transition explode = TransitionInflater.from(this).inflateTransition(Android.R.transition.explode); 8 getWindow().setEnterTransition(explode); 9 10 setContentView(R.layout.activity_three); 11 }
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

这里我们在Activity的setContentView之前调用了:

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
  • 1

  • 1

方法,看过我的Activity布局加载流程的同学应该知道,这里的setFeature就是为activity的窗口设置特性,不同的特性对应不同的布局方式,比如可以设置无toolbar模式,有toolbar模式等等。而这里设置的是需要过渡动画,并且我们获取了Android中内置的explode动画,并设值给了Activity的window窗口对象,这样当Activity被启动的时候就会执行explode所带便的动画效果了。

(2)在startActivity执行跳转逻辑的时候调用startActivity的重写方法,执行ActivityOptions.makeSceneTransitionAnimation方法

1/** 2 * 点击按钮,实现Activity的跳转操作 3 * 通过Android5.0及以上代码的方式实现activity的跳转动画 4 */ 5 button3.setOnClickListener(new View.OnClickListener() { 6 @Override 7 public void onClick(View v) { 8 Intent intent = new Intent(MainActivity.this, ThreeActivity.class); 9 startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle()); 10 } 11 });
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

这里我们调用了startActivity的重载方法:

public void startActivity(Intent intent, @Nullable Bundle options)
  • 1

  • 1

并且我们传入了ActivityOptions.makeSceneTransitionAnimation,该方法表示将Activity a平滑的切换到Activity b,其还有几个重载方法可以指定相关的View,即以View为焦点平滑的从Activity a切换到Activity b。

调用这段代码之后我们activity跳转的时候就展示出了动画效果。 
这里写图片描述

(四)使用ActivityOptions之后内置的动画效果通过style的方式

这种方式其实就是通过style的方式展示和使用ActivityOptions过度动画,下面是实现通过定义style方式定义过度动画的步骤:

(1)编写过度动画文件

1<explode xmlns:Android="http://schemas.Android.com/apk/res/Android" 2 Android:duration="300" />
  • 1

  • 2

  • 1

  • 2

首先我们需要在Application项目res目录下新建一个transition目录,然后创建资源文件,然后使用这些系统自带的过渡动画效果,这里设置了过度时长为300ms。

(2)定义style文件

1<!-- Base application theme. --> 2 <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> 3 <!-- Customize your theme here. --> 4 <item name="colorPrimary">@color/colorPrimary</item> 5 <item name="colorPrimaryDark">@color/colorPrimaryDark</item> 6 <item name="colorAccent">@color/colorAccent</item> 7 8 <item name="Android:windowEnterTransition">@transition/activity_explode</item> 9 <item name="Android:windowExitTransition">@transition/activity_explode</item> 10 </style>
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

在Application的style文件中添加:

1<item name="Android:windowEnterTransition">@transition/activity_explode</item> 2 <item name="Android:windowExitTransition">@transition/activity_explode</item>
  • 1

  • 2

  • 1

  • 2

并指定过渡动画效果为我们刚刚定义的过渡动画文件。

(3)执行跳转逻辑

1/** 2 * 点击按钮,实现Activity的跳转操作 3 * 通过Android5.0及以上style的方式实现activity的跳转动画 4 */ 5 button4.setOnClickListener(new View.OnClickListener() { 6 @Override 7 public void onClick(View v) { 8 /** 9 * 调用ActivityOptions.makeSceneTransitionAnimation实现过度动画 10 */ 11 Intent intent = new Intent(MainActivity.this, FourActivity.class); 12 startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this).toBundle()); 13 } 14 });
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

这样执行之后也可以展示出Activity跳转过度动画了,其和通过代码方式实现的效果是类似的,而且这种动画效果是全局的。

(五)使用ActivityOptions动画共享组件的方式实现跳转Activity动画

这里的共享组件动画效果是指将前面一个Activity的某个子View与后面一个Activity的某个子View之间有过渡效果,即在这种过度效果下实现Activity的跳转操作。那么如何实现两个组件View之间实现过渡效果呢?

(1)定义共享组件

在Activity a中的button按钮点击transitionName属性:

1<Button 2 Android:id="@+id/button5" 3 Android:layout_width="match_parent" 4 Android:layout_height="wrap_content" 5 Android:layout_below="@+id/button4" 6 Android:layout_marginTop="10dp" 7 Android:layout_marginRight="10dp" 8 Android:layout_marginLeft="10dp" 9 Android:text="组件过度动画" 10 Android:background="@color/colorPrimary" 11 Android:transitionName="shareNames" 12 />
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

在Activity b的布局文件中为组件定义transitionName属性,这样这两个组件相当于有了过度对应关系,这里需要注意的是这两个组件的transitionName属性的值必须是相同的。

1<?xml version="1.0" encoding="utf-8"?> 2<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android" 3 Android:id="@+id/activity_second" 4 Android:layout_width="match_parent" 5 Android:layout_height="match_parent" 6 Android:gravity="center_horizontal" 7 Android:orientation="vertical" 8 Android:transitionName="shareNames" 9 > 10 11 <TextView 12 Android:layout_width="match_parent" 13 Android:layout_height="match_parent" 14 Android:background="@color/colorAccent" 15 Android:layout_marginTop="10dp" 16 Android:layout_marginBottom="10dp" 17 /> 18 19 20</LinearLayout>
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 12

  • 13

  • 14

  • 15

  • 16

  • 17

  • 18

  • 19

  • 20

(2)调用startActivity执行跳转动画

1/** 2 * 点击按钮,实现Activity的跳转操作 3 * 通过Android5.0及以上共享组件的方式实现activity的跳转动画 4 */ 5 button5.setOnClickListener(new View.OnClickListener() { 6 @Override 7 public void onClick(View v) { 8 Intent intent = new Intent(MainActivity.this, FiveActivity.class); 9 startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(MainActivity.this, button5, "shareNames").toBundle()); 10 } 11 });
  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

  • 1

  • 2

  • 3

  • 4

  • 5

  • 6

  • 7

  • 8

  • 9

  • 10

  • 11

需要说明的是这里调用的ActivityOptions.makeSceneTransitionAnimation方法,传递了三个参数,其中第一个参数为context对象,第二个参数为启动Activity的共享组件,第三个参数为启动Activity的共享组件transitionName属性值。

这样经过调用之后我们就实现了从Activity a跳转到Activity b的时候a中的组件到b中组件的过度效果。 
这里写图片描述

总结:

  • 本文主要讲解了通过overridePendingTransition方式和ActivityOptions动画API实现Activity的切换动画效果;

  • overridePendingTransition方法从Android2.0开始,基本上能够覆盖我们activity跳转动画的需求;

  • ActivityOptions API是在Android5.0开始的,可以实现一些炫酷的动画效果,更加符合MD风格;

  • ActivityOptions还可以实现两个Activity组件之间的过度动画;

  • 本项目例子已上传待github中,欢迎star和follow,项目地址:实现activity跳转动画的五种方式

另外对github项目,开源项目解析感兴趣的同学可以参考我的: 
Github项目解析(一)–>上传Android项目至github 
Github项目解析(二)–>将Android项目发布至JCenter代码库
Github项目解析(三)–>Android内存泄露监测之leakcanary 
Github项目解析(四)–>动态更改TextView的字体大小 
Github项目解析(五)–>Android日志框架 
Github项目解析(六)–>自定义实现ButterKnife框架 
Github项目解析(七)–>防止按钮重复点击 
Github项目解析(八)–>Activity启动过程中获取组件宽高的五种方式

18

0

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解

Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593