Android(安卓)启动页过渡动画效果实现(二)
16lz
2021-12-09
Android 启动页过渡动画效果实现(一)
Android 启动页过渡动画效果实现(二)
一.效果1:缩放、平移、渐变、弹簧弹性动画效果
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.布局代码:
<?xml version="1.0" encoding="utf-8"?>
5.xml动画:
anim_top_in.xml
<?xml version="1.0" encoding="utf-8"?>
fade_out.xml是Android API 28自带的 :
<?xml version="1.0" encoding="utf-8"?>
二.效果2:由小到大缩放动画效果
1.效果图:
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.布局代码:
<?xml version="1.0" encoding="utf-8"?>
4.xml动画
a.my_anim_scale2.xml
<?xml version="1.0" encoding="utf-8"?>
b.my_anim_scale.xml
<?xml version="1.0" encoding="utf-8"?>
@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 从上到下掉落弹性动画效果
<?xml version="1.0" encoding="utf-8"?>
my_anim_translate3.xml 旋转渐变缩放一起执行动画效果
<?xml version="1.0" encoding="utf-8"?>
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/8962d6ba936edependencies { // 依赖 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 启动页过渡动画效果实现(二)
更多相关文章
- Android用xml写动画效果
- Android(安卓)属性系统 详解
- RelativeLayout布局,以及部分常用属性介绍scaleType/gravity/layo
- android launcher2开发之 有抽屉改成无抽屉
- linearLayout 和 relativeLayout的属性区别
- ImageView的scaletype属性
- Android(安卓)View类属性及方法
- 深入Gradle插件开发
- [Android][SystemUI]navigationbar 3个虚拟键隐藏与显示