android进阶4step1:Android动画处理与自定义View——转场动画

以下都需要运行在5.0以上

一、揭露动画效果

参考:使用Circular Reveal为你的应用添加揭露动画效果

最主要的类Circular Reveal

官方将这一动画称为揭露效果,它在官网中的描述是这样的:

当您显示或隐藏一组 UI 元素时,揭露动画可为用户提供视觉连续性。[ViewAnimationUtils.createCircularReveal()](https://developer.android.com/reference/android/view/ViewAnimationUtils.html?hl=zh-cn#createCircularReveal(android.view.View, int, int, float, float))
方法让您能够为裁剪区域添加动画以揭露或隐藏视图。

很明显,我们使用ViewAnimationUtils.createCircularReveal()方法就能达到基本的揭露动画效果了。那么我们就直接开始看一下这个方法到底需要哪些参数吧

Animator createCircularReveal (View view,        // The View will be clipped to the animating circle.
            int centerX,                         // The x coordinate of the center of the animating circle, relative to view
            int centerY,                         // The y coordinate of the center of the animating circle, relative to view
            float startRadius,                   // The starting radius of the animating circle.
            float endRadius                      // The ending radius of the animating circle.
)

ViewAnimationUtils.createCircularReveal()方法所执行的效果,就是将一个View裁剪成圆,然后从圆心逐渐揭露展现视图。

参数 参数说明
view 要执行动画效果的View
centerX 圆心x坐标
centerY 圆心y坐标
startRadius 开始时的圆半径
endRadius 结束时的圆半径

其实参数都是比较容易理解的,主要是涉及到了动画开始的x,y坐标,以及圆形揭露的半径变化startRadius->endRadius。
在此我就以最上面的那个效果图为例,对createCircularReveal ()的使用进行一个简单的引入吧。

简单使用:

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewAnimationUtils;

public class MainActivity extends AppCompatActivity {

    private View mView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mView = findViewById(R.id.view);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_enter:
                revealEnter();
                break;
            case R.id.btn_exit:
                revealExit();
                break;
        }
    }


    /**
     * 进入动画
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void revealEnter() {
        //获取视图的宽度
        int w = mView.getWidth();
        int h = mView.getHeight();
        //设置基准点(园的中心点)的位置 从左上角开始(0,0)
        //(w,h) 应该在视图的右下角
        int cx = w;
        int cy = h;
        //Math.hypot() 函数返回它的所有参数的平方和的平方根,即:视图的对角线
        //开始的圆的半径
        int r = (int) Math.hypot(w, h);
        Animator animator = ViewAnimationUtils.createCircularReveal(mView, cx, cy, 0, r);
        //设置显示动画的时间间隔
        animator.setDuration(2000);
        mView.setVisibility(View.VISIBLE);
        animator.start();
    }

    /**
     * 离开动画
     */
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void revealExit() {
        //获取视图的宽度
        int w = mView.getWidth();
        int h = mView.getHeight();
        //设置基准点(园的中心点)的位置 从左上角开始(0,0)
        int cx = w;
        int cy = h;
        //Math.hypot() 函数返回它的所有参数的平方和的平方根,即:视图的对角线
        //开始的圆的半径
        int r = (int) Math.hypot(w, h);
        /**
         *
         */
        Animator animator = ViewAnimationUtils.createCircularReveal(mView, cx, cy, r, 0);
        //设置显示动画的时间间隔
        animator.setDuration(2000);
        animator.start();
        //当动画结束后让视图不可见
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                mView.setVisibility(View.INVISIBLE);
            }
        });
    }
}

二、转场动画(场景间 同一个Activity中)

Transition框架核心Scene、Transition和TransitionManager类

  • Scene:场景  (定义了界面当前的状态信息,保存了布局中所有View的属性值)

其中Scene是一个容器,就是放置你定义的布局,而真正去做场景之间切换这个动作是Transition框架中TransitionManager 调用其中go方法或者transitionTo方法完成场景之间切换,而真正创建具体动画交由Transition子类来完成,开始动画交给Transition来执行。
转:Android场景动画(Scene)

Scene.getSceneForLayout() 参数介绍如下:

扫描二维码关注公众号,回复: 4767671 查看本文章
  • sceneRoot 表示从什么地方开始切换场景。
  • layoutId 切换到什么场景的布局文件,比如上述例子中生成Scene2实例,layoutId 就是场景2中的布局。
  • context 上下文
  • Transition:转换

当一个场景改变的时候,transition主要负责:捕获每个View在开始场景和结束场景时的状态(各种属性值);

根据两个场景(开始和结束)之间的区别自动创建一个Animator。

监听一个容器内部有控件的状态发生改变后执行的动画

一个有四种动画效果:

  • Slide 划入
  • Explode 爆炸
  • Fade 隐藏
  • changeBounds 位置与大小变化
  • TransitionManager:负责场景之间的跳转和添加效果

  • 这个类将SenceTransition关联了起来,大多数情况下的场景变化都会使用AutoTransition(默认动画)。只有当应用程序需要不同的转换行为时,才需要指定其他的Transition来满足特定的场景需求。

以下转载:Android Transition——基础篇

  • setTransition(Scene scene, Transition transition) 

设置需要的场景与过渡动画

  • setTransition(Scene fromScene, Scene toScene, Transition transition) 

设置起始场景和结束场景与过渡动画

  • go(Scene scene) 

切换到指定的场景

  • go(Scene scene, Transition transition) 

切换到指定的场景以及所使用的过渡动画,transition如果传了null,那么就没有了过渡动画。

  • beginDelayedTransition(ViewGroup sceneRoot, Transition transition) 

可以自定义场景过渡的方法,调用此方法时,TransitionManager会捕获sceneRoot中View的属性值,然后发出请求以在下一帧上进行转换。那时候,sceneRoot中的新值将被捕获,变化的过程将会以动画的形式展现出来。我们没有必要创建一个新的Scene,因为这个方法主要是用来展现当前场景到下一帧的过渡效果。

  • void endTransitions (ViewGroup sceneRoot) 

结束指定场景根目录在准备/正在进行的转换。

更详细的解释,请移步官方API。 

 示例代码:

效果:

自定义动画效果:在res目录中创建transition文件夹 创建transition.xml文件

<?xml version="1.0" encoding="utf-8"?>
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
     <!--第一种动画效果-->
    <changeImageTransform android:duration="1000">
        <!--指定图片控件的id-->
        <targets android:targetId="@id/image" />
    </changeImageTransform>
    <!--第二种动画效果 淡入淡出-->
    <fade android:duration="1000" android:startDelay="1000">
    </fade>
</transitionSet>

实现类 


​public class SceneActivity extends AppCompatActivity {

    private Scene mOverViewScene;
    private Scene mInfoScene;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scene);
        //根布局
        ViewGroup sceneRoot = (ViewGroup) findViewById(R.id.scene_root);
        //搭建第一个场景
        mOverViewScene = Scene.getSceneForLayout(sceneRoot, R.layout.scene_overview, getBaseContext());
        //搭建第二个场景
        mInfoScene = Scene.getSceneForLayout(sceneRoot, R.layout.scene_info, getBaseContext());
        //首先跳转到第一个场景
        TransitionManager.go(mOverViewScene);
    }

    //点击事件实现场景的跳转逻辑
    public void onClick(View view) {
        switch (view.getId()) {
            //点击info图标时
            case R.id.btnInfo:
                //加载自定义的跳转动画
                Transition transition = TransitionInflater.from(getBaseContext())
                        .inflateTransition(R.transition.transition);
                TransitionManager.go(mInfoScene, transition);
                 //默认是AutoTransition
                //TransitionManager.go(mInfoScene);
                break; 
            //点击close图标时
            case R.id.btnClose:
                TransitionManager.go(mOverViewScene);
                break;
        }
    }

}

三、Activity间的转场动画

转:Android开发之Activity转场动画

转:android 学习使用Activity转场动画及shareElement

转场动画(Activity Transition)基本介绍

Android 5.0 提供了三种Transition类型

  • 进入:决定Activity中的所有的视图怎么进入屏幕。
  • 退出:决定一个Activity中的所有视图怎么退出屏幕。
  • 共享元素(shareElement:决定两个activities之间的过渡,怎么共享(它们)的视图。

进入和退出包含如下动画效果

  • explode(分解) – 从屏幕中间进或出
  • slide(滑动) - 从屏幕边缘进或出地
  • fade(淡出) –通过改变屏幕上视图的不透明度达到添加或者移除视图的效果

共享元素包含如下动画效果

  • changeBounds - 改变目标视图的布局边界
  • changeClipBounds - 裁剪目标视图边界
  • changeTransform - 改变目标视图的缩放比例和旋转角度
  • changeImageTransform - 改变目标图片的大小和缩放比例

Transition 与 Activity的跳转动画有以下几个

  • setEnterTransition 进入的动画
  • setExitTransition 退出的动画
  • setReturnTransition 返回的动画
  • setReenterTransition 重入的动画

示例:

第一个Activity

public class FirstActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void onClick(View view) {
        int resId = -1;
        switch (view.getId()) {
            case R.id.iv1:
                resId = R.drawable.pic1;
                break;
            case R.id.iv2:
                resId = R.drawable.pic2;
                break;
            case R.id.iv3:
                resId = R.drawable.pic3;
                break;
            case R.id.iv4:
                resId = R.drawable.pic4;
                break;
        }
        /**
         * 每点击一张图片
         * 都会将这一张图片的资源id传出去
         */
        Intent intent = new Intent(this, SecondActivity.class);
        intent.putExtra("resId", resId);

        //创建transition
        Transition transition = new Explode();
        //指定状态栏不变(指定某一个控件不使用动画)(排除某个元素不在转场动画中)
        transition.excludeTarget(android.R.id.statusBarBackground, true);

        //设置进场动画
        getWindow().setEnterTransition(transition);
        //设置离场动画
        getWindow().setExitTransition(transition);
        //重进动画
        getWindow().setReenterTransition(transition);
        //设置共享元素进场动画
        getWindow().setSharedElementEnterTransition(transition);
        //设置共享元素(当前view 和 共享元素id 根据这个id来匹配)
        Pair<View, String> shareElement = Pair.create(view, "img");

        
        //makeSceneTransitionAnimation 可以不设置或者设置多个共享元素
        ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this, shareElement);
        //通过toBundle方法传给startActivity 
        startActivity(intent, options.toBundle());
    }
}

第二个Activity

public class SecondActivity extends Activity {

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        //拿到传来的图片资源id
        int resId = getIntent().getExtras().getInt("resId");
        ImageView iv =  findViewById(R.id.iv);
        //共享元素的id
        iv.setTransitionName("img");
        //设置给当前布局的ImageView
        iv.setImageResource(resId);

        Transition transition = new Explode();
        //指定状态栏不变(指定某一个控件不使用动画)(排除它)
        transition.excludeTarget(android.R.id.statusBarBackground, true);
        //设置进场动画
        getWindow().setEnterTransition(transition);
        //设置离场动画
        getWindow().setExitTransition(transition);

    }

}

 除了可以在代码中开启转场还可以定义在Style中

启动转场

<style name="BaseAppTheme" parent="android:Theme.Material"> 

<!– 启动窗口内容转场 -->
<item name="android:windowContentTransitions">true</item>
<!– 窗口进入/离开时演示的动画 -->
<item name="android:windowEnterTransition">@transition/explode</item> <item name="android:windowExitTransition">@transition/explode</item>
<!– 共享元素进入/离开时演示的动画 -->
<item name="android:windowSharedElementEnterTransition">
@transition/change_image_transform</item>
<item name="android:windowSharedElementExitTransition">
@transition/change_image_transform</item> 

</style>

更多案例:https://github.com/Trisaa/MaterialTranstion

进阶用法:https://github.com/andremion/Music-Player

猜你喜欢

转载自blog.csdn.net/qq_17846019/article/details/84931834