Activity过渡动画

看了下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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值