高级UI-MD动画

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

MD动画是谷歌推出的一种动画效果,其实现的效果能让用户看着很是舒服,符合MD动画的动画,有很强的用户交互体验

Touch Feedback(触摸反馈)

在触摸反馈这一块,用的最多的就是水波纹效果,而水波纹效果是从5.0才开始出现的,从5.0开始,便已自带水波纹效果
以下是一个水波纹的按钮示例

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="自带效果" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/selectableItemBackground"
        android:text="系统效果 有边界" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/selectableItemBackgroundBorderless"
        android:text="系统效果 无边界" />

</LinearLayout>

其效果如下
MD动画-button效果
可以明显看出,不使用系统属性的button自带水波纹效果,这主要是由于使用了AppCompat的主题的原因,当然,也可以在主题中修改背景和水波纹的颜色

<item name="colorControlHighlight">?attr/colorPrimary</item>
<item name="colorControlNormal">@android:color/holo_orange_light</item>

在使用AppCompat主题的时候,Activity最好也使用AppCompatActivity,可以实现更好的兼容
上面的例子可以看出selectableItemBackground是不带按钮边界的,但在点击时候会后水波纹,长按时会显示出轮廓,selectableItemBackgroundBorderless也没有轮廓,长按时会显示出圆形,圆的大小与控件的宽高最大值匹配

Reveal Effect(揭露效果)

比如Activity的揭露出现的效果,需要使用ViewAnimationUtil工具类来设置View
比如要实现一个水波纹揭露效果,那么需要操作的View,扩散的中心点,开始的扩散半径,结束的扩散半径,函数原型如下

ViewAnimationUtils.createCircularReveal(view, centerX, centerY, startRadius, endRadius)

这里扩散一个按钮作为示例
布局就只有一个按钮

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <Button
        android:id="@+id/button"
        android:onClick="revealAnimation"
        android:layout_width="100dp"
        android:layout_height="100dp" />

</LinearLayout>

然后实现其效果

public void revealAnimation(View view) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        Animator animator = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2,
                view.getHeight() / 2, 0,
                (float) Math.hypot(view.getWidth(), view.getHeight()));
        animator.setDuration(1000);
        animator.setInterpolator(new AccelerateInterpolator());
        animator.start();
    }
}

实现效果如下图
MD动画-揭露效果

Activity transition(Activity转场动画效果)

要实现转场动画就需要使用到ActivityOptions,而这个类只支持5.0及以上版本,在v4包中有一个ActivityOptionsCompat,其作用一致,但在低于5.0的版本中,却无法实现转场动画,只是避免了在使用ActivityOptions时候的版本判断
不使用MD的转场动画例子

startActivity(new Intent(this, SecondActivity.class));
overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);

MD转场动画主要分为两大类:共享元素转换和普通转换

转场动画使用前提

要使用转场动画,就需要设置转场动画使用允许,例如A,B两个活动,从A到B的转场动画依赖于两个活动允许转场动画
设置转场动画方式:代码方式和主题方式,两种方法都可以实现
代码方式,这个是设置在setContentView()之前

getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

主题方式

<item name="android:windowContentTransitions">true</item>

这里使用第一种,因为这样方便控制

共享元素转换

在不使用转场动画的时候,activity跳转默认效果如下
MD动画-无转场效果
可以把两个Activity当中的相同的元素关联起来做连贯的变换动画
要实现共享元素的转换,就需要设置共享元素的元素名 使用android:transitionName属性设置其view名,两个元素名相同就可实现共享元素转换
这里实现了两个Activity,并且已经注册
FirstActivity布局及活动

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/first_image_view"
        android:layout_width="200dp"
        android:layout_height="300dp"
        android:src="@drawable/image"
        android:transitionName="iamge"
        android:scaleType="centerCrop"
        android:onClick="startSecondActivity"/>

</LinearLayout>
public class First_Activity extends AppCompatActivity {
    private ImageView imageView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        setContentView(R.layout.activity_first);
        imageView = findViewById(R.id.first_image_view);
    }

    public void startSecondActivity(View view) {
        ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(
                this, imageView, "image");
        Intent intent = new Intent(this, SecondActivity.class);
        startActivity(intent, optionsCompat.toBundle());
    }
}

SecondActivity布局及活动

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/image"
        android:transitionName="iamge" />

</LinearLayout>
public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
        setContentView(R.layout.activity_second);
    }
}

实现效果图如下
MD动画-有转场效果
按返回键的时候自动实现了返回的共享元素转场动画,这是在源代码中实现的
单个元素共享

ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this, imageView, "image");
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent, optionsCompat.toBundle());

多个元素共享
要使元素关联起来,例如FirstActivity中有ImageView和Button,分别设置为image,button,那么在SecondActivity中也要相应设置image和button

ActivityOptionsCompat optionsCompat = ActivityOptionsCompat
		.makeSceneTransitionAnimation(this, Pair.create((View)imageView, "image"),Pair.create((View)button, "button"));
Intent intent = new Intent(this, SecondActivity.class);
startActivity(intent, optionsCompat.toBundle());

普通转场动画

普通转场动画主要有三种效果:滑动效果(Slide)、展开效果(Explode)、渐变显示隐藏效果(Fade)
这里使用一个跳转界面,复用跳转后的界面,实现转场动画,同时返回时候动画也与跳转动画相统一
跳转界面

public class NormalActivity extends AppCompatActivity {

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

    public void startSlide(View view) {
        Slide slide = new Slide();
        slide.setDuration(3000);
        getWindow().setExitTransition(slide);
        getWindow().setEnterTransition(slide);
        ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this);
        Intent intent = new Intent(this, NormalAnimActivity.class);
        intent.setType("slide");
        startActivity(intent, optionsCompat.toBundle());
    }

    public void startExplode(View view) {
        Explode explode = new Explode();
        explode.setDuration(3000);
        getWindow().setExitTransition(explode);
        getWindow().setEnterTransition(explode);
        ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this);
        Intent intent = new Intent(this, NormalAnimActivity.class);
        intent.setType("explode");
        startActivity(intent, optionsCompat.toBundle());
    }

    public void startFade(View view) {
        Fade fade = new Fade();
        fade.setDuration(3000);
        getWindow().setExitTransition(fade);
        getWindow().setEnterTransition(fade);
        ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(this);
        Intent intent = new Intent(this, NormalAnimActivity.class);
        intent.setType("fade");
        startActivity(intent, optionsCompat.toBundle());
    }
}

跳转界面布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/first_image_view"
        android:layout_width="200dp"
        android:layout_height="300dp"
        android:scaleType="centerCrop"
        android:src="@drawable/image" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal">

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Slide"
            android:onClick="startSlide"/>

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Explode"
            android:onClick="startExplode"/>

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Fade"
            android:onClick="startFade"/>
    </LinearLayout>

</RelativeLayout>

展示界面

public class NormalAnimActivity extends AppCompatActivity {

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

        String type = getIntent().getType();
        switch (type){
            case "slide":
                Slide slide = new Slide();
                slide.setDuration(3000);
                getWindow().setExitTransition(slide);
                getWindow().setEnterTransition(slide);
                break;
            case "explode":
                Explode explode = new Explode();
                explode.setDuration(3000);
                getWindow().setExitTransition(explode);
                getWindow().setEnterTransition(explode);
                break;
            case "fade":
                Fade fade = new Fade();
                fade.setDuration(3000);
                getWindow().setExitTransition(fade);
                getWindow().setEnterTransition(fade);
                break;
        }
    }
}

展示界面布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:src="@drawable/image" />

</LinearLayout>

为了更好的看见过程,这里设置的的动画时间有点长,设置为3秒
实现效果如下,图片有点大
MD动画-普通转场效果
如果有共享元素,可以设置共享元素,那么它就会按照共享元素动画执行,其他的子view就会按照Fade动画执行

猜你喜欢

转载自blog.csdn.net/cj5785/article/details/89061816