├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── dictionaries │ └── wangchenlong.xml ├── encodings.xml ├── gradle.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── me │ │ └── chunyu │ │ └── spike │ │ └── wcl_circle_reveal_demo │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── me │ │ │ └── chunyu │ │ │ └── spike │ │ │ └── wcl_circle_reveal_demo │ │ │ ├── GuiUtils.java │ │ │ ├── MainActivity.java │ │ │ └── OtherActivity.java │ └── res │ │ ├── drawable-nodpi │ │ └── ic_close_white.png │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── activity_other.xml │ │ └── content_main.xml │ │ ├── menu │ │ └── menu_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── transition-v21 │ │ └── arc_motion.xml │ │ ├── values-v21 │ │ └── styles.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── me │ └── chunyu │ └── spike │ └── wcl_circle_reveal_demo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | wcl-circle-reveal-demo -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/dictionaries/wangchenlong.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | 26 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | Android > Lint > Correctness 46 | 47 | 48 | C/C++ 49 | 50 | 51 | Data flow issuesJava 52 | 53 | 54 | General 55 | 56 | 57 | Java 58 | 59 | 60 | Unused codeC/C++ 61 | 62 | 63 | 64 | 65 | Android 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 87 | 88 | 89 | 90 | 91 | 1.8 92 | 93 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wcl-circle-reveal-demo 2 | 3 | 实现页面展开中圆形爆炸展开的动画效果 4 | 5 | 工程文档:https://www.jianshu.com/p/e30510b83e0e 6 | 7 | 本文的合集已经编著成书,**[高级Android开发强化实战](https://item.jd.com/12385680.html)**,欢迎各位读友的建议和指导。 8 | 9 | 在京东即可购买:https://item.jd.com/12385680.html 10 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id "me.tatarka.retrolambda" version "3.2.5" 3 | } 4 | 5 | apply plugin: 'com.android.application' 6 | 7 | android { 8 | compileSdkVersion 23 9 | buildToolsVersion '25.0.0' 10 | 11 | defaultConfig { 12 | applicationId "me.chunyu.spike.wcl_circle_reveal_demo" 13 | minSdkVersion 14 14 | targetSdkVersion 23 15 | versionCode 1 16 | versionName "1.0" 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | compileOptions { 25 | sourceCompatibility JavaVersion.VERSION_1_8 26 | targetCompatibility JavaVersion.VERSION_1_8 27 | } 28 | } 29 | 30 | dependencies { 31 | compile fileTree(dir: 'libs', include: ['*.jar']) 32 | testCompile 'junit:junit:4.12' 33 | compile 'com.android.support:appcompat-v7:23.1.1' 34 | compile 'com.android.support:design:23.1.1' 35 | compile 'com.jakewharton:butterknife:7.0.1' 36 | } 37 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/wangchenlong/Installations/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/me/chunyu/spike/wcl_circle_reveal_demo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.wcl_circle_reveal_demo; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/wcl_circle_reveal_demo/GuiUtils.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.wcl_circle_reveal_demo; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.annotation.TargetApi; 6 | import android.content.Context; 7 | import android.os.Build; 8 | import android.support.annotation.ColorRes; 9 | import android.support.v4.content.ContextCompat; 10 | import android.view.View; 11 | import android.view.ViewAnimationUtils; 12 | import android.view.animation.AccelerateDecelerateInterpolator; 13 | 14 | /** 15 | * 动画效果 16 | *

17 | * Created by wangchenlong on 16/2/26. 18 | */ 19 | public class GuiUtils { 20 | public interface OnRevealAnimationListener { 21 | void onRevealHide(); 22 | 23 | void onRevealShow(); 24 | } 25 | 26 | // 圆圈爆炸效果显示 27 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 28 | public static void animateRevealShow( 29 | final Context context, final View view, 30 | final int startRadius, @ColorRes int color, 31 | OnRevealAnimationListener listener) { 32 | int cx = (view.getLeft() + view.getRight()) / 2; 33 | int cy = (view.getTop() + view.getBottom()) / 2; 34 | 35 | float finalRadius = (float) Math.hypot(view.getWidth(), view.getHeight()); 36 | 37 | // 设置圆形显示动画 38 | Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, startRadius, finalRadius); 39 | anim.setDuration(300); 40 | anim.setInterpolator(new AccelerateDecelerateInterpolator()); 41 | anim.addListener(new AnimatorListenerAdapter() { 42 | @Override public void onAnimationEnd(Animator animation) { 43 | super.onAnimationEnd(animation); 44 | view.setVisibility(View.VISIBLE); 45 | listener.onRevealShow(); 46 | } 47 | 48 | @Override public void onAnimationStart(Animator animation) { 49 | super.onAnimationStart(animation); 50 | view.setBackgroundColor(ContextCompat.getColor(context, color)); 51 | } 52 | }); 53 | 54 | anim.start(); 55 | } 56 | 57 | // 圆圈凝聚效果 58 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 59 | public static void animateRevealHide( 60 | final Context context, final View view, 61 | final int finalRadius, @ColorRes int color, 62 | OnRevealAnimationListener listener 63 | ) { 64 | int cx = (view.getLeft() + view.getRight()) / 2; 65 | int cy = (view.getTop() + view.getBottom()) / 2; 66 | int initialRadius = view.getWidth(); 67 | // 与入场动画的区别就是圆圈起始和终止的半径相反 68 | Animator anim = ViewAnimationUtils.createCircularReveal(view, cx, cy, initialRadius, finalRadius); 69 | anim.setDuration(300); 70 | anim.setInterpolator(new AccelerateDecelerateInterpolator()); 71 | anim.addListener(new AnimatorListenerAdapter() { 72 | @Override public void onAnimationStart(Animator animation) { 73 | super.onAnimationStart(animation); 74 | view.setBackgroundColor(ContextCompat.getColor(context, color)); 75 | } 76 | 77 | @Override public void onAnimationEnd(Animator animation) { 78 | super.onAnimationEnd(animation); 79 | listener.onRevealHide(); 80 | view.setVisibility(View.INVISIBLE); 81 | } 82 | }); 83 | anim.start(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/wcl_circle_reveal_demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.wcl_circle_reveal_demo; 2 | 3 | import android.app.ActivityOptions; 4 | import android.content.Intent; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.support.design.widget.FloatingActionButton; 8 | import android.support.design.widget.Snackbar; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.Menu; 12 | import android.view.MenuItem; 13 | import android.view.View; 14 | 15 | import butterknife.Bind; 16 | import butterknife.ButterKnife; 17 | 18 | public class MainActivity extends AppCompatActivity { 19 | 20 | @Bind(R.id.fab) FloatingActionButton mFab; 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_main); 26 | ButterKnife.bind(this); 27 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 28 | setSupportActionBar(toolbar); 29 | } 30 | 31 | @Override 32 | public boolean onCreateOptionsMenu(Menu menu) { 33 | // Inflate the menu; this adds items to the action bar if it is present. 34 | getMenuInflater().inflate(R.menu.menu_main, menu); 35 | return true; 36 | } 37 | 38 | @Override 39 | public boolean onOptionsItemSelected(MenuItem item) { 40 | // Handle action bar item clicks here. The action bar will 41 | // automatically handle clicks on the Home/Up button, so long 42 | // as you specify a parent activity in AndroidManifest.xml. 43 | int id = item.getItemId(); 44 | 45 | //noinspection SimplifiableIfStatement 46 | if (id == R.id.action_settings) { 47 | return true; 48 | } 49 | 50 | return super.onOptionsItemSelected(item); 51 | } 52 | 53 | // Fab的跳转事件 54 | public void startOtherActivity(View view) { 55 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 56 | ActivityOptions options = 57 | ActivityOptions.makeSceneTransitionAnimation(this, mFab, mFab.getTransitionName()); 58 | startActivity(new Intent(this, OtherActivity.class), options.toBundle()); 59 | } else { 60 | startActivity(new Intent(this, OtherActivity.class)); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /app/src/main/java/me/chunyu/spike/wcl_circle_reveal_demo/OtherActivity.java: -------------------------------------------------------------------------------- 1 | package me.chunyu.spike.wcl_circle_reveal_demo; 2 | 3 | import android.annotation.TargetApi; 4 | import android.os.Build; 5 | import android.os.Bundle; 6 | import android.os.Handler; 7 | import android.os.Looper; 8 | import android.support.annotation.Nullable; 9 | import android.support.design.widget.FloatingActionButton; 10 | import android.support.v7.app.AppCompatActivity; 11 | import android.transition.Fade; 12 | import android.transition.Transition; 13 | import android.transition.TransitionInflater; 14 | import android.view.View; 15 | import android.view.animation.Animation; 16 | import android.view.animation.AnimationUtils; 17 | import android.widget.ImageView; 18 | import android.widget.RelativeLayout; 19 | import android.widget.TextView; 20 | 21 | import butterknife.Bind; 22 | import butterknife.ButterKnife; 23 | 24 | /** 25 | * 跳转的Activity 26 | *

27 | * Created by wangchenlong on 16/2/26. 28 | */ 29 | public class OtherActivity extends AppCompatActivity { 30 | 31 | @Bind(R.id.other_fab_circle) FloatingActionButton mFabCircle; 32 | @Bind(R.id.other_tv_container) TextView mTvContainer; 33 | @Bind(R.id.other_iv_close) ImageView mIvClose; 34 | @Bind(R.id.other_rl_container) RelativeLayout mRlContainer; 35 | 36 | @Override protected void onCreate(@Nullable Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_other); 39 | ButterKnife.bind(this); 40 | 41 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 42 | setupEnterAnimation(); // 入场动画 43 | setupExitAnimation(); // 退场动画 44 | } else { 45 | initViews(); 46 | } 47 | } 48 | 49 | // 入场动画 50 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 51 | private void setupEnterAnimation() { 52 | Transition transition = TransitionInflater.from(this) 53 | .inflateTransition(R.transition.arc_motion); 54 | transition.addListener(new Transition.TransitionListener() { 55 | @Override public void onTransitionStart(Transition transition) { 56 | 57 | } 58 | 59 | @Override public void onTransitionEnd(Transition transition) { 60 | transition.removeListener(this); 61 | animateRevealShow(); 62 | } 63 | 64 | @Override public void onTransitionCancel(Transition transition) { 65 | 66 | } 67 | 68 | @Override public void onTransitionPause(Transition transition) { 69 | 70 | } 71 | 72 | @Override public void onTransitionResume(Transition transition) { 73 | 74 | } 75 | }); 76 | getWindow().setSharedElementEnterTransition(transition); 77 | } 78 | 79 | // 动画展示 80 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 81 | private void animateRevealShow() { 82 | GuiUtils.animateRevealShow( 83 | this, mRlContainer, 84 | mFabCircle.getWidth() / 2, R.color.colorAccent, 85 | new GuiUtils.OnRevealAnimationListener() { 86 | @Override public void onRevealHide() { 87 | 88 | } 89 | 90 | @Override public void onRevealShow() { 91 | initViews(); 92 | } 93 | }); 94 | } 95 | 96 | // 退出动画 97 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 98 | private void setupExitAnimation() { 99 | Fade fade = new Fade(); 100 | fade.setDuration(300); 101 | getWindow().setReturnTransition(fade); 102 | } 103 | 104 | // 初始化视图 105 | private void initViews() { 106 | new Handler(Looper.getMainLooper()).post(() -> { 107 | Animation animation = AnimationUtils.loadAnimation(this, android.R.anim.fade_in); 108 | animation.setDuration(300); 109 | 110 | mTvContainer.setVisibility(View.VISIBLE); 111 | mIvClose.setVisibility(View.VISIBLE); 112 | mTvContainer.startAnimation(animation); 113 | mIvClose.setAnimation(animation); 114 | }); 115 | } 116 | 117 | // 退出按钮 118 | public void backActivity(View view) { 119 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 120 | onBackPressed(); 121 | } else { 122 | defaultBackPressed(); 123 | } 124 | } 125 | 126 | // 退出事件 127 | @Override public void onBackPressed() { 128 | GuiUtils.animateRevealHide( 129 | this, mRlContainer, 130 | mFabCircle.getWidth() / 2, R.color.colorAccent, 131 | new GuiUtils.OnRevealAnimationListener() { 132 | @Override 133 | public void onRevealHide() { 134 | defaultBackPressed(); 135 | } 136 | 137 | @Override 138 | public void onRevealShow() { 139 | 140 | } 141 | }); 142 | } 143 | 144 | // 默认回退 145 | private void defaultBackPressed() { 146 | super.onBackPressed(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/ic_close_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/wcl-circle-reveal-demo/3ff38d62d3ce45bcd982809a97ca2cb552c88b84/app/src/main/res/drawable-nodpi/ic_close_white.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_other.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 22 | 23 | 35 | 36 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/layout/content_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | 16 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 |

5 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/wcl-circle-reveal-demo/3ff38d62d3ce45bcd982809a97ca2cb552c88b84/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/wcl-circle-reveal-demo/3ff38d62d3ce45bcd982809a97ca2cb552c88b84/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/wcl-circle-reveal-demo/3ff38d62d3ce45bcd982809a97ca2cb552c88b84/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/wcl-circle-reveal-demo/3ff38d62d3ce45bcd982809a97ca2cb552c88b84/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpikeKing/wcl-circle-reveal-demo/3ff38d62d3ce45bcd982809a97ca2cb552c88b84/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/transition-v21/arc_motion.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 16dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | wcl-circle-reveal-demo 3 | Settings 4 | 动画显示: (1)角度滑动 (2)爆炸效果 5 | transition_reveal 6 | 广告\n(Advertisement) 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |