Android 启动页过渡动画效果实现(二)

Android 启动页过渡动画效果实现(一)   

 Android 启动页过渡动画效果实现(二)

一.效果1:缩放、平移、渐变、弹簧弹性动画效果

1.效果图:

Android 启动页过渡动画效果实现(二)_第1张图片

2.添加依赖:

    //动画
    implementation 'com.daimajia.androidanimations:library:1.1.3@aar'
    implementation 'io.reactivex:rxandroid:1.2.0'
    implementation 'io.reactivex:rxjava:1.1.5'
    implementation 'com.jakewharton:butterknife:8.0.1'

3.主函数代码:

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;

import com.daimajia.androidanimations.library.Techniques;
import com.daimajia.androidanimations.library.YoYo;
import com.hjq.demo.R;
import com.hjq.demo.ui.activity.sgf.search.SearchviewActivity;

import java.util.concurrent.TimeUnit;

import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * app启动动画系列
 * https://github.com/HMonkey1024/MyLauncher
 * https://github.com/darryrzhong/OpenEyes
 */
public final class SgfSplash5Activity extends AppCompatActivity {
    @BindView(R.id.logo_outer_iv)
    ImageView mLogoOuterIv;
    @BindView(R.id.logo_inner_iv)
    ImageView mLogoInnerIv;
    boolean isShowingRubberEffect = false;
    @BindView(R.id.app_name_tv)
    TextView mAppNameTv;
    private long exitTime;
    private TextView tvRegister;
    private TextView tvLogin;
    private ImageView ivLogo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //全屏
//        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_sgf_splash5);
        ButterKnife.bind(this);

        initAnimation();
    }

    private void initAnimation() {
        startLogoInner1();
        startLogoOuterAndAppName();
    }

    private void startLogoInner1() {
        Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_top_in);
        mLogoInnerIv.startAnimation(animation);
    }

    private void startLogoOuterAndAppName() {
        final ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.setDuration(1000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float fraction = animation.getAnimatedFraction();
//                KLog.d("fraction: " + fraction);
                if (fraction >= 0.8 && !isShowingRubberEffect) {
                    isShowingRubberEffect = true;
                    startLogoOuter();
                    startShowAppName();
                    finishActivity();
                } else if (fraction >= 0.95) {
                    valueAnimator.cancel();
                    startLogoInner2();
                }

            }
        });
        valueAnimator.start();
    }

    private void startLogoOuter() {
        YoYo.with(Techniques.RubberBand).duration(1000).playOn(mLogoOuterIv);
    }

    private void startShowAppName() {
        YoYo.with(Techniques.FadeIn).duration(1000).playOn(mAppNameTv);
    }

    private void startLogoInner2() {
        YoYo.with(Techniques.Bounce).duration(1000).playOn(mLogoInnerIv);
    }

    private void finishActivity() {
        Observable.timer(1000, TimeUnit.MILLISECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1() {
                    @Override
                    public void call(Long aLong) {
                        startActivity(new Intent(SgfSplash5Activity.this, SearchviewActivity.class));
                        overridePendingTransition(0, android.R.anim.fade_out);
                        finish();
                    }
                });
    }
}

4.布局代码:




    

    

    

 5.xml动画:

anim_top_in.xml




    
    
    

fade_out.xml是Android API 28自带的 :





 

 二.效果2:由小到大缩放动画效果

1.效果图:

Android 启动页过渡动画效果实现(二)_第2张图片

 2.主函数代码:

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.daimajia.androidanimations.library.Techniques;
import com.daimajia.androidanimations.library.YoYo;
import com.hjq.demo.R;
import com.hjq.demo.ui.activity.sgf.search.SearchviewActivity;
import com.hjq.demo.utils.KickBackAnimator;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action1;
import rx.schedulers.Schedulers;

/**
 * app启动动画系列
 * https://github.com/HMonkey1024/MyLauncher
 * https://github.com/darryrzhong/OpenEyes
 */
public final class SgfSplash6Activity extends AppCompatActivity {
    @BindView(R.id.lin)
    LinearLayout lin;
    @BindView(R.id.tv_sbs)
    TextView tv_sbs;
    @BindView(R.id.tv_search)
    TextView tv_search;
    @BindView(R.id.tv_course)
    TextView tv_course;
    @BindView(R.id.tv_task)
    TextView tv_task;
    private Handler mHandler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //全屏
//        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_sgf_splash6);
        ButterKnife.bind(this);

        ArrayList textViews = new ArrayList<>();
        textViews.add(tv_sbs);
        textViews.add(tv_search);
        textViews.add(tv_course);
        textViews.add(tv_task);
//        showAnimation(textViews);
        showAnimation();
    }

    private void showAnimation() {
        tv_sbs.setVisibility(View.INVISIBLE);
        tv_search.setVisibility(View.INVISIBLE);
        tv_course.setVisibility(View.INVISIBLE);
        tv_task.setVisibility(View.INVISIBLE);
        Animation animation = AnimationUtils.loadAnimation(SgfSplash6Activity.this, R.anim.my_anim_scale2);
        tv_sbs.startAnimation(animation);
        tv_sbs.setVisibility(View.VISIBLE);
        mHandler.postDelayed(new Runnable() {

            @Override
            public void run() {

                //动画效果
                Animation animation = AnimationUtils.loadAnimation(SgfSplash6Activity.this, R.anim.my_anim_scale2);
                tv_search.startAnimation(animation);
                tv_search.setVisibility(View.VISIBLE);
                mHandler.postDelayed(new Runnable() {

                    @Override
                    public void run() {
                        //动画效果
                        Animation animation = AnimationUtils.loadAnimation(SgfSplash6Activity.this, R.anim.my_anim_scale2);
                        tv_course.startAnimation(animation);
                        tv_course.setVisibility(View.VISIBLE);
                        mHandler.postDelayed(new Runnable() {

                            @Override
                            public void run() {
                                //动画效果
                                Animation animation = AnimationUtils.loadAnimation(SgfSplash6Activity.this, R.anim.my_anim_scale2);
                                tv_task.startAnimation(animation);
                                tv_task.setVisibility(View.VISIBLE);

                            }
                        }, 500);
                    }
                }, 500);
            }
        }, 500);
    }

    private void showAnimation(ArrayList textViews) {
        try {
            //菜单项弹出动画
            for (int i = 0; i < textViews.size(); i++) {
//                textViews.get(i).setOnClickListener(this);
                textViews.get(i).setVisibility(View.INVISIBLE);
                int finalI = i;
                mHandler.postDelayed(new Runnable() {

                    @Override
                    public void run() {
                        textViews.get(finalI).setVisibility(View.VISIBLE);

                        //动画效果1
//                        ValueAnimator fadeAnim = ObjectAnimator.ofFloat(textViews.get(finalI), "translationY", 600, 0);
//                        fadeAnim.setDuration(2000);
//                        KickBackAnimator kickAnimator = new KickBackAnimator();
//                        kickAnimator.setDuration(1500);
//                        fadeAnim.setEvaluator(kickAnimator);
//                        fadeAnim.start();

                        //动画效果2
//                        Animation animation = AnimationUtils.loadAnimation(SgfSplash6Activity.this, R.anim.anim_top_in);
//                        textViews.get(finalI).startAnimation(animation);

                        //动画效果3
//                        Animation animation = AnimationUtils.loadAnimation(SgfSplash6Activity.this, R.anim.my_anim_scale);
                        Animation animation = AnimationUtils.loadAnimation(SgfSplash6Activity.this, R.anim.my_anim_scale2);
                        textViews.get(finalI).startAnimation(animation);

                    }
                }, i * 50 + 1000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

3.布局代码:




    
    

        

        

        

        
    

4.xml动画

a.my_anim_scale2.xml




    

b.my_anim_scale.xml




    

Android 启动页过渡动画效果实现(二)_第3张图片

 

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //全屏
//        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_sgf_splash6);
        ButterKnife.bind(this);

        ArrayList textViews = new ArrayList<>();
        textViews.add(tv_sbs);
        textViews.add(tv_search);
        textViews.add(tv_course);
        textViews.add(tv_task);
//        showAnimation(textViews);

        tv_sbs.setVisibility(View.INVISIBLE);
        tv_search.setVisibility(View.INVISIBLE);
        tv_course.setVisibility(View.INVISIBLE);
        tv_task.setVisibility(View.INVISIBLE);
        Animation animation = AnimationUtils.loadAnimation(SgfSplash6Activity.this, R.anim.my_anim_translate2);
        iv_icon.startAnimation(animation);
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                showAnimation();//动画结束时执行
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

    }

 my_anim_translate2.xml   从上到下掉落弹性动画效果




    
    

 my_anim_translate3.xml    旋转渐变缩放一起执行动画效果




    

    

    

5.看看依赖:

apply plugin: 'com.android.application'

android {
    compileSdkVersion rootProject.ext.compileVersion

    // 使用 JDK 1.8
    compileOptions {
        targetCompatibility JavaVersion.VERSION_1_8
        sourceCompatibility JavaVersion.VERSION_1_8
    }
    lintOptions {
        abortOnError false
    }

    defaultConfig {
        // 无痛修改包名:https://www.jianshu.com/p/17327e191d2e
        applicationId "com.hjq.demo"
        minSdkVersion 19
        targetSdkVersion rootProject.ext.targetVersion
        versionCode 10
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

        // 仅保留中文语种的资源
        resConfig 'zh'

        // 仅保留 xxhdpi 图片资源(目前主流分辨率 1920 * 1080)
        resConfig 'xxhdpi'

        // 仅保留两种架构的 so 库
        ndk {
            // armeabi:已经淘汰(0%)
            // armeabi-v7a:曾经主流的架构平台(20%)
            // arm64-v8a:目前主流架构平台(80%)
            //"x86_64",
            abiFilters "armeabi-v7a", "arm64-v8a", "x86", "armeabi"
        }

        // 开启 Dex 分包
        multiDexEnabled true

        // 混淆配置
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-app.pro'

        javaCompileOptions {
            annotationProcessorOptions {
                // EventBus Apt 索引类生成位置
                arguments = [ eventBusIndex : applicationId + '.MyEventBusIndex' ]
            }
        }
    }

    // APK 签名的那些事:https://www.jianshu.com/p/a1f8e5896aa2
    signingConfigs {
        debug {
            storeFile file(StoreFile)
            storePassword StorePassword
            keyAlias KeyAlias
            keyPassword KeyPassword
        }
        release {
            storeFile file(StoreFile)
            storePassword StorePassword
            keyAlias KeyAlias
            keyPassword KeyPassword
        }
    }

    buildTypes {
        release {
            // 移除无用的资源文件
            shrinkResources true
            // ZipAlign 优化
            zipAlignEnabled true
            // 设置混淆
            minifyEnabled true
            // 正式环境签名
            signingConfig signingConfigs.release
            // 正式环境下的 BuglyId
            buildConfigField "String", "BUGLY_ID", "\"请自行替换 Bugly 上面的 AppID\""
        }

        debug {
            // 移除无用的资源文件
            shrinkResources false
            // ZipAlign 优化
            zipAlignEnabled false
            // 设置混淆
            minifyEnabled false
            // 开发环境签名
            signingConfig signingConfigs.debug
            // 开发环境下的 BuglyId
            buildConfigField "String", "BUGLY_ID", "\"请自行替换 Bugly 上面的 AppID\""
        }
    }

    // 默认渠道名
    flavorDimensions "default"
    // 友盟多渠道打包
    productFlavors {
        tencent {}  // 应用宝
        baidu {}    // 百度
        xiaomi {}   // 小米
        huawei {}   // 华为

        productFlavors.all { flavor ->
            flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
        }
    }

    // JNI 目录
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

    // 执行配置
    applicationVariants.all { variant ->

        // Apk 输出配置
        variant.outputs.all { output ->
            def appName = "AndroidProject"
            if (variant.buildType.name == 'debug') {
                outputFileName = appName + '_v' + versionName + '_' + variant.buildType.name + '.apk'
            } else {
                outputFileName = appName + '_v' + versionName + '_' + new Date().format("yyyyMMdd") + '_' + variant.productFlavors[0].name + '_' + variant.buildType.name + '.apk'
            }
        }

        // AndroidManifest 输出配置
        variant.outputs[0].processManifest.doLast {
            def manifestFile = "${manifestOutputDirectory}/AndroidManifest.xml"
            def updatedContent = new File(manifestFile).getText('UTF-8')
                    .replaceAll("UMENG_APPKEY_VALUE", "5cb16d93570df399fd0014e2") // 友盟 AppKey
                    .replaceAll("QQ_APPID_VALUE", "100424468") // QQ AppId
                    .replaceAll("QQ_APPKEY_VALUE", "c7394704798a158208a74ab60104f0ba") // QQ Key
                    .replaceAll("WX_APPID_VALUE", "wxdc1e388c3822c80b") // 微信 AppId
                    .replaceAll("WX_APPKEY_VALUE", "3baf1193c85774b3fd9d18447d76cab0") // 微信 Key
            new File(manifestFile).write(updatedContent, 'UTF-8')
        }
    }
}

// api 与 implementation 的区别:https://www.jianshu.com/p/8962d6ba936e
dependencies {
    // 依赖 libs 目录下所有 jar 包
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    // 依赖 libs 目录下所有 aar 包
    implementation fileTree(include: ['*.aar'], dir: 'libs')

    // 基础库(不包任何第三方框架)
    implementation project(':base')
    // 自定义 View
    implementation project(':widget')
    // Glide 隔离
    implementation project(':image')
    // 友盟隔离
    implementation project(':umeng')

    // 谷歌 Support 包
    implementation "androidx.appcompat:appcompat:$rootProject.ext.appcompatVersion"
    implementation "com.google.android.material:material:$rootProject.ext.materialVersion"

    // Dex 分包,解决 64k 方法问题
    implementation 'androidx.multidex:multidex:2.0.1'

    // ButterKnife 注解库:https://github.com/JakeWharton/butterknife
    implementation 'com.jakewharton:butterknife:10.1.0'
    annotationProcessor 'com.jakewharton:butterknife-compiler:10.1.0'

    // EventBus 事件总线:https://github.com/greenrobot/EventBus
    implementation "org.greenrobot:eventbus:3.1.1"
    annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.1.1'

    // 状态栏沉浸:https://github.com/gyf-dev/ImmersionBar
    implementation 'com.gyf.immersionbar:immersionbar:3.0.0'

    // 权限请求框架:https://github.com/getActivity/XXPermissions
    implementation 'com.hjq:xxpermissions:6.0'

    // 标题栏:https://github.com/getActivity/TitleBar
    implementation 'com.hjq:titlebar:6.0'

    // 吐司工具类:https://github.com/getActivity/ToastUtils
    implementation 'com.hjq:toast:8.0'

    // 支持放大缩放的 ImageView:https://github.com/chrisbanes/PhotoView
    implementation 'com.github.chrisbanes:PhotoView:2.3.0'
    // ViewPager 指示器:https://github.com/romandanylyk/PageIndicatorView
    implementation 'com.romandanylyk:pageindicatorview:1.0.3'

    // Bugly 异常捕捉:https://bugly.qq.com/docs/user-guide/instruction-manual-android/?v=20190418140644
    implementation 'com.tencent.bugly:crashreport:3.0.1'
    implementation 'com.tencent.bugly:nativecrashreport:3.7.1'

    // 本地异常捕捉框架:https://github.com/Ereza/CustomActivityOnCrash
    implementation 'cat.ereza:customactivityoncrash:2.2.0'

    // 内存泄漏捕捉:https://github.com/square/leakcanary
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
    releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'

    // 网络请求(待发布):https://github.com/getActivity/EasyHttp

    // 国际化:https://github.com/getActivity/MultiLanguages
    // 悬浮窗:https://github.com/getActivity/XToast
    // 上拉刷新下拉加载:https://github.com/scwang90/SmartRefreshLayout
    // 工具类:https://github.com/Blankj/AndroidUtilCode
    // 轮播图:https://github.com/bingoogolapple/BGABanner-Android
    // 二维码:https://github.com/bingoogolapple/BGAQRCode-Android
    // 第三方支付:https://github.com/getActivity/RxPay
    // Log 打印:https://github.com/elvishew/XLog
    // 图片压缩:https://github.com/Curzibn/Luban
    // 对象存储:https://github.com/leavesC/DoKV
    // 数据注入:https://github.com/JumeiRdGroup/Parceler

    implementation 'com.android.support:design:26.1.0'
    //约束布局
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    //第三方适配器
    implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'
    implementation 'com.google.code.gson:gson:2.8.0'
//    implementation 'com.github.bumptech.glide:glide:3.7.0'

    //通用标题栏
    implementation 'com.hjq:titlebar:6.0'
    implementation 'com.makeramen:roundedimageview:2.3.0'
    //高度自定义的开源安卓视频框架
    implementation 'cn.jzvd:jiaozivideoplayer:7.0.5'
    implementation 'com.danikula:videocache:2.7.0'
//    implementation 'com.github.bumptech.glide:glide:4.7.1'
    implementation 'com.github.bumptech.glide:glide:4.9.0'
    //
    annotationProcessor 'com.github.bumptech.glide:compiler:4.9.0'
    dependencies {
        implementation ('com.google.android.exoplayer:exoplayer:2.9.1'){

        }
    }
//    dependencies {
//        implementation ('com.github.bumptech.glide:glide:4.7.1'){
//
//        }
//    }
    implementation 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
    implementation 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.4'
//    implementation 'com.google.android.exoplayer:exoplayer:2.9.1'
    //圆形图片
    implementation 'de.hdodenhof:circleimageview:2.2.0'
    //弹簧动画效果
    implementation 'com.facebook.rebound:rebound:0.3.8'
    //抖音APP点赞效果实现,模仿抖音APP双击屏幕蹦出心图,特点: 1. 可以自定义图片 2. 可以自定义旋转角度 3. 超级简洁,占用内存小
    implementation 'com.github.KevinYou128:HotHeart:v1.2'

    //轮播图  https://github.com/bingoogolapple/BGABanner-Android
    implementation 'com.android.support:support-v4:latestVersion'
    implementation 'cn.bingoogolapple:bga-banner:2.2.7@aar'
    implementation 'com.squareup.retrofit2:retrofit:2.4.0'
    implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
    implementation 'cn.bingoogolapple:bga-baseadapter:1.2.9@aar'

    implementation 'com.facebook.fresco:fresco:1.5.0'
//    implementation 'com.android.support:multidex:1.+'
    //轮播图  https://github.com/bingoogolapple/BGABanner-Android

    //一个富有动感的Sheet(选择器)
    implementation 'com.github.zzz40500:AndroidSweetSheet:1.1.0'

    //实现九宫格框架
//   implementation 'com.wobiancao:imagenice9lib:1.0.1'
//    implementation('com.wobiancao:imagenice9lib:1.0.1') {
//        transitive = true;
//    }
    //阿里巴巴推出的一个RecyclerView得扩展库vlayout
    implementation ('com.alibaba.android:vlayout:1.2.8@aar') {
        transitive = true
    }
    //3D 外科调试工具,可发现您应用下的图层
    implementation 'com.jakewharton.scalpel:scalpel:1.1.2'
    //RecyclerView扩展库提供了高级功能。 (例如,Google的Inbox应用(例如滑动,Play Music应用(例如,拖放排序)
    implementation 'com.h6ah4i.android.widget.advrecyclerview:advrecyclerview:1.0.0'
    //
    implementation 'com.alibaba:fastjson:1.2.56'

    implementation 'com.flyco.tablayout:FlycoTabLayout_Lib:2.0.0@aar'
    implementation 'com.trello:rxlifecycle-components:0.6.1'
    implementation 'com.zhy:flowlayout-lib:1.0.1'

    //动画
    implementation 'com.daimajia.androidanimations:library:1.1.3@aar'
}

Android 启动页过渡动画效果实现(一)   

 Android 启动页过渡动画效果实现(二)

 

你可能感兴趣的:(启动页)