├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── circulardemo ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── hu │ │ └── gordon │ │ └── circulardemo │ │ ├── MainActivity.java │ │ └── fragments │ │ ├── RadialFragment.java │ │ ├── RevealFragment.java │ │ └── TransformFragment.java │ └── res │ ├── drawable-hdpi │ ├── ic_drawer.png │ ├── ic_menu.png │ ├── ic_radial.png │ ├── ic_refresh_white_36dp.png │ ├── ic_reveal.png │ ├── ic_transform.png │ ├── img_camera.png │ ├── img_cloud_empty.png │ └── img_cloud_full.png │ ├── drawable-mdpi │ ├── ic_drawer.png │ ├── ic_menu.png │ ├── ic_radial.png │ ├── ic_refresh_white_36dp.png │ ├── ic_reveal.png │ ├── ic_transform.png │ ├── img_camera.png │ ├── img_cloud_empty.png │ └── img_cloud_full.png │ ├── drawable-xhdpi │ ├── ic_drawer.png │ ├── ic_menu.png │ ├── ic_radial.png │ ├── ic_refresh_white_36dp.png │ ├── ic_reveal.png │ ├── ic_transform.png │ ├── img_camera.png │ ├── img_cloud_empty.png │ └── img_cloud_full.png │ ├── drawable-xxhdpi │ ├── ic_drawer.png │ ├── ic_menu.png │ ├── ic_radial.png │ ├── ic_refresh_white_36dp.png │ ├── ic_reveal.png │ ├── ic_transform.png │ ├── img_camera.png │ ├── img_cloud_empty.png │ └── img_cloud_full.png │ ├── drawable-xxxhdpi │ ├── ic_menu.png │ ├── ic_radial.png │ ├── ic_refresh_white_36dp.png │ ├── ic_reveal.png │ ├── ic_transform.png │ ├── img_camera.png │ ├── img_cloud_empty.png │ └── img_cloud_full.png │ ├── drawable │ └── autsoft_white.png │ ├── layout │ ├── activity_main.xml │ ├── fragment_main.xml │ ├── fragment_radial.xml │ ├── fragment_reveal.xml │ ├── fragment_transform.xml │ └── nav_header.xml │ ├── menu │ └── main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── circulartools ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── hu │ │ └── aut │ │ └── utillib │ │ └── circular │ │ ├── animation │ │ ├── CircularAnimationUtils.java │ │ ├── CircularAnimator.java │ │ ├── RadialReactionDelegate.java │ │ ├── RadialReactionListener.java │ │ └── RadialReactionParent.java │ │ └── widget │ │ ├── CircularFrameLayout.java │ │ └── RadialReactionLinearLayout.java │ └── res │ └── values │ └── strings.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | gen 3 | .project 4 | .classpath 5 | .settings 6 | .idea 7 | *.iml 8 | *.ipr 9 | *.iws 10 | out 11 | target 12 | release.properties 13 | pom.xml.* 14 | build.xml 15 | local.properties 16 | proguard.cfg 17 | .DS_Store 18 | .gradle 19 | build 20 | app/build -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 AutSoft Kft. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | CircularTools 2 | ============== 3 | Circle based animations for Android (min. API 11) 4 | 5 | Currently implemented: 6 | - Circular reveal 7 | - Circular transform 8 | - Radial reaction 9 | 10 | |**Reveal:**YouTube|**Transform:**YouTube|**Radial reaction:**YouTube| 11 | |---------------|-----------|-----------| 12 | |Reveal DEMO|Transform DEMO|Radial reaction DEMO| 13 | 14 | 15 | Sample 16 | ------ 17 | Demo in the source and releases 18 | 19 | Note 20 | ----- 21 | - it's a fork from https://github.com/ozodrukh/CircularReveal/ 22 | - independent from Jake Wharton's NineOldsAndroid 23 | - the returned `animator` is an `ObjectAnimator` so you can reverse it. 24 | 25 | Limitations 26 | ----------- 27 | **For reveal and transform:** 28 | - it will never use the native `ViewAnimationUtils.createCircularReveal` method 29 | - currently there is an issue: views with elevation cannot be animated correctly on Lollipop and above. 30 | - workaround A: set the LayerType of the target (or source) view to LayerType.SOFTWARE 31 | - workaround B: wrap your target or (source) view with a simple layout, without elevation, and animate that. Demo reveal uses this method. 32 | - hardware acceleration cannot be used in every situation. See table below: 33 | 34 | | | API 11-17 | API 18+ | 35 | |---------------|-----------|-----------| 36 | | **Reveal** | Software | Hardware | 37 | | **Transform** | Software | Hardware | 38 | 39 | **For radial reaction** 40 | - only one reaction can be animated at the same time, in the same `RadialReactionParent` 41 | - only one layout implemented yet: a LinearLayout. 42 | - once an affectedView is reached, it will be removed from the list in the `RadialReactionParent`. If you want to animate multiple times, you have to add the views again. See demo for details. 43 | 44 | Usage 45 | ------ 46 | 47 | For reveal and transform you have to wrap your animated views with a `CircularFrameLayout`. 48 | 49 | ```xml 50 | 54 | 55 | 56 | 57 | 58 | ``` 59 | **Transform:** 60 | ```java 61 | //myTargetView & mySourceView are children in the CircularFrameLayout 62 | float finalRadius = CircularAnimationUtils.hypo(width, height); 63 | 64 | //getCenter computes from 2 view: One is touched, and one will be animated, but you can use anything for center 65 | int[] center = CircularAnimationUtils.getCenter(fab, myTargetView); 66 | 67 | animator = CircularAnimationUtils.createCircularTransform(myTargetView, mySourceView, center[0], center[1], 0F, finalRadius); 68 | animator.setInterpolator(new AccelerateDecelerateInterpolator()); 69 | animator.setDuration(1500); 70 | animator.start(); 71 | 72 | ``` 73 | 74 | **Reveal:** 75 | ```java 76 | //myView is a child in the CircularFrameLayout 77 | float finalRadius = CircularAnimationUtils.hypo(width, height); 78 | 79 | //getCenter computes from 2 view: One is touched, and one will be animated, but you can use anything for center 80 | int[] center = CircularAnimationUtils.getCenter(fab, myView); 81 | 82 | animator = CircularAnimationUtils.createCircularReveal(myView, center[0], center[1], 0, finalRadius); 83 | animator.setInterpolator(new AccelerateDecelerateInterpolator()); 84 | animator.setDuration(1500); 85 | animator.start(); 86 | 87 | ``` 88 | 89 | For radial reaction you have to wrap your views -that are affected by the radial reaction- with a `RadialReactionParent`. 90 | - Wrap your view 91 | - Add a listener to it (this listener will be notified when the invisible circle reaches an affected view) 92 | - Add views to the parent's watchlist by calling `addAffectedView(View v)` 93 | - Create animation and start it 94 | - Get notified when the radial reaction's invisible circle reaches one of the affected view 95 | 96 | ```xml 97 | 101 | 102 | 110 | 111 | 112 | 113 | 114 | ``` 115 | **Radial reaction:** 116 | ```java 117 | reactionParent = (RadialReactionParent) view.findViewById(R.id.reaction_parent); 118 | reactionParent.addListener(this); 119 | 120 | //add views 121 | reactionParent.addAffectedView(child1); 122 | 123 | ObjectAnimator animator = CircularAnimationUtils.createRadialReaction(reactionParent, fab, "action"); 124 | animator.setInterpolator(new AccelerateDecelerateInterpolator()); 125 | animator.setDuration(1500); 126 | animator.start(); 127 | 128 | ... 129 | 130 | @Override 131 | public void onRadialReaction(View affectedView, String action) { 132 | //Do what you want with the view 133 | } 134 | 135 | ``` 136 | 137 | How to add dependency 138 | ===================== 139 | 140 | This library is not released in Maven Central, but instead you can use [JitPack](https://www.jitpack.io/) 141 | 142 | add remote maven url 143 | 144 | ```groovy 145 | repositories { 146 | maven { 147 | url "https://jitpack.io" 148 | } 149 | } 150 | ``` 151 | 152 | then add a library dependency 153 | 154 | ```groovy 155 | dependencies { 156 | compile 'com.github.AutSoft:CircularTools:1.1.0' 157 | } 158 | ``` 159 | 160 | 161 | License 162 | -------- 163 | 164 | The MIT License (MIT) 165 | 166 | Copyright (c) 2015 AutSoft Kft. 167 | 168 | Permission is hereby granted, free of charge, to any person obtaining a copy 169 | of this software and associated documentation files (the "Software"), to deal 170 | in the Software without restriction, including without limitation the rights 171 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 172 | copies of the Software, and to permit persons to whom the Software is 173 | furnished to do so, subject to the following conditions: 174 | 175 | The above copyright notice and this permission notice shall be included in 176 | all copies or substantial portions of the Software. 177 | 178 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 179 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 180 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 181 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 182 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 183 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 184 | THE SOFTWARE. 185 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.0.0' 9 | classpath 'com.github.dcendents:android-maven-plugin:1.2' 10 | // NOTE: Do not place your application dependencies here; they belong 11 | // in the individual module build.gradle files 12 | } 13 | } 14 | 15 | allprojects { 16 | repositories { 17 | jcenter() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /circulardemo/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /circulardemo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | defaultConfig { 7 | applicationId "hu.gordon.circulardemo" 8 | minSdkVersion 11 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | productFlavors { 20 | } 21 | } 22 | 23 | repositories { 24 | maven { 25 | url "https://jitpack.io" 26 | maven { 27 | url 'http://raw.github.com/wada811/Android-Material-Design-Colors/master/repository/' 28 | } 29 | } 30 | } 31 | 32 | dependencies { 33 | compile project(':circulartools') 34 | compile 'com.android.support:design:22.2.0' 35 | compile 'com.android.support:appcompat-v7:22.2.0' 36 | compile 'com.android.support:cardview-v7:22.2.0' 37 | } 38 | -------------------------------------------------------------------------------- /circulardemo/proguard-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/proguard-rules.pro -------------------------------------------------------------------------------- /circulardemo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /circulardemo/src/main/java/hu/gordon/circulardemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package hu.gordon.circulardemo; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.NavigationView; 5 | import android.support.v4.app.FragmentManager; 6 | import android.support.v4.view.GravityCompat; 7 | import android.support.v4.widget.DrawerLayout; 8 | import android.support.v7.app.ActionBar; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.support.v7.widget.Toolbar; 11 | import android.view.MenuItem; 12 | 13 | import hu.gordon.circulardemo.fragments.RadialFragment; 14 | import hu.gordon.circulardemo.fragments.RevealFragment; 15 | import hu.gordon.circulardemo.fragments.TransformFragment; 16 | 17 | 18 | public class MainActivity extends AppCompatActivity { 19 | 20 | private DrawerLayout mDrawerLayout; 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_main); 26 | 27 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 28 | setSupportActionBar(toolbar); 29 | 30 | final ActionBar ab = getSupportActionBar(); 31 | ab.setHomeAsUpIndicator(R.drawable.ic_menu); 32 | ab.setDisplayHomeAsUpEnabled(true); 33 | 34 | mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout); 35 | 36 | NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); 37 | if (navigationView != null) { 38 | setupDrawerContent(navigationView); 39 | } 40 | 41 | FragmentManager fm = getSupportFragmentManager(); 42 | fm.beginTransaction().add(R.id.fragment, new RevealFragment(), RevealFragment.TAG).commit(); 43 | } 44 | 45 | @Override 46 | public boolean onOptionsItemSelected(MenuItem item) { 47 | switch (item.getItemId()) { 48 | case android.R.id.home: 49 | mDrawerLayout.openDrawer(GravityCompat.START); 50 | return true; 51 | } 52 | return super.onOptionsItemSelected(item); 53 | } 54 | 55 | private void setupDrawerContent(NavigationView navigationView) { 56 | navigationView.setNavigationItemSelectedListener( 57 | new NavigationView.OnNavigationItemSelectedListener() { 58 | @Override 59 | public boolean onNavigationItemSelected(MenuItem menuItem) { 60 | menuItem.setChecked(true); 61 | 62 | FragmentManager fm = getSupportFragmentManager(); 63 | 64 | switch (menuItem.getItemId()) { 65 | case R.id.navigation_item_1: 66 | fm.beginTransaction().replace(R.id.fragment, new RevealFragment()).commit(); 67 | break; 68 | case R.id.navigation_item_2: 69 | fm.beginTransaction().replace(R.id.fragment, new TransformFragment()).commit(); 70 | break; 71 | case R.id.navigation_item_3: 72 | fm.beginTransaction().replace(R.id.fragment, new RadialFragment()).commit(); 73 | break; 74 | } 75 | 76 | mDrawerLayout.closeDrawers(); 77 | return true; 78 | } 79 | }); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /circulardemo/src/main/java/hu/gordon/circulardemo/fragments/RadialFragment.java: -------------------------------------------------------------------------------- 1 | package hu.gordon.circulardemo.fragments; 2 | 3 | 4 | import android.animation.Animator; 5 | import android.animation.ObjectAnimator; 6 | import android.os.Bundle; 7 | import android.support.design.widget.FloatingActionButton; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | import android.view.animation.AccelerateDecelerateInterpolator; 13 | import android.view.animation.AlphaAnimation; 14 | import android.view.animation.Animation; 15 | import android.view.animation.AnimationSet; 16 | import android.view.animation.DecelerateInterpolator; 17 | import android.view.animation.ScaleAnimation; 18 | 19 | import java.util.ArrayList; 20 | 21 | import hu.aut.utillib.circular.animation.CircularAnimationUtils; 22 | import hu.aut.utillib.circular.animation.RadialReactionListener; 23 | import hu.aut.utillib.circular.animation.RadialReactionParent; 24 | import hu.gordon.circulardemo.R; 25 | 26 | /** 27 | * A simple {@link Fragment} subclass. 28 | */ 29 | public class RadialFragment extends Fragment implements RadialReactionListener, Animator.AnimatorListener { 30 | 31 | static final String RADIAL_DEMO_ACTION = "fab_action"; 32 | 33 | RadialReactionParent reactionParent; 34 | boolean animationInProgress = false; 35 | boolean isAppearing = true; 36 | ArrayList childList; 37 | 38 | 39 | @Override 40 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 41 | Bundle savedInstanceState) { 42 | // Inflate the layout for this fragment 43 | return inflater.inflate(R.layout.fragment_radial, container, false); 44 | } 45 | 46 | @Override 47 | public void onViewCreated(View view, Bundle savedInstanceState) { 48 | super.onViewCreated(view, savedInstanceState); 49 | 50 | reactionParent = (RadialReactionParent) view.findViewById(R.id.reaction_parent); 51 | reactionParent.addListener(this); 52 | 53 | childList = new ArrayList<>(); 54 | 55 | childList.add(view.findViewById(R.id.child_1)); 56 | childList.add(view.findViewById(R.id.child_2)); 57 | childList.add(view.findViewById(R.id.child_3)); 58 | childList.add(view.findViewById(R.id.child_4)); 59 | childList.add(view.findViewById(R.id.child_5)); 60 | childList.add(view.findViewById(R.id.child_6)); 61 | childList.add(view.findViewById(R.id.child_7)); 62 | childList.add(view.findViewById(R.id.child_8)); 63 | childList.add(view.findViewById(R.id.child_9)); 64 | 65 | final FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fab); 66 | fab.setOnClickListener(new View.OnClickListener() { 67 | @Override 68 | public void onClick(View v) { 69 | if (!animationInProgress) { 70 | reactionParent.addAffectedViews(childList); 71 | ObjectAnimator animator = CircularAnimationUtils.createRadialReaction(reactionParent, fab, RADIAL_DEMO_ACTION); 72 | animator.setInterpolator(new AccelerateDecelerateInterpolator()); 73 | animator.setDuration(1500); 74 | animator.addListener(RadialFragment.this); 75 | animator.start(); 76 | } 77 | } 78 | }); 79 | 80 | } 81 | 82 | @Override 83 | public void onRadialReaction(final View affectedView, String action) { 84 | if (action == RADIAL_DEMO_ACTION) { 85 | if (isAppearing) { 86 | Animation fadeIn = new AlphaAnimation(0.0F, 1.0F); 87 | fadeIn.setInterpolator(new DecelerateInterpolator()); 88 | fadeIn.setDuration(300); 89 | 90 | Animation scale = new ScaleAnimation(0.5F, 1.0F, 0.5F, 1.0F, 0.5F, 0.5F); 91 | scale.setInterpolator(new AccelerateDecelerateInterpolator()); 92 | scale.setDuration(300); 93 | 94 | AnimationSet animationSet = new AnimationSet(false); 95 | animationSet.addAnimation(fadeIn); 96 | animationSet.addAnimation(scale); 97 | animationSet.setAnimationListener(new Animation.AnimationListener() { 98 | @Override 99 | public void onAnimationStart(Animation animation) { 100 | affectedView.setVisibility(View.VISIBLE); 101 | } 102 | 103 | @Override 104 | public void onAnimationEnd(Animation animation) { 105 | 106 | } 107 | 108 | @Override 109 | public void onAnimationRepeat(Animation animation) { 110 | 111 | } 112 | }); 113 | affectedView.startAnimation(animationSet); 114 | } else { 115 | Animation fadeOut = new AlphaAnimation(1.0F, 0.0F); 116 | fadeOut.setInterpolator(new DecelerateInterpolator()); 117 | fadeOut.setDuration(300); 118 | 119 | Animation scale = new ScaleAnimation(1.0F, 0.5F, 1.0F, 0.5F, 0.5F, 0.5F); 120 | scale.setInterpolator(new AccelerateDecelerateInterpolator()); 121 | scale.setDuration(300); 122 | 123 | AnimationSet animationSet = new AnimationSet(false); 124 | animationSet.addAnimation(fadeOut); 125 | animationSet.addAnimation(scale); 126 | animationSet.setAnimationListener(new Animation.AnimationListener() { 127 | @Override 128 | public void onAnimationStart(Animation animation) { 129 | 130 | } 131 | 132 | @Override 133 | public void onAnimationEnd(Animation animation) { 134 | affectedView.setVisibility(View.INVISIBLE); 135 | } 136 | 137 | @Override 138 | public void onAnimationRepeat(Animation animation) { 139 | 140 | } 141 | }); 142 | affectedView.startAnimation(animationSet); 143 | } 144 | } 145 | } 146 | 147 | @Override 148 | public void onAnimationStart(Animator animation) { 149 | animationInProgress = true; 150 | } 151 | 152 | @Override 153 | public void onAnimationEnd(Animator animation) { 154 | animationInProgress = false; 155 | isAppearing = !isAppearing; 156 | } 157 | 158 | @Override 159 | public void onAnimationCancel(Animator animation) { 160 | 161 | } 162 | 163 | @Override 164 | public void onAnimationRepeat(Animator animation) { 165 | 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /circulardemo/src/main/java/hu/gordon/circulardemo/fragments/RevealFragment.java: -------------------------------------------------------------------------------- 1 | package hu.gordon.circulardemo.fragments; 2 | 3 | 4 | import android.animation.ObjectAnimator; 5 | import android.graphics.Point; 6 | import android.os.Bundle; 7 | import android.support.design.widget.FloatingActionButton; 8 | import android.support.v4.app.Fragment; 9 | import android.view.Display; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.view.animation.AccelerateDecelerateInterpolator; 14 | 15 | import hu.aut.utillib.circular.animation.CircularAnimationUtils; 16 | import hu.gordon.circulardemo.R; 17 | 18 | public class RevealFragment extends Fragment { 19 | 20 | public static final String TAG = RevealFragment.class.getSimpleName(); 21 | 22 | private int screenWidth; 23 | private int screenHeight; 24 | private FloatingActionButton fab; 25 | private View myView; 26 | 27 | @Override 28 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 29 | Bundle savedInstanceState) { 30 | // Inflate the layout for this fragment 31 | return inflater.inflate(R.layout.fragment_reveal, container, false); 32 | } 33 | 34 | @Override 35 | public void onViewCreated(View view, Bundle savedInstanceState) { 36 | super.onViewCreated(view, savedInstanceState); 37 | 38 | Display display = getActivity().getWindowManager().getDefaultDisplay(); 39 | 40 | if (android.os.Build.VERSION.SDK_INT >= 13) { 41 | Point size = new Point(); 42 | display.getSize(size); 43 | screenWidth = size.x; 44 | screenHeight = size.y; 45 | } else { 46 | screenWidth = display.getWidth(); 47 | screenHeight = display.getHeight(); 48 | } 49 | 50 | myView = view.findViewById(R.id.linear); 51 | myView.setOnClickListener(new View.OnClickListener() { 52 | @Override 53 | public void onClick(View view) { 54 | myView.setVisibility(View.INVISIBLE); 55 | } 56 | }); 57 | fab = (FloatingActionButton) view.findViewById(R.id.fab); 58 | fab.setOnClickListener(new View.OnClickListener() { 59 | @Override 60 | public void onClick(View view) { 61 | 62 | if (myView.getVisibility() == View.VISIBLE) { 63 | return; 64 | } 65 | 66 | // 67 | // Pre-calculations 68 | // 69 | // get the final radius for the clipping circle 70 | 71 | int[] myViewLocation = new int[2]; 72 | myView.getLocationInWindow(myViewLocation); 73 | 74 | float finalRadius = CircularAnimationUtils.hypo(screenWidth - myViewLocation[0], screenHeight - myViewLocation[1]); 75 | int[] center = CircularAnimationUtils.getCenter(fab, (View) myView.getParent()); 76 | 77 | ObjectAnimator animator = 78 | CircularAnimationUtils.createCircularReveal(myView, center[0], center[1], 0, finalRadius); 79 | 80 | animator.setInterpolator(new AccelerateDecelerateInterpolator()); 81 | animator.setDuration(1500); 82 | animator.start(); 83 | 84 | } 85 | }); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /circulardemo/src/main/java/hu/gordon/circulardemo/fragments/TransformFragment.java: -------------------------------------------------------------------------------- 1 | package hu.gordon.circulardemo.fragments; 2 | 3 | 4 | import android.animation.Animator; 5 | import android.animation.ObjectAnimator; 6 | import android.graphics.Point; 7 | import android.os.Bundle; 8 | import android.support.design.widget.FloatingActionButton; 9 | import android.support.v4.app.Fragment; 10 | import android.util.Log; 11 | import android.view.Display; 12 | import android.view.LayoutInflater; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | import android.view.animation.AccelerateDecelerateInterpolator; 16 | import android.widget.ImageView; 17 | 18 | import hu.aut.utillib.circular.animation.CircularAnimationUtils; 19 | import hu.gordon.circulardemo.R; 20 | 21 | /** 22 | * A simple {@link Fragment} subclass. 23 | */ 24 | public class TransformFragment extends Fragment implements Animator.AnimatorListener { 25 | 26 | public static final String TAG = TransformFragment.class.getSimpleName(); 27 | 28 | private int screenWidth; 29 | private int screenHeight; 30 | private FloatingActionButton fab; 31 | private ImageView imageView1, imageView2; 32 | private boolean state = true; 33 | private boolean animationInProgress = false; 34 | private ObjectAnimator animator; 35 | 36 | private ImageView mySourceView; 37 | private ImageView myTargetView; 38 | 39 | public TransformFragment() { 40 | // Required empty public constructor 41 | } 42 | 43 | @Override 44 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 45 | Bundle savedInstanceState) { 46 | // Inflate the layout for this fragment 47 | View root = inflater.inflate(R.layout.fragment_transform, container, false); 48 | 49 | imageView1 = (ImageView) root.findViewById(R.id.iv1); 50 | imageView2 = (ImageView) root.findViewById(R.id.iv2); 51 | 52 | if (state) { 53 | imageView2.setVisibility(View.INVISIBLE); 54 | } else { 55 | imageView1.setVisibility(View.INVISIBLE); 56 | } 57 | return root; 58 | } 59 | 60 | @Override 61 | public void onViewCreated(View view, Bundle savedInstanceState) { 62 | super.onViewCreated(view, savedInstanceState); 63 | 64 | Display display = getActivity().getWindowManager().getDefaultDisplay(); 65 | 66 | if (android.os.Build.VERSION.SDK_INT >= 13) { 67 | Point size = new Point(); 68 | display.getSize(size); 69 | screenWidth = size.x; 70 | screenHeight = size.y; 71 | } else { 72 | screenWidth = display.getWidth(); 73 | screenHeight = display.getHeight(); 74 | } 75 | 76 | 77 | fab = (FloatingActionButton) view.findViewById(R.id.fab); 78 | fab.setOnClickListener(new View.OnClickListener() { 79 | @Override 80 | public void onClick(View view) { 81 | 82 | if (animationInProgress) { 83 | animator.cancel(); 84 | return; 85 | } 86 | 87 | if (state) { 88 | mySourceView = imageView1; 89 | myTargetView = imageView2; 90 | } else { 91 | mySourceView = imageView2; 92 | myTargetView = imageView1; 93 | } 94 | 95 | // 96 | // Pre-calculations 97 | // 98 | // get the final radius for the clipping circle 99 | int[] myTargetViewLocation = new int[2]; 100 | myTargetView.getLocationInWindow(myTargetViewLocation); 101 | 102 | float finalRadius = CircularAnimationUtils.hypo(screenWidth - myTargetViewLocation[0], screenHeight - myTargetViewLocation[1]); 103 | int[] center = CircularAnimationUtils.getCenter(fab, (View) myTargetView.getParent()); 104 | 105 | animator = 106 | CircularAnimationUtils.createCircularTransform(myTargetView, mySourceView, center[0], center[1], 0F, finalRadius); 107 | 108 | animator.addListener(TransformFragment.this); 109 | 110 | animator.setInterpolator(new AccelerateDecelerateInterpolator()); 111 | animator.setDuration(1500); 112 | 113 | animator.start(); 114 | state = !state; 115 | } 116 | }); 117 | } 118 | 119 | @Override 120 | public void onAnimationStart(Animator animator) { 121 | Log.d(TAG, "animation start"); 122 | animationInProgress = true; 123 | } 124 | 125 | @Override 126 | public void onAnimationEnd(Animator animator) { 127 | Log.d(TAG, "animation end"); 128 | animationInProgress = false; 129 | } 130 | 131 | @Override 132 | public void onAnimationCancel(Animator animator) { 133 | Log.d(TAG, "animation cancel"); 134 | } 135 | 136 | @Override 137 | public void onAnimationRepeat(Animator animator) { 138 | 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-hdpi/ic_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-hdpi/ic_drawer.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-hdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-hdpi/ic_menu.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-hdpi/ic_radial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-hdpi/ic_radial.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-hdpi/ic_refresh_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-hdpi/ic_refresh_white_36dp.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-hdpi/ic_reveal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-hdpi/ic_reveal.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-hdpi/ic_transform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-hdpi/ic_transform.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-hdpi/img_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-hdpi/img_camera.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-hdpi/img_cloud_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-hdpi/img_cloud_empty.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-hdpi/img_cloud_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-hdpi/img_cloud_full.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-mdpi/ic_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-mdpi/ic_drawer.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-mdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-mdpi/ic_menu.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-mdpi/ic_radial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-mdpi/ic_radial.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-mdpi/ic_refresh_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-mdpi/ic_refresh_white_36dp.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-mdpi/ic_reveal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-mdpi/ic_reveal.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-mdpi/ic_transform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-mdpi/ic_transform.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-mdpi/img_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-mdpi/img_camera.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-mdpi/img_cloud_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-mdpi/img_cloud_empty.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-mdpi/img_cloud_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-mdpi/img_cloud_full.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xhdpi/ic_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xhdpi/ic_drawer.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xhdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xhdpi/ic_menu.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xhdpi/ic_radial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xhdpi/ic_radial.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xhdpi/ic_refresh_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xhdpi/ic_refresh_white_36dp.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xhdpi/ic_reveal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xhdpi/ic_reveal.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xhdpi/ic_transform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xhdpi/ic_transform.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xhdpi/img_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xhdpi/img_camera.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xhdpi/img_cloud_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xhdpi/img_cloud_empty.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xhdpi/img_cloud_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xhdpi/img_cloud_full.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxhdpi/ic_drawer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxhdpi/ic_drawer.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxhdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxhdpi/ic_menu.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxhdpi/ic_radial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxhdpi/ic_radial.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxhdpi/ic_refresh_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxhdpi/ic_refresh_white_36dp.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxhdpi/ic_reveal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxhdpi/ic_reveal.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxhdpi/ic_transform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxhdpi/ic_transform.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxhdpi/img_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxhdpi/img_camera.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxhdpi/img_cloud_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxhdpi/img_cloud_empty.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxhdpi/img_cloud_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxhdpi/img_cloud_full.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxxhdpi/ic_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxxhdpi/ic_menu.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxxhdpi/ic_radial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxxhdpi/ic_radial.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxxhdpi/ic_refresh_white_36dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxxhdpi/ic_refresh_white_36dp.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxxhdpi/ic_reveal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxxhdpi/ic_reveal.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxxhdpi/ic_transform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxxhdpi/ic_transform.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxxhdpi/img_camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxxhdpi/img_camera.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxxhdpi/img_cloud_empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxxhdpi/img_cloud_empty.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable-xxxhdpi/img_cloud_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable-xxxhdpi/img_cloud_full.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/drawable/autsoft_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/drawable/autsoft_white.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 13 | 14 | 19 | 20 | 25 | 26 | 27 | 28 | 33 | 34 | 35 | 42 | 43 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/layout/fragment_main.xml: -------------------------------------------------------------------------------- 1 | 10 | 11 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/layout/fragment_radial.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 13 | 14 | 19 | 20 | 28 | 29 | 38 | 39 | 48 | 49 | 57 | 58 | 68 | 69 | 78 | 79 | 87 | 88 | 98 | 99 | 109 | 110 | 111 | 112 | 113 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/layout/fragment_reveal.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 22 | 23 | 36 | 37 | 43 | 44 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/layout/fragment_transform.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 14 | 15 | 16 | 23 | 24 | 25 | 32 | 33 | 34 | 35 | 36 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/layout/nav_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 24 | 25 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/menu/main.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 10 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulardemo/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /circulardemo/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #03A9F4 4 | #0288D1 5 | #B3E5FC 6 | #FFC107 7 | #212121 8 | #727272 9 | #FFFFFF 10 | #B6B6B6 11 | 12 | #004d40 13 | #FFFFFF 14 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | 8 | 240dp 9 | 10 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Circular Demo 3 | 4 | Reveal 5 | Transform 6 | Radial reaction 7 | 8 | 9 | Tap me to hide 10 | 11 | 12 | -------------------------------------------------------------------------------- /circulardemo/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /circulartools/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /circulartools/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | defaultConfig { 7 | minSdkVersion 11 8 | targetSdkVersion 22 9 | versionCode 1 10 | versionName "1.0" 11 | } 12 | buildTypes { 13 | release { 14 | minifyEnabled false 15 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 16 | } 17 | } 18 | productFlavors { 19 | } 20 | } 21 | 22 | dependencies { 23 | compile 'com.android.support:support-annotations:22.2.0' 24 | } 25 | -------------------------------------------------------------------------------- /circulartools/proguard-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/circulartools/proguard-rules.pro -------------------------------------------------------------------------------- /circulartools/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /circulartools/src/main/java/hu/aut/utillib/circular/animation/CircularAnimationUtils.java: -------------------------------------------------------------------------------- 1 | package hu.aut.utillib.circular.animation; 2 | 3 | import android.animation.Animator; 4 | import android.animation.Animator.AnimatorListener; 5 | import android.animation.ObjectAnimator; 6 | import android.os.Build; 7 | import android.view.View; 8 | 9 | import java.lang.ref.WeakReference; 10 | 11 | import hu.aut.utillib.circular.widget.CircularFrameLayout; 12 | 13 | public class CircularAnimationUtils { 14 | 15 | public static final int AUTOMATIC = 0; 16 | public static final int MANUAL = 1; 17 | private static final String RADIUS = "Radius"; 18 | 19 | /** 20 | * Creates a radial reaction animation in the container parent with the provided action 21 | * 22 | * @param parent The container view. It's radius property will be animated 23 | * @param origin The view which will be the origin of the event 24 | * @param action This helps to identify the event in that case when there are multiple use cases for radial reaction. 25 | * In the RadialReactionListener.onRadialReaction() callback you'll get back this action to detect which event happened. 26 | * @return The radial reaction animation 27 | */ 28 | public static ObjectAnimator createRadialReaction(RadialReactionParent parent, View origin, String action) { 29 | if (parent == null) { 30 | throw new IllegalArgumentException("Parent can't be null!"); 31 | } else if (origin == null) { 32 | throw new IllegalArgumentException("Origin can't be null!"); 33 | } 34 | int[] position = new int[2]; 35 | origin.getLocationOnScreen(position); 36 | 37 | int[] center = getCenter(origin, (View) parent); 38 | parent.setCenter(center[0], center[1]); 39 | parent.setAction(action); 40 | 41 | ObjectAnimator radialReaction = ObjectAnimator.ofFloat(parent, RADIUS, 0, parent.getMaxRadius()); 42 | radialReaction.addListener(new RadialListener(parent)); 43 | return radialReaction; 44 | } 45 | 46 | 47 | /** 48 | * Creates a radial reaction animation in the container parent with the provided action 49 | * 50 | * @param parent The container view. It's radius property will be animated 51 | * @param centerX X coordinate of the circle's center 52 | * @param centerY Y coordinate of the circle's center 53 | * @param action This helps to identify the event in that case when there are multiple use cases for radial reaction. 54 | * In the RadialReactionListener.onRadialReaction() callback you'll get back this action to detect which event happened. 55 | * @return The radial reaction animation 56 | */ 57 | public static ObjectAnimator createRadialReaction(RadialReactionParent parent, int centerX, int centerY, String action) { 58 | if (parent == null) { 59 | throw new IllegalArgumentException("Parent can't be null!"); 60 | } 61 | 62 | parent.setCenter(centerX, centerY); 63 | parent.setAction(action); 64 | 65 | ObjectAnimator radialReaction = ObjectAnimator.ofFloat(parent, RADIUS, 0, parent.getMaxRadius()); 66 | radialReaction.addListener(new RadialListener(parent)); 67 | return radialReaction; 68 | } 69 | 70 | /** 71 | * Returns an ObjectAnimator which can animate a clipping circle for a reveal effect. 72 | * The animated views visibility will change automatically. 73 | * See {@link CircularAnimationUtils#createCircularReveal(View, int, int, float, float, int)} 74 | * 75 | * @param view The View will be clipped to the animating circle. 76 | * @param centerX The x coordinate of the center of the animating circle. 77 | * @param centerY The y coordinate of the center of the animating circle. 78 | * @param startRadius The starting radius of the animating circle. 79 | * @param endRadius The ending radius of the animating circle. 80 | */ 81 | public static ObjectAnimator createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius) { 82 | return createCircularTransform(view, null, centerX, centerY, startRadius, endRadius, AUTOMATIC); 83 | } 84 | 85 | /** 86 | * Returns an ObjectAnimator which can animate a clipping circle for a reveal effect. 87 | * 88 | * @param view The View will be clipped to the animating circle. 89 | * @param centerX The x coordinate of the center of the animating circle. 90 | * @param centerY The y coordinate of the center of the animating circle. 91 | * @param startRadius The starting radius of the animating circle. 92 | * @param endRadius The ending radius of the animating circle. 93 | * @param mode The behavior of the animation. If set to {@link #AUTOMATIC} 94 | * the animated views visibility will change automatically, 95 | * otherwise these properties won't be touched. 96 | */ 97 | public static ObjectAnimator createCircularReveal(View view, int centerX, int centerY, float startRadius, float endRadius, int mode) { 98 | return createCircularTransform(view, null, centerX, centerY, startRadius, endRadius, mode); 99 | } 100 | 101 | /** 102 | * Returns an ObjectAnimator which can animate a clipping circle over two views in the same parent. 103 | * 104 | * @param target The appearing View will be clipped to the animating circle. 105 | * @param source The disappearing View will be inverse clipped to the animating circle. 106 | * @param centerX The x coordinate of the center of the animating circle. 107 | * @param centerY The y coordinate of the center of the animating circle. 108 | * @param startRadius The starting radius of the animating circle. 109 | * @param endRadius The ending radius of the animating circle. 110 | */ 111 | public static ObjectAnimator createCircularTransform(View target, View source, int centerX, int centerY, float startRadius, float endRadius) { 112 | return createCircularTransform(target, source, centerX, centerY, startRadius, endRadius, AUTOMATIC); 113 | } 114 | 115 | /** 116 | * Returns an ObjectAnimator which can animate a clipping circle over two views in the same parent. 117 | * 118 | * @param target The appearing View will be clipped to the animating circle. 119 | * @param source The disappearing View will be inverse clipped to the animating circle. 120 | * @param centerX The x coordinate of the center of the animating circle. 121 | * @param centerY The y coordinate of the center of the animating circle. 122 | * @param startRadius The starting radius of the animating circle. 123 | * @param endRadius The ending radius of the animating circle. 124 | * @param mode The behavior of the animation. If set to {@link #AUTOMATIC} 125 | * the animated views visibility will change automatically, 126 | * otherwise these properties won't be touched. 127 | */ 128 | public static ObjectAnimator createCircularTransform(View target, View source, int centerX, int centerY, float startRadius, float endRadius, int mode) { 129 | 130 | if (target == null) { 131 | throw new IllegalArgumentException("Target can't be null!"); 132 | } else if (source != null) { 133 | if (target.getParent() != source.getParent()) { 134 | throw new IllegalArgumentException("Target and source parent must be the same!"); 135 | } 136 | } 137 | 138 | if (!(target.getParent() instanceof CircularAnimator)) { 139 | throw new IllegalArgumentException("View must be inside CircularFrameLayout"); 140 | } 141 | 142 | CircularFrameLayout transformLayout = (CircularFrameLayout) target.getParent(); 143 | transformLayout.setTarget(target); 144 | transformLayout.setAnimated(true); 145 | transformLayout.setSource(source); 146 | transformLayout.setCenter(centerX, centerY); 147 | 148 | ObjectAnimator transform = ObjectAnimator.ofFloat(transformLayout, RADIUS, startRadius, endRadius); 149 | 150 | if (source == null) { 151 | transform.addListener(new RevealListener(target, mode)); 152 | } else { 153 | transform.addListener(new TransformListener(target, source, mode)); 154 | } 155 | 156 | return transform; 157 | } 158 | 159 | 160 | /** 161 | * Computes the center of the clipping circle used by transform and reveal animations 162 | * The result is relative to the target. 163 | * 164 | * @param origin The Origin of the effect (eg. pressed view) 165 | * @param target Targeted view, that will be clipped 166 | * @return x and y coordinates in an array, in that order 167 | */ 168 | public static int[] getCenter(View origin, View target) { 169 | 170 | //the top left corner of origin 171 | int[] originPosition = new int[2]; 172 | origin.getLocationOnScreen(originPosition); 173 | 174 | //the center of origin 175 | originPosition[0] = originPosition[0] + origin.getWidth() / 2; 176 | originPosition[1] = originPosition[1] + origin.getHeight() / 2; 177 | 178 | // get the center for the clipping circle for the view 179 | int[] targetPosition = new int[2]; 180 | target.getLocationOnScreen(targetPosition); 181 | 182 | int[] center = new int[2]; 183 | 184 | center[0] = originPosition[0] - targetPosition[0]; 185 | center[1] = originPosition[1] - targetPosition[1]; 186 | 187 | return center; 188 | } 189 | 190 | /** 191 | * Returns the square root of the sum of squares of its arguments, see {@link Math#hypot(double, double)} 192 | */ 193 | public static float hypo(int a, int b) { 194 | return (float) Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2)); 195 | } 196 | 197 | public static boolean isHWAsupported() { 198 | return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2); 199 | } 200 | 201 | static class RevealListener implements AnimatorListener { 202 | int originalLayerType; 203 | int mode; 204 | WeakReference targetReference; 205 | WeakReference parentReference; 206 | 207 | RevealListener(View target, int mode) { 208 | targetReference = new WeakReference<>(target); 209 | parentReference = new WeakReference<>((CircularFrameLayout) targetReference.get().getParent()); 210 | originalLayerType = ((CircularFrameLayout) target.getParent()).getLayerType(); 211 | this.mode = mode; 212 | } 213 | 214 | @Override 215 | public void onAnimationStart(Animator animation) { 216 | if (!isHWAsupported()) { 217 | parentReference.get().setLayerType(View.LAYER_TYPE_SOFTWARE, null); 218 | } 219 | if (mode == AUTOMATIC) { 220 | targetReference.get().setVisibility(View.VISIBLE); 221 | } 222 | } 223 | 224 | @Override 225 | public void onAnimationEnd(Animator animation) { 226 | 227 | } 228 | 229 | @Override 230 | public void onAnimationCancel(Animator animation) { 231 | if (!isHWAsupported()) { 232 | parentReference.get().setLayerType(originalLayerType, null); 233 | } 234 | } 235 | 236 | @Override 237 | public void onAnimationRepeat(Animator animation) { 238 | 239 | } 240 | } 241 | 242 | static class TransformListener extends RevealListener { 243 | WeakReference sourceReference; 244 | 245 | TransformListener(View target, View source, int mode) { 246 | super(target, mode); 247 | sourceReference = new WeakReference<>(source); 248 | } 249 | 250 | 251 | @Override 252 | public void onAnimationStart(Animator animation) { 253 | if (!isHWAsupported()) { 254 | parentReference.get().setLayerType(View.LAYER_TYPE_SOFTWARE, null); 255 | } 256 | if (mode == AUTOMATIC) { 257 | targetReference.get().setVisibility(View.VISIBLE); 258 | } 259 | } 260 | 261 | @Override 262 | public void onAnimationEnd(Animator animation) { 263 | if (!isHWAsupported()) { 264 | parentReference.get().setLayerType(originalLayerType, null); 265 | } 266 | if (mode == AUTOMATIC) { 267 | sourceReference.get().setVisibility(View.INVISIBLE); 268 | } 269 | } 270 | } 271 | 272 | static class RadialListener implements AnimatorListener { 273 | WeakReference parentReference; 274 | 275 | RadialListener(RadialReactionParent parent) { 276 | parentReference = new WeakReference<>(parent); 277 | } 278 | 279 | @Override 280 | public void onAnimationStart(Animator animation) { 281 | parentReference.get().setAnimated(true); 282 | } 283 | 284 | @Override 285 | public void onAnimationEnd(Animator animation) { 286 | parentReference.get().setAnimated(false); 287 | } 288 | 289 | @Override 290 | public void onAnimationCancel(Animator animation) { 291 | 292 | } 293 | 294 | @Override 295 | public void onAnimationRepeat(Animator animation) { 296 | 297 | } 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /circulartools/src/main/java/hu/aut/utillib/circular/animation/CircularAnimator.java: -------------------------------------------------------------------------------- 1 | package hu.aut.utillib.circular.animation; 2 | 3 | 4 | public interface CircularAnimator { 5 | 6 | 7 | /** 8 | * Whether enable {@link android.graphics.Canvas} to clip 9 | * outlines of the certain or not 10 | * 11 | * @param isAnimated Whether it's animated or not 12 | * @see #setCenter(int, int) 13 | * @see #setRadius(float) 14 | */ 15 | void setAnimated(boolean isAnimated); 16 | 17 | /** 18 | * Sets central points where to start clipping 19 | * certain child 20 | * 21 | * @param cx x point of child 22 | * @param cy y point of child 23 | * @see #setAnimated(boolean) (float, float) 24 | * @see #setRadius(float) 25 | */ 26 | void setCenter(int cx, int cy); 27 | 28 | /** 29 | * Used with animator to animate view clipping 30 | * 31 | * @param value clip radius 32 | */ 33 | void setRadius(float value); 34 | 35 | /** 36 | * Used with animator to animate view clipping 37 | * 38 | * @return current radius 39 | */ 40 | float getRadius(); 41 | 42 | } -------------------------------------------------------------------------------- /circulartools/src/main/java/hu/aut/utillib/circular/animation/RadialReactionDelegate.java: -------------------------------------------------------------------------------- 1 | package hu.aut.utillib.circular.animation; 2 | 3 | import android.view.View; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Iterator; 7 | import java.util.List; 8 | 9 | public class RadialReactionDelegate { 10 | 11 | private boolean mAnimated; 12 | private int mCx; 13 | private int mCy; 14 | private float mRadius; 15 | private List mListeners; 16 | private List mAffectedViews; 17 | private String mAction; 18 | 19 | public RadialReactionDelegate() { 20 | mListeners = new ArrayList<>(); 21 | mAffectedViews = new ArrayList<>(); 22 | } 23 | 24 | public void setAnimated(boolean isAnimated) { 25 | mAnimated = isAnimated; 26 | } 27 | 28 | public void setCenter(int cx, int cy) { 29 | mCx = cx; 30 | mCy = cy; 31 | } 32 | 33 | public float getRevealRadius() { 34 | return mRadius; 35 | } 36 | 37 | public void setRevealRadius(float value) { 38 | mRadius = value; 39 | 40 | for (Iterator iterator = mAffectedViews.iterator(); iterator.hasNext(); ) { 41 | 42 | View item = (View) iterator.next(); 43 | int[] position = new int[2]; 44 | item.getLocationOnScreen(position); 45 | 46 | //corner coordinates where tLx means Top Left X coordinate, etc. 47 | int tLx = position[0]; 48 | int tLy = position[1]; 49 | int tRx = tLx + item.getWidth(); 50 | int tRy = tLy; 51 | int bLx = tLx; 52 | int bLy = tLy + item.getHeight(); 53 | int bRx = bLx + item.getWidth(); 54 | int bRy = bLy; 55 | 56 | if (mRadius >= CircularAnimationUtils.hypo(mCx - tLx, mCy - tLy) || 57 | mRadius >= CircularAnimationUtils.hypo(mCx - tRx, mCy - tRy) || 58 | mRadius >= CircularAnimationUtils.hypo(mCx - bLx, mCy - bLy) || 59 | mRadius >= CircularAnimationUtils.hypo(mCx - bRx, mCy - bRy)) { 60 | // view reached by circle 61 | for (RadialReactionListener listener : mListeners) { 62 | listener.onRadialReaction(item, mAction); 63 | iterator.remove(); 64 | } 65 | } 66 | } 67 | } 68 | 69 | public void addListener(RadialReactionListener listener) { 70 | mListeners.add(listener); 71 | } 72 | 73 | public void addAffectedView(View view) { 74 | mAffectedViews.add(view); 75 | } 76 | 77 | public void addAffectedViews(List viewList) { 78 | mAffectedViews.addAll(viewList); 79 | } 80 | 81 | public void setAction(String action) { 82 | mAction = action; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /circulartools/src/main/java/hu/aut/utillib/circular/animation/RadialReactionListener.java: -------------------------------------------------------------------------------- 1 | package hu.aut.utillib.circular.animation; 2 | 3 | import android.view.View; 4 | 5 | public interface RadialReactionListener { 6 | 7 | /** 8 | * This callback is called from a RadialReactionParent, when the radius of radial action reached 9 | * a view 10 | * 11 | * @param affectedView The reached view 12 | * @param action A previously given identifier for event 13 | */ 14 | void onRadialReaction(View affectedView, String action); 15 | } 16 | -------------------------------------------------------------------------------- /circulartools/src/main/java/hu/aut/utillib/circular/animation/RadialReactionParent.java: -------------------------------------------------------------------------------- 1 | package hu.aut.utillib.circular.animation; 2 | 3 | import android.view.View; 4 | 5 | import java.util.List; 6 | 7 | public interface RadialReactionParent extends CircularAnimator { 8 | 9 | void addListener(RadialReactionListener listener); 10 | 11 | void addAffectedViews(View view); 12 | 13 | void addAffectedViews(List viewList); 14 | 15 | void setAction(String action); 16 | 17 | int getMaxRadius(); 18 | } 19 | -------------------------------------------------------------------------------- /circulartools/src/main/java/hu/aut/utillib/circular/widget/CircularFrameLayout.java: -------------------------------------------------------------------------------- 1 | package hu.aut.utillib.circular.widget; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Path; 6 | import android.graphics.Region; 7 | import android.support.annotation.NonNull; 8 | import android.util.AttributeSet; 9 | import android.view.View; 10 | import android.widget.FrameLayout; 11 | 12 | import hu.aut.utillib.circular.animation.CircularAnimator; 13 | 14 | 15 | public class CircularFrameLayout extends FrameLayout implements CircularAnimator { 16 | 17 | Path mRevealPath; 18 | 19 | boolean mClipOutlines; 20 | 21 | int mCenterX; 22 | int mCenterY; 23 | float mRadius; 24 | 25 | View mTarget; 26 | View mSource; 27 | 28 | 29 | public CircularFrameLayout(Context context) { 30 | this(context, null); 31 | } 32 | 33 | public CircularFrameLayout(Context context, AttributeSet attrs) { 34 | this(context, attrs, 0); 35 | } 36 | 37 | public CircularFrameLayout(Context context, AttributeSet attrs, int defStyle) { 38 | super(context, attrs, defStyle); 39 | mRevealPath = new Path(); 40 | } 41 | 42 | 43 | /** 44 | * Reference the target of circular animation to appear 45 | * 46 | * @param target View to clip outlines 47 | */ 48 | public void setTarget(View target) { 49 | mTarget = target; 50 | } 51 | 52 | /** 53 | * Reference the target of circular animation to disappear 54 | * 55 | * @param source View to clip outlines 56 | */ 57 | public void setSource(View source) { 58 | mSource = source; 59 | } 60 | 61 | /** 62 | * Epicenter of animation circle reveal 63 | */ 64 | @Override 65 | public void setCenter(int centerX, int centerY) { 66 | mCenterX = centerX; 67 | mCenterY = centerY; 68 | } 69 | 70 | /** 71 | * Flag that animation is enabled (so the view should use the clipping) 72 | * Clipping won't work if it's not set to true 73 | */ 74 | @Override 75 | public void setAnimated(boolean isAnimated) { 76 | mClipOutlines = isAnimated; 77 | } 78 | 79 | /** 80 | * Sets the clipping circle radius size. Radius won't be smaller than 1F 81 | */ 82 | @Override 83 | public void setRadius(float radius) { 84 | mRadius = Math.max(1F, radius); 85 | invalidate(); 86 | } 87 | 88 | /** 89 | * Returns the clipping circle radius size 90 | */ 91 | @Override 92 | public float getRadius() { 93 | return mRadius; 94 | } 95 | 96 | @Override 97 | protected boolean drawChild(@NonNull Canvas canvas, @NonNull View child, long drawingTime) { 98 | if (mClipOutlines && (child == mTarget || child == mSource)) { 99 | 100 | canvas.save(); 101 | 102 | mRevealPath.reset(); 103 | mRevealPath.addCircle(mCenterX, mCenterY, mRadius, Path.Direction.CW); 104 | 105 | if (child == mTarget) { 106 | //appearing 107 | canvas.clipPath(mRevealPath, Region.Op.INTERSECT); 108 | } else { 109 | //disappearing 110 | canvas.clipPath(mRevealPath, Region.Op.DIFFERENCE); 111 | } 112 | 113 | boolean isInvalided = super.drawChild(canvas, child, drawingTime); 114 | canvas.restore(); 115 | return isInvalided; 116 | } 117 | 118 | return super.drawChild(canvas, child, drawingTime); 119 | } 120 | 121 | } 122 | -------------------------------------------------------------------------------- /circulartools/src/main/java/hu/aut/utillib/circular/widget/RadialReactionLinearLayout.java: -------------------------------------------------------------------------------- 1 | package hu.aut.utillib.circular.widget; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.os.Build; 6 | import android.util.AttributeSet; 7 | import android.view.View; 8 | import android.widget.LinearLayout; 9 | 10 | import java.util.List; 11 | 12 | import hu.aut.utillib.circular.animation.RadialReactionDelegate; 13 | import hu.aut.utillib.circular.animation.RadialReactionListener; 14 | import hu.aut.utillib.circular.animation.RadialReactionParent; 15 | 16 | public class RadialReactionLinearLayout extends LinearLayout implements RadialReactionParent { 17 | 18 | private RadialReactionDelegate mDelegate = new RadialReactionDelegate(); 19 | 20 | public RadialReactionLinearLayout(Context context) { 21 | super(context); 22 | } 23 | 24 | public RadialReactionLinearLayout(Context context, AttributeSet attrs) { 25 | super(context, attrs); 26 | } 27 | 28 | public RadialReactionLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { 29 | super(context, attrs, defStyleAttr); 30 | } 31 | 32 | @TargetApi(Build.VERSION_CODES.LOLLIPOP) 33 | public RadialReactionLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 34 | super(context, attrs, defStyleAttr, defStyleRes); 35 | } 36 | 37 | @Override 38 | public void setAnimated(boolean isAnimated) { 39 | mDelegate.setAnimated(isAnimated); 40 | } 41 | 42 | @Override 43 | public void setCenter(int cx, int cy) { 44 | mDelegate.setCenter(cx, cy); 45 | } 46 | 47 | @Override 48 | public float getRadius() { 49 | return mDelegate.getRevealRadius(); 50 | } 51 | 52 | @Override 53 | public void setRadius(float value) { 54 | mDelegate.setRevealRadius(value); 55 | } 56 | 57 | @Override 58 | public void addListener(RadialReactionListener listener) { 59 | mDelegate.addListener(listener); 60 | } 61 | 62 | @Override 63 | public void addAffectedViews(View view) { 64 | mDelegate.addAffectedView(view); 65 | } 66 | 67 | @Override 68 | public void addAffectedViews(List viewList) { 69 | mDelegate.addAffectedViews(viewList); 70 | } 71 | 72 | @Override 73 | public void setAction(String action) { 74 | mDelegate.setAction(action); 75 | } 76 | 77 | @Override 78 | public int getMaxRadius() { 79 | return Math.max(getWidth(), getHeight()); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /circulartools/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CircularTools 3 | 4 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AutSoft/CircularTools/8a12255fa4f2d9132f9ec18ceff1f33e878f3b14/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Dec 27 12:22:39 UZT 2014 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':circulartools', ':circulardemo' 2 | --------------------------------------------------------------------------------