Android 材料设计Material Design 动画篇(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/q714093365/article/details/83511998

Material Design,中文名:材料设计语言,是由Google推出的全新的设计语言,谷歌表示,这种设计语言旨在为手机、平板电脑、台式机和“其他平台”提供更一致、更广泛的“外观和感觉”。 

Material Design语言的一些重要功能包括 系统字体Roboto的升级版本 ,同时颜色更鲜艳,动画效果更突出。谷歌的想法是让谷歌平台上的开发者掌握这个新框架,从而让所有应用就有统一的外观,就像是苹果向开发者提出的设计原则一样。谷歌还基于这种新的设计语言对本公司旗舰应用进行了重新设计,包括安卓和网页端的Gmail和Calendar。在安卓平台上,这种新界面被称为Material,支持各种新动画效果,具有内置的实时UI阴影,以及可在不同屏幕之间切换的hero元素。

展示

 

CircularReveal(揭露动画)

背景扩散从某一个点向四周展开或者从四周向某一点聚合起来,类似波纹的效果,可以给任意的View添加这种效果。 显示或隐藏一组 UI 元素时,揭露动画可为用户提供视觉连续性;可以用在 Activity 里面的 View 动画效果,用来揭露某个隐藏 View 的显示;也可以使用在 Activity 跳转过渡动画中。

展示

代码实现 :

Android Sdk 中已经帮我们提供了一个工具类 ViewAnimationUtils 来创建揭露动画。ViewAnimationUtils 里面只有一个静态方法 createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius), 返回一个 Animator 动画对象。


//第一个参数是执行揭露动画的 View 视图
//第二个参数是相对于视图 View 的坐标系,动画圆的中心的x坐标
//第三个参数是相对于视图 View 的坐标系,动画圆的中心的y坐标
//第四个参数是动画圆的起始半径,
//第五个参数动画圆的结束半径。
ViewAnimationUtils.createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius);
mButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        final int width = mImageView.getMeasuredWidth();
        final int height = mImageView.getMeasuredHeight();
        final float radius = (float) Math.sqrt(width * width + height * height);
        //主要代码
        Animator animator = ViewAnimationUtils.createCircularReveal(mImageView, width , height , radius, 0);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                  //mImageView.setVisibility(View.GONE);
            }
        });
        animator.setDuration(2000);
        animator.start();
    }
});

Transition(过度动画)

曾经的Android在Activity进行跳转的时候,只是非常生硬的进行切换,即使用overridePendingTransition(int inId,int outId)这个方法来给Activity增加一些简单的切换动画。而在Android 5.X中,Google对动画效果进行了更深一步的诠释,为Activity的转场效果设计了更加丰富的动画效果。

 Android 5.0之前使用overridePendingTransition(int inId,int outId)方法进行平移,旋转,缩放,淡入等简单动画

Android 5.0之后,加入1.explode(分解) ———从屏幕中间进或出,移动视图。2.slide(滑动)———从屏幕边缘进或出,移动视图。3.fade(淡出)———通过改变屏幕上视图的不透明度达到添加或移除的效果。

展示

代码实现 :

  1. 这三种方式需要在设置动画的页面上设置如下所示代码:
    // 允许使用transitions
    getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
  2. 设置进入Activty或退出Activty的动画
    //分解
    getWindow().setEnterTransition(new Explode());
    getWindow().setExitTransition(new Explode());
    //滑动
    getWindow().setEnterTransition(new Slide());
    getWindow().setExitTransition(new Slide());
    //淡出
    getWindow().setEnterTransition(new Fade());
    getWindow().setExitTransition(new Fade());
    
    getWindow().setEnterTransition(); //首次进入显示的动画
    getWindow().setExitTransition(); //启动一个新Activity,当前页的退出动画
    getWindow().setReturnTransition(); //调用 finishAfterTransition() 退出时,当前页退出的动画
    getWindow().setReenterTransition(); //重新进入的动画。即第二次进入,可以和首次进入不一样。
    
  3. 需要将Activity跳转的代码startActivity(intent)的方法改为
    startActivity(intent,ActivityOptions.makeSceneTransitionAnimation(this).toBundle());

Shared Element Transition(共享元素)

  • changeBounds———改变目标视图的布局边界

  • changeClipBounds———裁切目标视图边界

  • changeTransform———改变目标视图的缩放比例和旋转角度

  • changeImageTransfrom———改变目标图片的大小和缩放比例

 

 

从一个Activity A转换到Activity B,而且他们共享一个元素(比如是一个view),在这种场景下,最好的用户体验可能就是将共享的元素直接变换到最终的地方和大小,这会使用户专注于应用而且有一种连贯性的表达。

共享元素的连接点是所有共享元素View的transition name。通过transtion name来判断哪两个元素是共享关系
 

  1. 首先需要给当前的Activity的布局文件中设置要共享的元素,给它增加相应的属性:
        <ImageView
            android:id="@+id/ImageView1"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:src="@drawable/timg"
            android:transitionName="test" />
    
    
        //代码设置
        imageView. setTransitionName();
  2. 给跳转的Activity的布局文件也增加相同的属性,共享元素的属性名要保持一致。
        <ImageView
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:src="@drawable/timg"
            android:transitionName="test" />
  3. 跳转代码

    //共享单个元素跳转
    Intent intent = new Intent();
    intent.setClass(ExcessiveActivity.this, ExcessiveActivity2.class);
    startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(this, imageView, "test").toBundle());
    
    //共享多个元素跳转
    Intent intent = new Intent(this,SecondActivity.class);
    ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
                    Pair.create(imageView,"test"),
                    Pair.create(textview,"test2"));
    startActivity(intent,options.toBundle());
    

    注:一定要保证命名相同,这样系统才能找到共享元素 

延时共享元素动画

加载网络图片,在网络图片获取到之前,这个共享元素的动画效果没有作用。需要在图片下载完成之后在开始共享元素的动画效果,这个时候这个时候需要用到延时共享元素动画

 postponeEnterTransition()函数用于延时动画,startPostponedEnterTransition()函数用于开始延时的共享动画。在Activity进入的时候先调用postponeEnterTransition()延时动画,在网络图片获取完成之后在调用startPostponedEnterTransition()开始动画。

    private ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_excessive2);
        imageView = findViewById(R.id.ImageView);
        handler.sendEmptyMessageDelayed(0, 1000);
        postponeEnterTransition();//停止动画
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            imageView.setImageResource(R.drawable.timg);
            startPostponedEnterTransition();//开始动画
        }
    };

 

尽管添加延时可以让共享元素 Transition 更加流畅准确,但是你也要知道在应用中引入共享元素 Transition 的延迟还有一些副作用:

  • 调用postponeEnterTransition后不要忘记调用startPostponedEnterTransition
    忘记调用startPostponedEnterTransition会让你的应用处于死锁状态,用户无法进入下个Activity。

  • 不能将共享元素 Transition 延迟设置到1s以上。延迟时间过长会在应用中产生不必要的卡顿,影响用户体验。


曲线运动:

曲线运动是动画利用曲线实现时间内插与空间移动模式, 
PathInterpolator是一个基于贝塞尔曲线或path对象的全新插入器,这个插入器会在1*1的正方形内指定一个
运动曲线,定位点位于(0,0)以及(1,1),而控制点由构造函数参数指定。
属性动画类别给出了新的构造函数,可以使用path对象为视图的X,Y属性添加动画,系统提供了三种基本曲线:

  • @interpolator/fast_out_linear_in.xml
  • @interpolator/fast_out_slow_in.xml
  • @interpolator/linear_out_slow_in.xml

除此之外可以自己定义:根据你需要的曲线去绘制,其实跟我们使用的贝塞尔曲线去不断刷新视图的运动轨迹是一样的。

    //TODO 使用曲线运动
    private void doCurdAnimation(View view) {
        Path path = new Path();
        path.arcTo(1f, 1f, 400f, 800f, 0, 90, false);
        PathInterpolator pathInterpolator = new PathInterpolator(1, 1);
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, View.X, View.Y, path);
        objectAnimator.setInterpolator(pathInterpolator);
        objectAnimator.setDuration(3000);
        objectAnimator.start();
    }


SVG矢量图动画

SVG 是使用 XML 来描述二维图形和绘图程序的语言。可伸缩矢量图形,图片在放大或者改变尺寸的情况下其图形质量不会有所损失

SVG中<path>标签

  • M = moveto 相当于 android Path 里的moveTo(),用于移动起始点
  • L = lineto 相当于 android Path 里的lineTo(),用于画线
  • H = horizontal lineto 用于画水平线
  • V = vertical lineto 用于画竖直线
  • C = curveto 相当于cubicTo(),三次贝塞尔曲线
  • S = smooth curveto 同样三次贝塞尔曲线,更平滑
  • Q = quadratic Belzier curve quadTo(),二次贝塞尔曲线
  • T = smooth quadratic Belzier curveto 同样二次贝塞尔曲线,更平滑
  • A = elliptical Arc 相当于arcTo(),用于画弧
  • Z = closepath 相当于closeTo(),关闭path

Google在Android5.X中提供了VectorDrawable    AnimatedVectorDrawable两个新的API来帮助支持SVG:

 VectorDrawable

在XML中创建一个静态的SVG,通常是如下结构。

 创建vector.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:height="200dp"
    android:width="200dp"
    android:viewportHeight="200"
    android:viewportWidth="200">
    <group 
        android:name="svg1"
        android:rotation="0">
        <path 
            android:fillColor="@android:color/holo_blue_light"
            android:pathData="M 25 50 a 25,25 0 1,0 50,0" />
    </group>
</vector>

其中包含两组宽高属性,height、width和viewportHeight、viewportWidth。这两组属性分别具有不同的含义,height、width表示该SVG图形的具体大小,而viewportHeight、viewportWidth表示SVG图形划分的比例。后面在绘制path时所使用的参数,就是根据这两个值来进行转换的,比如上面的代码,将200dp划分为100份,如果在绘制图形时使用坐标(50,50),则意味着该坐标位于该SVG图形正中间。因此,height、width的比例与viewportHeight、viewportWidth的比例,必须保持一致,不然图形就会发生压缩、形变。 

通过添加<group>标签和<path>标签来绘制一个SVG图形,其中pathData就是绘制SVG图形所用到的指令。使用方式如同正常的图片

AnimatedVectorDrawable

AnimatedVectorDrawable的作用是给VectorDrawable提供动画效果,Google将AnimatedVectorDrawable比喻一个胶水,通过AnimatedVectorDrawable来连接静态的VectorDrawable和动态的objectAnimator。

创建anim_vector.xml

<?xml version="1.0" encoding="utf-8"?> 
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"                 
    android:drawable="@drawable/verctor"> 
    <target 
        android:name="test" 
        android:animation="@animator/anim_rotate" > 
    </target> 
</animated-vector>

对应的vector中  android:drawable="@drawable/verctor" 即为静态的VectorDrawable。target 中 android:animation="@animator/anim_rotate"   代表的是动画效果,采用objectAnimator 属性动画

 动画启动方式:

        final ImageView imageView = (ImageView) findViewById(R.id.image);
        
        imageView.setImageResource(R.drawable.anim_vector); // 设置Resource为动画资源
        imageView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Animatable anim =  (Animatable)imageView.getDrawable();
                anim.start(); // 开始动画
            }
        });

 


完结

猜你喜欢

转载自blog.csdn.net/q714093365/article/details/83511998