Activity过渡动画

简介: 看了下5.0的过渡动画,效果确实蛮炫的,可惜我是4.4.2的,哎,享受不了啊,没钱买手机,穷啊 后来在格瓦拉app里面发现了这种过渡动画,4.4.2的也支持,那时候感觉,这么牛×啊(其实以下的都能支持),但是一直没见着好的源码看看,直到我看到了别人仿的一个知乎日报app,里面发现有这个功能,我就把他提取了出来,加上了自己所理解的一些注释,如有其它见解的,可以留言哦废话

看了下5.0的过渡动画,效果确实蛮炫的,可惜我是4.4.2的,哎,享受不了啊,没钱买手机,穷啊
后来在格瓦拉app里面发现了这种过渡动画,4.4.2的也支持,那时候感觉,这么牛×啊(其实以下的都能支持),但是一直没见着好的源码看看,直到我看到了别人仿的一个知乎日报app,里面发现有这个功能,我就把他提取了出来,加上了自己所理解的一些注释,如有其它见解的,可以留言哦

  • 废话不多说,老规矩,先上效果图
    这里写图片描述

效果是真的蛮不错的,思路其实挺简单的,就是在第二个Activity界面上面再添加了一层动画效果的View,动画结束后就隐藏他,然后显示Activity界面

  • MainActivity.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    public void next(View v) {
        int location[] = new int[2];
        v.getLocationOnScreen(location);//将当前控件的坐标值赋给数组
        location[0]+=v.getWidth()/2;//获取横坐标控件的中心位置
        Intent intent=new Intent(this,SecondActivity.class);
        intent.putExtra("location", location);
        startActivity(intent);
        //关闭Activity启动的动画,目的是为了显示自己的动画
        overridePendingTransition(0, 0);
    }

    public void next1(View v) {
        int location[] = new int[2];
        v.getLocationOnScreen(location);
        location[0]+=v.getWidth()/2;
        Intent intent=new Intent(this,SecondActivity.class);
        intent.putExtra("location", location);
        startActivity(intent);
        overridePendingTransition(0, 0);
    }

activity_main.xml的文件就不写了,就是两个button,添加了两个onClick,一个next,一个next1。

  • SecondActivity.java
public class SecondActivity extends Activity implements OnStateChangeListener {
    private RevealBackgroundView revealBackgroundView;
    private LinearLayout linea;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        linea = (LinearLayout) findViewById(R.id.linea);
        revealBackgroundView = (RevealBackgroundView) findViewById(R.id.RevealBackgroundView);
        setupRevealBackground(savedInstanceState);
    }

    private void setupRevealBackground(Bundle savedInstanceState) {
        revealBackgroundView.setOnStateChangeListener(this);
        //初始化时,当前的savedInstanceState为空
        if (savedInstanceState == null) {
            final int[] startLocation = getIntent()
                    .getIntArrayExtra("location");
            // 初始化控件时的监听
            revealBackgroundView.getViewTreeObserver().addOnPreDrawListener(
                    new OnPreDrawListener() {
                        @Override
                        public boolean onPreDraw() {
                                        revealBackgroundView.getViewTreeObserver().removeOnPreDrawListener(this);
                            // 设置单击坐标点的半径
                            revealBackgroundView.setCurrentRadius(50);
                            // 设置绘制填充画笔的颜色
                            revealBackgroundView.setFillPaintColor(0xff34A67B);
                            // 开启动画
                            revealBackgroundView.startFromLocation(startLocation);
                            return true;
                        }
                    });
        } else {
            // 完成动画
            revealBackgroundView.setToFinishedFrame();
        }
    }

    @Override
    public void onStateChange(int state) {
        // 如果当前状态完成,就显示底部布局,隐藏RevealBackgroundView
        if (RevealBackgroundView.STATE_FINISHED == state) {
            linea.setVisibility(View.VISIBLE);
            revealBackgroundView.setVisibility(View.GONE);
        }
    }
}
  • activity_second.xml
<?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"
    android:orientation="vertical" >

    <com.example.anim.RevealBackgroundView
        android:id="@+id/RevealBackgroundView "
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <LinearLayout
        android:id="@+id/linea"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:visibility="gone" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="我是第二个页面"
            android:textSize="50px" />
    </LinearLayout>

</RelativeLayout>

重头戏View来了

  • RevealBackgroundView.java

public class RevealBackgroundView extends View {
    public static final int STATE_NOT_STARTED = 0;// 没有开始状态
    public static final int STATE_FILL_STARTED = 1;// 填充满状态
    public static final int STATE_FINISHED = 2;// 填充完成状态

    // 在动画开始的时候速率比较慢,后面持续增加
    private static final Interpolator INTERPOLATOR = new AccelerateInterpolator();
    private static final int FILL_TIME = 600;// 动画时间600毫秒

    private int state = STATE_NOT_STARTED;// 默认状态

    private Paint fillPaint;// 画笔
    private int currentRadius;// 半径
    ObjectAnimator revealAnimator;

    private int startLocationX;// 控件的x坐标值
    private int startLocationY;// 控件的Y坐标值

    private OnStateChangeListener onStateChangeListener;

    public RevealBackgroundView(Context context) {
        super(context);
        init();
    }

    public RevealBackgroundView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RevealBackgroundView(Context context, AttributeSet attrs,
            int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        fillPaint = new Paint();
        fillPaint.setStyle(Paint.Style.FILL);
        fillPaint.setColor(Color.WHITE);
    }

    // 设置画笔的颜色
    public void setFillPaintColor(int color) {
        fillPaint.setColor(color);
    }

    //开启动画
    public void startFromLocation(int[] tapLocationOnScreen) {
        changeState(STATE_FILL_STARTED);

        startLocationX = tapLocationOnScreen[0];//传递过来view的x的RELATIVE_TO_SELF坐标值
        startLocationY = tapLocationOnScreen[1];//传递过来view的y的RELATIVE_TO_SELF坐标值
        // 动画标记为当前的半径currentRadius,值为RevealBackgroundView的0--width+height
        revealAnimator = ObjectAnimator.ofInt(this, "currentRadius", 0,
                getWidth() + getHeight()).setDuration(FILL_TIME);
        revealAnimator.setInterpolator(INTERPOLATOR);
        // 动画监听器
        revealAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // 在动画结束的时候调用该方法
                changeState(STATE_FINISHED);
            }
        });
        revealAnimator.start();
    }

    // 当回调为true时,调用该方法,重新绘制当前界面
    public void setToFinishedFrame() {
        changeState(STATE_FINISHED);
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 在动画完成后直接画整个界面,不在让他继续扩散
        if (state == STATE_FINISHED) {
            canvas.drawRect(0, 0, getWidth(), getHeight(), fillPaint);
        } else {
            // 绘制点击控件位置扩散的圆圈
            canvas.drawCircle(startLocationX, startLocationY, currentRadius,
                    fillPaint);
        }
    }

    // 判断当前的状态
    private void changeState(int state) {
        if (this.state == state) {
            return;
        }
        this.state = state;
        // 将当前状态不停的回调,回调时判断一下当前是否完成,是的话就显示底部布局
        if (onStateChangeListener != null) {
            onStateChangeListener.onStateChange(state);
        }
    }

    // 设置圆圈的半径时,重新调用onDraw,重新画圆
    public void setCurrentRadius(int radius) {
        this.currentRadius = radius;
        invalidate();
    }

    public void setOnStateChangeListener(
            OnStateChangeListener onStateChangeListener) {
        this.onStateChangeListener = onStateChangeListener;
    }

    public static interface OnStateChangeListener {
        void onStateChange(int state);
    }
}

整个效果都是RevealBackgroundView来支持,代码也不是太多,很棒吧^-^


题外话,2016/3/12要去润创驾校体检,15号考科目一,在此记录一下,good idea

目录
相关文章
|
4月前
|
XML Android开发 数据格式
Android 中如何设置activity的启动动画,让它像dialog一样从底部往上出来
在 Android 中实现 Activity 的对话框式过渡动画:从底部滑入与从顶部滑出。需定义两个 XML 动画文件 `activity_slide_in.xml` 和 `activity_slide_out.xml`,分别控制 Activity 的进入与退出动画。使用 `overridePendingTransition` 方法在启动 (`startActivity`) 或结束 (`finish`) Activity 时应用这些动画。为了使前 Activity 保持静止,可定义 `no_animation.xml` 并在启动新 Activity 时仅设置新 Activity 的进入动画。
93 12
|
容器
Fragment——底部导航栏的实现
本节开始我们会讲解一些Fragment在实际开发中的一些实例!而本节给大家讲解的是底部导航栏的实现!而基本的底部导航栏方法有很多种,比如全用TextView做,或者用RadioButton,又或者使用TabLayout + RadioButton,当然复杂的情况还是得走外层套布局的方法!本节我们用TextView来做一个底部导航栏的效果,也熟悉下Fragment的使用!
112 0
|
XML Java 数据格式
Fragment底部导航栏
一个页面以微信为例,从上到下依次是状态栏,Activity顶部导航栏,Fragment,Activity底部导航栏。 每点击一个底部导航栏都会replace另一个Fragment。
72 0
获取Activity当前屏幕方向。
获取Activity当前屏幕方向。
152 0
|
XML Android开发 数据格式
Android动画一:Activity过渡动画详细实现原理
虽然 Android 5.0 之后推出了新的过渡动画方式,但通常只是用于特定的场合使用,activity.overridePendingTransition() 通用方式的过渡动画还是很常用。 原理分析 startActivity(Intent(this,SecondActivity::class.
7573 0
|
Android开发
Android Reveal圆形Activity转场动画
一、效果 图片较大无法上传~~ 地址:https://user-gold-cdn.xitu.io/2018/11/2/166d4b91aecdf577?imageslim 二、知识点 CircularReveal动画、透明主题、转场动画(非必须) 三、方案 假设有两个Activity A和B。
2044 0