• 高级UI-MD动画


    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动画执行

  • 相关阅读:
    luoguP1080 国王游戏 题解(NOIP2012)(贪心+高精)
    luoguP1079 Vigenère 密码 题解(NOIP2012)
    luoguP2184 贪婪大陆 题解(树状数组)
    luoguP2680 运输计划 题解(二分答案+树上差分)
    树链剖分总结
    树上差分总结
    luoguP3258 [JLOI2014]松鼠的新家 题解(树上差分)
    简单差分(保证你一看就懂)
    luoguP3128 [USACO15DEC]最大流Max Flow 题解(树上差分)
    luoguP1541 乌龟棋 题解(NOIP2010)
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664589.html
Copyright © 2020-2023  润新知