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

目录
相关文章
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:一场永无止境的较量
【10月更文挑战第3天】 本文旨在深入剖析安卓 (Android) 和iOS两大移动操作系统在安全性方面的显著差异,通过细致对比,揭示它们在隐私保护、数据加密、应用生态监管以及系统更新机制等关键领域的不同策略与实践。文章不仅从技术层面探讨了两者的设计理念差异,还结合了实际案例分析,展示了这些差异如何影响用户体验和数据安全。最终,旨在为读者提供一个全面的视角,理解在日益复杂的数字环境中,选择何种移动平台可能更符合其对安全性和隐私保护的需求。
|
SQL XML Java
mybatis实现动态sql
MyBatis的动态SQL功能为开发人员提供了强大的工具来应对复杂的查询需求。通过使用 `<if>`、`<choose>`、`<foreach>`等标签,可以根据不同的条件动态生成SQL语句,从而提高代码的灵活性和可维护性。本文详细介绍了动态SQL的基本用法和实际应用示例,希望对您在实际项目中使用MyBatis有所帮助。
804 11
|
人工智能 移动开发 算法
【2023华中杯数学建模】B 题 小学数学应用题相似性度量及难度评估详细建模方案及实现代码
本文提供了2023年华中杯数学建模B题的详细建模方案和实现代码,包括设计小学数学应用题相似性度量方法、建立题目难度评估数学模型、对题库进行相似性或难度分类,以及使用TF-IDF和K-Means聚类算法进行题目难度分析和相似题目推荐。
409 0
【2023华中杯数学建模】B 题 小学数学应用题相似性度量及难度评估详细建模方案及实现代码
|
10月前
|
机器学习/深度学习 人工智能 算法
解锁政策红利:大数据时代的企业与个人发展新契机
在大数据与机器学习时代,政策解读、预测分析和个性化匹配成为挖掘发展新动能的重要工具。无论是企业还是个人,都能借助先进技术轻松理解复杂政策,把握趋势先机。文章探讨了自由职业者、创业者及企业员工如何通过政策支持实现协同发展,并介绍了“政策宝”这一智慧助手,助力用户发现和利用政策红利,抓住机遇实现目标。探索政策宝库,开启发展新征程!
|
缓存 资源调度 JavaScript
Yarn的安装与使用
Yarn的安装与使用
263 1
|
安全
深入理解Qt多线程编程:QThread、QTimer与QAudioOutput的内在联系__Qt 事件循环(三)
深入理解Qt多线程编程:QThread、QTimer与QAudioOutput的内在联系__Qt 事件循环
490 0
|
机器学习/深度学习 算法 数据挖掘
从零到精通:Scikit-learn在手,数据分析与机器学习模型评估不再难!
【7月更文挑战第25天】在数据科学中,模型评估是理解模型泛化能力的关键。对新手来说,众多评估指标可能令人困惑,但Scikit-learn简化了这一过程。
296 2
|
自然语言处理 运维 搜索推荐
内容社区行业搜索最佳实践
社区内容通常包括UGC和PGC。由于关键词和内容多样性丰富、用词规范程度参差不齐,搜索引擎需要对关键词和内容进行智能语义分析,识别出用户真正的查询意图,找到最全面最相关的结果满足用户需求。本文将详细介绍如何通过“开放搜索(OpenSearch)内容增强版”在社区论坛场景的应用,提升用户搜索体验,带来更多的业务转化
1279 0
|
网络安全
为KALI进行换元更新
为KALI进行更新 由于kali的软件仓库在国外,更新很慢,我们需要将kali的软件源更换为国内的软件源,推荐中科大的源 编辑 /etc/apt/sources.list 文件, 在文件最前面添加以下条目: ``` deb https://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib deb-src https://mirrors.ustc.edu.cn/kali kali-rolling main non-free contrib ``` 更改完 sources.list 文件后请运行 sudo apt-get u
551 0
为KALI进行换元更新
|
前端开发
CSS边框样式详解
border-color属性用于定义边框的颜色 简写形式: 想要为一个元素定义边框,我们需要完整地给出border-width、border-style和bordercolor。这种写法代码量过多,费时费力。不过CSS为我们提供了一种简写形式
316 0
CSS边框样式详解

热门文章

最新文章