aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrumeet <liangyuteng12345@gmail.com>2017-08-07 14:37:32 +0800
committerTrumeet <liangyuteng12345@gmail.com>2017-08-07 14:37:32 +0800
commit5270e353c7c1a33a4005d5517f0f8591e5914916 (patch)
treefbaa9112c2b3cd28501ef550f8e859b6268d5063
parent37429d7aa881801a2bbf3a6111bf01d0f78d6daf (diff)
downloadAnimations-5270e353c7c1a33a4005d5517f0f8591e5914916.tar
Animations-5270e353c7c1a33a4005d5517f0f8591e5914916.tar.gz
Animations-5270e353c7c1a33a4005d5517f0f8591e5914916.tar.bz2
Animations-5270e353c7c1a33a4005d5517f0f8591e5914916.zip
feat: add appear/disappear animation
-rw-r--r--README.md12
-rw-r--r--app/build.gradle2
-rw-r--r--app/src/main/AndroidManifest.xml4
-rw-r--r--app/src/main/java/top/trumeet/snippet/aospanimation/AppearAnimationActivity.java147
-rw-r--r--app/src/main/java/top/trumeet/snippet/aospanimation/FingerprintIsloatedActivity.java (renamed from app/src/main/java/top/trumeet/snippet/aospanimation/MainActivity.java)32
-rw-r--r--app/src/main/java/top/trumeet/snippet/aospanimation/LauncherActivity.java53
-rw-r--r--app/src/main/java/top/trumeet/snippet/aospanimation/ViewAnimationActivity.java46
-rw-r--r--app/src/main/res/layout/activity_main.xml25
-rw-r--r--app/src/main/res/layout/appear.xml56
-rw-r--r--app/src/main/res/layout/fingerprint_isloated.xml21
-rw-r--r--art/AppearAnimation.gifbin0 -> 491639 bytes
-rw-r--r--art/appear_animation_demo.mp4bin0 -> 449840 bytes
-rw-r--r--build.gradle5
-rw-r--r--library/build.gradle3
-rw-r--r--library/lib/classes.jarbin0 -> 16348161 bytes
-rw-r--r--library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/AppearAnimationCreator.java29
-rw-r--r--library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/AppearAnimationUtils.java254
-rw-r--r--library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/DisappearAnimationUtils.java58
-rw-r--r--library/src/main/res/anim/confirm_credential_close_enter.xml30
-rw-r--r--library/src/main/res/anim/confirm_credential_close_exit.xml21
-rw-r--r--library/src/main/res/anim/fast_out_linear_in.xml22
-rw-r--r--library/src/main/res/anim/linear_out_slow_in.xml22
-rw-r--r--library/src/main/res/values/dimens.xml3
23 files changed, 794 insertions, 51 deletions
diff --git a/README.md b/README.md
index 695949f..136bfb6 100644
--- a/README.md
+++ b/README.md
@@ -69,6 +69,18 @@ Beautiful animations and views from AOSP
停止動畫: `mFingerprintAnimator.stopIconAnimation()`
+## Appear / Disappear Animation
+
+ **設置 中 確認密碼時的進入/退出動畫** (API21+)
+
+ Activity 位於:[ConfirmLockPattern](https://android.googlesource.com/platform/packages/apps/Settings/+/master/src/com/android/settings/ConfirmLockPattern.java)
+
+ ![AppearAnimation](https://raw.githubusercontent.com/AndroidSnippet/Animations/master/art/AppearAnimation.GIF)
+
+ 使用方法:[參照 Demo AppearAnimationActivity](https://github.com/AndroidSnippet/Animations/tree/master/app/src/main/java/top/trumeet/snippet/aospanimation/AppearAnimationActivity.java)
+
+ `startAnimation2d`的第一個參數 T[][] 是可以傳入 X行X列 的二維數組,比如説 TableLayout。詳見 Demo
+
# Licenses
使用本項目請確保您遵守 `Apache License 2.0`
```
diff --git a/app/build.gradle b/app/build.gradle
index 64efa10..705f3ca 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,7 +5,7 @@ android {
buildToolsVersion "26.0.1"
defaultConfig {
applicationId "top.trumeet.snippet.aospanimation"
- minSdkVersion 15
+ minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 874160c..cc612f8 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,11 +6,13 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light">
- <activity android:name=".MainActivity">
+ <activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
+ <activity android:name=".FingerprintIsloatedActivity" />
+ <activity android:name=".AppearAnimationActivity" />
</application>
</manifest>
diff --git a/app/src/main/java/top/trumeet/snippet/aospanimation/AppearAnimationActivity.java b/app/src/main/java/top/trumeet/snippet/aospanimation/AppearAnimationActivity.java
new file mode 100644
index 0000000..b110f68
--- /dev/null
+++ b/app/src/main/java/top/trumeet/snippet/aospanimation/AppearAnimationActivity.java
@@ -0,0 +1,147 @@
+package top.trumeet.snippet.aospanimation;
+
+import android.os.Bundle;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import android.widget.TableLayout;
+import android.widget.TableRow;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import top.trumeet.snippet.aospanimation.library.animation.AppearAnimationCreator;
+import top.trumeet.snippet.aospanimation.library.animation.AppearAnimationUtils;
+import top.trumeet.snippet.aospanimation.library.animation.DisappearAnimationUtils;
+
+/**
+ * Created by Trumeet on 2017/8/7.
+ * @see top.trumeet.snippet.aospanimation.library.animation.AppearAnimationUtils
+ */
+
+public class AppearAnimationActivity extends ViewAnimationActivity implements AppearAnimationCreator<Object> {
+ private AppearAnimationUtils mAppearAnimationUtils;
+ private DisappearAnimationUtils mDisappearAnimationUtils;
+
+ private View icon_top;
+ private TableLayout tableLayout;
+
+ @Override
+ public void onCreate (Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.appear);
+ icon_top = findViewById(R.id.icon_top);
+ tableLayout = findViewById(R.id.table);
+ mAppearAnimationUtils = new AppearAnimationUtils(this,
+ AppearAnimationUtils.DEFAULT_APPEAR_DURATION, 2f /* translationScale */,
+ 1.3f /* delayScale */, AnimationUtils.loadInterpolator(
+ this, R.anim.linear_out_slow_in));
+ mDisappearAnimationUtils = new DisappearAnimationUtils(this,
+ 125, 4f /* translationScale */,
+ 0.3f /* delayScale */, AnimationUtils.loadInterpolator(
+ this, R.anim.fast_out_linear_in),
+ new AppearAnimationUtils.RowTranslationScaler() {
+ @Override
+ public float getRowTranslationScale(int row, int numRows) {
+ return (float)(numRows - row) / numRows;
+ }
+ });
+ startAnimation();
+ }
+
+ @Override
+ public void startAnimation() {
+ mAppearAnimationUtils.startAnimation2d(getViews()
+ , null, this);
+ }
+
+ @Override
+ public void stopAnimation() {
+ mDisappearAnimationUtils.startAnimation2d(getViews(),
+ new Runnable() {
+ @Override
+ public void run() {
+ /*
+ finish();
+ overridePendingTransition(
+ R.anim.confirm_credential_close_enter,
+ R.anim.confirm_credential_close_exit);
+ */
+ }
+ }, this);
+ }
+
+ @Override
+ public void onBackPressed () {
+ mDisappearAnimationUtils.startAnimation2d(getViews(),
+ new Runnable() {
+ @Override
+ public void run() {
+ finish();
+ overridePendingTransition(
+ R.anim.confirm_credential_close_enter,
+ R.anim.confirm_credential_close_exit);
+ }
+ }, this);
+ }
+
+ @Override
+ public CharSequence getStartText() {
+ return "Appear";
+ }
+
+ @Override
+ public CharSequence getStopText() {
+ return "Disappear";
+ }
+
+ private static List<TableRow> getRows (TableLayout table) {
+ List<TableRow> list = new ArrayList<>(table.getChildCount());
+ for(int i = 0, j = table.getChildCount(); i < j; i++) {
+ View view = table.getChildAt(i);
+ if (view instanceof TableRow) {
+ TableRow row = (TableRow) view;
+ list.add(row);
+ }
+ }
+ return list;
+ }
+
+ private ArrayList<ArrayList<Object>> getAllChildren() {
+ ArrayList<ArrayList<Object>> result = new ArrayList<>();
+ result.add(new ArrayList<Object>(Collections.singletonList(icon_top)));
+ List<TableRow> list = getRows(tableLayout);
+ List<List<View>> radios = new ArrayList<>(list.size() * 5);
+ for (TableRow row : list) {
+ List<View> views = new ArrayList<>(row.getChildCount());
+ for (int i = 0; i < row.getChildCount(); i ++) {
+ views.add(row.getChildAt(i));
+ }
+ radios.add(views);
+ }
+ for (int i = 0; i < radios.size(); i++) {
+ ArrayList<Object> row = new ArrayList<>();
+ row.addAll(radios.get(i));
+ result.add(row);
+ }
+ return result;
+ }
+ private Object[][] getViews () {
+ ArrayList<ArrayList<Object>> result = getAllChildren();
+ Object[][] resultArr = new Object[result.size()][5];
+ for (int i = 0; i < result.size(); i++) {
+ ArrayList<Object> row = result.get(i);
+ for (int j = 0; j < row.size(); j++) {
+ resultArr[i][j] = row.get(j);
+ }
+ }
+ return resultArr;
+ }
+
+ @Override
+ public void createAnimation(Object obj, long delay, long duration, float translationY, boolean appearing, Interpolator interpolator, Runnable finishListener) {
+ mAppearAnimationUtils.createAnimation((View) obj, delay, duration, translationY,
+ appearing, interpolator, finishListener);
+ }
+}
diff --git a/app/src/main/java/top/trumeet/snippet/aospanimation/MainActivity.java b/app/src/main/java/top/trumeet/snippet/aospanimation/FingerprintIsloatedActivity.java
index e1cf783..611e273 100644
--- a/app/src/main/java/top/trumeet/snippet/aospanimation/MainActivity.java
+++ b/app/src/main/java/top/trumeet/snippet/aospanimation/FingerprintIsloatedActivity.java
@@ -4,11 +4,8 @@ import android.annotation.SuppressLint;
import android.content.res.ColorStateList;
import android.os.Bundle;
import android.support.graphics.drawable.AnimatedVectorDrawableCompat;
-import android.support.v7.app.AppCompatActivity;
import android.support.v7.content.res.AppCompatResources;
import android.support.v7.widget.AppCompatImageView;
-import android.view.Menu;
-import android.view.MenuItem;
import android.widget.CheckBox;
import android.widget.CompoundButton;
@@ -19,18 +16,19 @@ import top.trumeet.snippet.aospanimation.library.drawables.LoopAnimatedVectorDra
* Demo activity
*/
-public class MainActivity extends AppCompatActivity {
+public class FingerprintIsloatedActivity extends ViewAnimationActivity {
private LoopAnimatedVectorDrawableCompat mFingerprintAnimator;
+
@SuppressLint("RestrictedApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
+ setContentView(R.layout.fingerprint_isloated);
final AppCompatImageView fingerprintIsolated = findViewById(R.id.fingerprint_animator);
mFingerprintAnimator = new LoopAnimatedVectorDrawableCompat(AnimatedVectorDrawableCompat.create(this,
R.drawable.enrollment_fingerprint_isolated_animation));
- fingerprintIsolated.setBackgroundDrawable(AppCompatResources.getDrawable(MainActivity.this
+ fingerprintIsolated.setBackgroundDrawable(AppCompatResources.getDrawable(FingerprintIsloatedActivity.this
, top.trumeet.snippet.aospanimation.library.R.drawable.fp_illustration_enrollment));
fingerprintIsolated.setSupportBackgroundTintList(ColorStateList.valueOf(getResources().getColor(top.trumeet.snippet.aospanimation.library.R.color.fingerprint_indicator_background_resting)));
@@ -39,7 +37,7 @@ public class MainActivity extends AppCompatActivity {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b) {
- fingerprintIsolated.setBackgroundDrawable(AppCompatResources.getDrawable(MainActivity.this
+ fingerprintIsolated.setBackgroundDrawable(AppCompatResources.getDrawable(FingerprintIsloatedActivity.this
, top.trumeet.snippet.aospanimation.library.R.drawable.fp_illustration_enrollment));
fingerprintIsolated.setSupportBackgroundTintList(ColorStateList.valueOf(getResources().getColor(top.trumeet.snippet.aospanimation.library.R.color.fingerprint_indicator_background_resting)));
} else {
@@ -64,24 +62,12 @@ public class MainActivity extends AppCompatActivity {
}
@Override
- public boolean onCreateOptionsMenu (Menu menu) {
- menu.add(0, 0, 0, "Start")
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- menu.add(0, 1, 0, "Stop")
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- return true;
+ public void startAnimation() {
+ mFingerprintAnimator.startAnimation();
}
@Override
- public boolean onOptionsItemSelected (MenuItem item) {
- switch (item.getItemId()) {
- case 0 :
- mFingerprintAnimator.startAnimation();
- return true;
- case 1 :
- mFingerprintAnimator.stopAnimation();
- return true;
- }
- return false;
+ public void stopAnimation() {
+ mFingerprintAnimator.stopAnimation();
}
}
diff --git a/app/src/main/java/top/trumeet/snippet/aospanimation/LauncherActivity.java b/app/src/main/java/top/trumeet/snippet/aospanimation/LauncherActivity.java
new file mode 100644
index 0000000..c24f0d9
--- /dev/null
+++ b/app/src/main/java/top/trumeet/snippet/aospanimation/LauncherActivity.java
@@ -0,0 +1,53 @@
+package top.trumeet.snippet.aospanimation;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.app.AppCompatActivity;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.SimpleAdapter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Created by Trumeet on 2017/8/7.
+ * @see FingerprintIsloatedActivity
+ * @see AppearAnimationActivity
+ */
+
+public class LauncherActivity extends AppCompatActivity {
+ private static final Class[] DATA = new Class[] {
+ FingerprintIsloatedActivity.class,
+ AppearAnimationActivity.class
+ };
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ ArrayList<Map<String, Object>> list = new ArrayList<>(DATA.length);
+ for (Class clz : DATA) {
+ Map<String, Object> map = new HashMap<>(1);
+ map.put("Title", clz.getSimpleName());
+ map.put("Class", clz);
+ list.add(map);
+ }
+
+ ListView listView = new ListView(this);
+ listView.setAdapter(new SimpleAdapter(this, list,
+ android.R.layout.simple_list_item_1, new String[]{"Title"}, new int[]{android.R.id.text1}));
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
+ Map<String, Object> data = (Map<String, Object>)adapterView.getItemAtPosition(i);
+ startActivity(new Intent(LauncherActivity.this,
+ (Class)data.get("Class")));
+ }
+ });
+ setContentView(listView);
+ }
+}
diff --git a/app/src/main/java/top/trumeet/snippet/aospanimation/ViewAnimationActivity.java b/app/src/main/java/top/trumeet/snippet/aospanimation/ViewAnimationActivity.java
new file mode 100644
index 0000000..a91f566
--- /dev/null
+++ b/app/src/main/java/top/trumeet/snippet/aospanimation/ViewAnimationActivity.java
@@ -0,0 +1,46 @@
+package top.trumeet.snippet.aospanimation;
+
+import android.support.v7.app.AppCompatActivity;
+import android.view.Menu;
+import android.view.MenuItem;
+
+/**
+ * Created by Trumeet on 2017/8/7.
+ * A abstract activity, include "Start" and "Stop" animation menu
+ */
+
+public abstract class ViewAnimationActivity extends AppCompatActivity {
+
+ @Override
+ public boolean onCreateOptionsMenu (Menu menu) {
+ menu.add(0, 0, 0, getStartText())
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ menu.add(0, 1, 0, getStopText())
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected (MenuItem item) {
+ switch (item.getItemId()) {
+ case 0 :
+ startAnimation();
+ return true;
+ case 1 :
+ stopAnimation();
+ return true;
+ }
+ return false;
+ }
+
+ public abstract void startAnimation();
+ public abstract void stopAnimation();
+
+ public CharSequence getStartText () {
+ return "Start";
+ }
+
+ public CharSequence getStopText () {
+ return "Stop";
+ }
+}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
deleted file mode 100644
index 1be4af6..0000000
--- a/app/src/main/res/layout/activity_main.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <LinearLayout
- android:gravity="center_horizontal"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <android.support.v7.widget.AppCompatImageView
- android:id="@+id/fingerprint_animator"
- android:layout_width="@dimen/fingerprint_animation_size"
- android:layout_height="@dimen/fingerprint_animation_size"
- app:background="@drawable/fp_illustration_enrollment"
- app:backgroundTint="@color/fingerprint_indicator_background_resting"
- />
- <CheckBox
- android:id="@+id/check_show_background"
- android:checked="true"
- android:text="Show Background"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </LinearLayout>
-</ScrollView> \ No newline at end of file
diff --git a/app/src/main/res/layout/appear.xml b/app/src/main/res/layout/appear.xml
new file mode 100644
index 0000000..4913ef8
--- /dev/null
+++ b/app/src/main/res/layout/appear.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:gravity="center_horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <ImageView
+ android:id="@+id/icon_top"
+ android:layout_marginTop="16dp"
+ android:contentDescription="@null"
+ android:src="@mipmap/ic_launcher_round"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TableLayout
+ android:id="@+id/table"
+ android:layout_gravity="center"
+ android:layout_marginTop="16dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TableRow>
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ </TableRow>
+ <TableRow>
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ </TableRow>
+ <TableRow>
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ </TableRow>
+ <TableRow>
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ </TableRow>
+ <TableRow>
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ <RadioButton />
+ </TableRow>
+ </TableLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/fingerprint_isloated.xml b/app/src/main/res/layout/fingerprint_isloated.xml
new file mode 100644
index 0000000..961f3bd
--- /dev/null
+++ b/app/src/main/res/layout/fingerprint_isloated.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout android:gravity="center_horizontal"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
+ <android.support.v7.widget.AppCompatImageView
+ android:id="@+id/fingerprint_animator"
+ android:layout_width="@dimen/fingerprint_animation_size"
+ android:layout_height="@dimen/fingerprint_animation_size"
+ app:background="@drawable/fp_illustration_enrollment"
+ app:backgroundTint="@color/fingerprint_indicator_background_resting"
+ />
+ <CheckBox
+ android:id="@+id/check_show_background"
+ android:checked="true"
+ android:text="Show Background"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+</LinearLayout> \ No newline at end of file
diff --git a/art/AppearAnimation.gif b/art/AppearAnimation.gif
new file mode 100644
index 0000000..03c2031
--- /dev/null
+++ b/art/AppearAnimation.gif
Binary files differ
diff --git a/art/appear_animation_demo.mp4 b/art/appear_animation_demo.mp4
new file mode 100644
index 0000000..54ad2e7
--- /dev/null
+++ b/art/appear_animation_demo.mp4
Binary files differ
diff --git a/build.gradle b/build.gradle
index 540ef2b..c1344f9 100644
--- a/build.gradle
+++ b/build.gradle
@@ -17,6 +17,11 @@ buildscript {
}
allprojects {
+ gradle.projectsEvaluated {
+ tasks.withType(JavaCompile) {
+ options.compilerArgs.add('-Xbootclasspath/p:app\\lib\\classes.jar')
+ }
+ }
repositories {
google()
jcenter()
diff --git a/library/build.gradle b/library/build.gradle
index fe4f348..bdb8c18 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -8,7 +8,7 @@ android {
defaultConfig {
- minSdkVersion 15
+ minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
@@ -31,4 +31,5 @@ dependencies {
androidTestCompile 'com.android.support.test:runner:0.5'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
compile 'com.android.support:appcompat-v7:26.0.0'
+ provided files('lib/classes.jar')
}
diff --git a/library/lib/classes.jar b/library/lib/classes.jar
new file mode 100644
index 0000000..1036492
--- /dev/null
+++ b/library/lib/classes.jar
Binary files differ
diff --git a/library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/AppearAnimationCreator.java b/library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/AppearAnimationCreator.java
new file mode 100644
index 0000000..c4d38ff
--- /dev/null
+++ b/library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/AppearAnimationCreator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package top.trumeet.snippet.aospanimation.library.animation;
+
+import android.view.animation.Interpolator;
+
+/**
+ * An interface which can create animations when starting an appear animation with
+ * {@link AppearAnimationUtils}
+ */
+public interface AppearAnimationCreator<T> {
+ void createAnimation(T animatedObject, long delay, long duration,
+ float translationY, boolean appearing, Interpolator interpolator,
+ Runnable finishListener);
+}
diff --git a/library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/AppearAnimationUtils.java b/library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/AppearAnimationUtils.java
new file mode 100644
index 0000000..75237a6
--- /dev/null
+++ b/library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/AppearAnimationUtils.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package top.trumeet.snippet.aospanimation.library.animation;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.view.RenderNodeAnimator;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import top.trumeet.snippet.aospanimation.library.R;
+
+/**
+ * A class to make nice appear transitions for views in a tabular layout.
+ *
+ * TODO: use non-hidden apis and support pre-lollipop roms
+ */
+@TargetApi(21)
+public class AppearAnimationUtils implements AppearAnimationCreator<View> {
+
+ public static final long DEFAULT_APPEAR_DURATION = 220;
+
+ private final Interpolator mInterpolator;
+ private final float mStartTranslation;
+ private final AppearAnimationProperties mProperties = new AppearAnimationProperties();
+ protected final float mDelayScale;
+ private final long mDuration;
+ protected RowTranslationScaler mRowTranslationScaler;
+ protected boolean mAppearing;
+
+ public AppearAnimationUtils(Context ctx) {
+ this(ctx, DEFAULT_APPEAR_DURATION,
+ 1.0f, 1.0f,
+ AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in));
+ }
+
+ public AppearAnimationUtils(Context ctx, long duration, float translationScaleFactor,
+ float delayScaleFactor, Interpolator interpolator) {
+ mInterpolator = interpolator;
+ mStartTranslation = ctx.getResources().getDimensionPixelOffset(
+ R.dimen.appear_y_translation_start) * translationScaleFactor;
+ mDelayScale = delayScaleFactor;
+ mDuration = duration;
+ mAppearing = true;
+ }
+
+ public void startAnimation2d(View[][] objects, final Runnable finishListener) {
+ startAnimation2d(objects, finishListener, this);
+ }
+
+ public void startAnimation(View[] objects, final Runnable finishListener) {
+ startAnimation(objects, finishListener, this);
+ }
+
+ public <T> void startAnimation2d(T[][] objects, final Runnable finishListener,
+ AppearAnimationCreator<T> creator) {
+ AppearAnimationProperties properties = getDelays(objects);
+ startAnimations(properties, objects, finishListener, creator);
+ }
+
+ public <T> void startAnimation(T[] objects, final Runnable finishListener,
+ AppearAnimationCreator<T> creator) {
+ AppearAnimationProperties properties = getDelays(objects);
+ startAnimations(properties, objects, finishListener, creator);
+ }
+
+ private <T> void startAnimations(AppearAnimationProperties properties, T[] objects,
+ final Runnable finishListener, AppearAnimationCreator<T> creator) {
+ if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) {
+ finishListener.run();
+ return;
+ }
+ for (int row = 0; row < properties.delays.length; row++) {
+ long[] columns = properties.delays[row];
+ long delay = columns[0];
+ Runnable endRunnable = null;
+ if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == 0) {
+ endRunnable = finishListener;
+ }
+ float translationScale = mRowTranslationScaler != null
+ ? mRowTranslationScaler.getRowTranslationScale(row, properties.delays.length)
+ : 1f;
+ float translation = translationScale * mStartTranslation;
+ creator.createAnimation(objects[row], delay, mDuration,
+ mAppearing ? translation : -translation,
+ mAppearing, mInterpolator, endRunnable);
+ }
+ }
+
+ private <T> void startAnimations(AppearAnimationProperties properties, T[][] objects,
+ final Runnable finishListener, AppearAnimationCreator<T> creator) {
+ if (properties.maxDelayRowIndex == -1 || properties.maxDelayColIndex == -1) {
+ if (finishListener != null) finishListener.run();
+ return;
+ }
+ for (int row = 0; row < properties.delays.length; row++) {
+ long[] columns = properties.delays[row];
+ float translationScale = mRowTranslationScaler != null
+ ? mRowTranslationScaler.getRowTranslationScale(row, properties.delays.length)
+ : 1f;
+ float translation = translationScale * mStartTranslation;
+ for (int col = 0; col < columns.length; col++) {
+ long delay = columns[col];
+ Runnable endRunnable = null;
+ if (properties.maxDelayRowIndex == row && properties.maxDelayColIndex == col) {
+ endRunnable = finishListener;
+ }
+ creator.createAnimation(objects[row][col], delay, mDuration,
+ mAppearing ? translation : -translation,
+ mAppearing, mInterpolator, endRunnable);
+ }
+ }
+ }
+
+ private <T> AppearAnimationProperties getDelays(T[] items) {
+ long maxDelay = -1;
+ mProperties.maxDelayColIndex = -1;
+ mProperties.maxDelayRowIndex = -1;
+ mProperties.delays = new long[items.length][];
+ for (int row = 0; row < items.length; row++) {
+ mProperties.delays[row] = new long[1];
+ long delay = calculateDelay(row, 0);
+ mProperties.delays[row][0] = delay;
+ if (items[row] != null && delay > maxDelay) {
+ maxDelay = delay;
+ mProperties.maxDelayColIndex = 0;
+ mProperties.maxDelayRowIndex = row;
+ }
+ }
+ return mProperties;
+ }
+
+ private <T> AppearAnimationProperties getDelays(T[][] items) {
+ long maxDelay = -1;
+ mProperties.maxDelayColIndex = -1;
+ mProperties.maxDelayRowIndex = -1;
+ mProperties.delays = new long[items.length][];
+ for (int row = 0; row < items.length; row++) {
+ T[] columns = items[row];
+ mProperties.delays[row] = new long[columns.length];
+ for (int col = 0; col < columns.length; col++) {
+ long delay = calculateDelay(row, col);
+ mProperties.delays[row][col] = delay;
+ if (items[row][col] != null && delay > maxDelay) {
+ maxDelay = delay;
+ mProperties.maxDelayColIndex = col;
+ mProperties.maxDelayRowIndex = row;
+ }
+ }
+ }
+ return mProperties;
+ }
+
+ protected long calculateDelay(int row, int col) {
+ return (long) ((row * 40 + col * (Math.pow(row, 0.4) + 0.4) * 20) * mDelayScale);
+ }
+
+ public Interpolator getInterpolator() {
+ return mInterpolator;
+ }
+
+ public float getStartTranslation() {
+ return mStartTranslation;
+ }
+
+ @Override
+ public void createAnimation(final View view, long delay, long duration, float translationY,
+ boolean appearing, Interpolator interpolator, final Runnable endRunnable) {
+ if (view != null) {
+ view.setAlpha(appearing ? 0f : 1.0f);
+ view.setTranslationY(appearing ? translationY : 0);
+ Animator alphaAnim;
+ float targetAlpha = appearing ? 1f : 0f;
+ if (view.isHardwareAccelerated()) {
+ // TODO: Use non-hidden and compat API
+ RenderNodeAnimator alphaAnimRt = new RenderNodeAnimator(RenderNodeAnimator.ALPHA,
+ targetAlpha);
+ alphaAnimRt.setTarget(view);
+ alphaAnim = alphaAnimRt;
+ } else {
+ alphaAnim = ObjectAnimator.ofFloat(view, View.ALPHA, view.getAlpha(), targetAlpha);
+ }
+ alphaAnim.setInterpolator(interpolator);
+ alphaAnim.setDuration(duration);
+ alphaAnim.setStartDelay(delay);
+ if (view.hasOverlappingRendering()) {
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ alphaAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ view.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ });
+ }
+ if (endRunnable != null) {
+ alphaAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ endRunnable.run();
+ }
+ });
+ }
+ alphaAnim.start();
+ startTranslationYAnimation(view, delay, duration, appearing ? 0 : translationY,
+ interpolator);
+ }
+ }
+
+ public static void startTranslationYAnimation(View view, long delay, long duration,
+ float endTranslationY, Interpolator interpolator) {
+ Animator translationAnim;
+ if (view.isHardwareAccelerated()) {
+ RenderNodeAnimator translationAnimRt = new RenderNodeAnimator(
+ RenderNodeAnimator.TRANSLATION_Y, endTranslationY);
+ translationAnimRt.setTarget(view);
+ translationAnim = translationAnimRt;
+ } else {
+ translationAnim = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y,
+ view.getTranslationY(), endTranslationY);
+ }
+ translationAnim.setInterpolator(interpolator);
+ translationAnim.setDuration(duration);
+ translationAnim.setStartDelay(delay);
+ translationAnim.start();
+ }
+
+ public class AppearAnimationProperties {
+ public long[][] delays;
+ public int maxDelayRowIndex;
+ public int maxDelayColIndex;
+ }
+
+ public interface RowTranslationScaler {
+ float getRowTranslationScale(int row, int numRows);
+ }
+}
diff --git a/library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/DisappearAnimationUtils.java b/library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/DisappearAnimationUtils.java
new file mode 100644
index 0000000..42c99e1
--- /dev/null
+++ b/library/src/main/java/top/trumeet/snippet/aospanimation/library/animation/DisappearAnimationUtils.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package top.trumeet.snippet.aospanimation.library.animation;
+
+import android.content.Context;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+/**
+ * A class to make nice disappear transitions for views in a tabular layout.
+ */
+public class DisappearAnimationUtils extends AppearAnimationUtils {
+
+ public DisappearAnimationUtils(Context ctx) {
+ this(ctx, DEFAULT_APPEAR_DURATION,
+ 1.0f, 1.0f,
+ AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_linear_in));
+ }
+
+ public DisappearAnimationUtils(Context ctx, long duration, float translationScaleFactor,
+ float delayScaleFactor, Interpolator interpolator) {
+ this(ctx, duration, translationScaleFactor, delayScaleFactor, interpolator,
+ ROW_TRANSLATION_SCALER);
+ }
+
+ public DisappearAnimationUtils(Context ctx, long duration, float translationScaleFactor,
+ float delayScaleFactor, Interpolator interpolator, RowTranslationScaler rowScaler) {
+ super(ctx, duration, translationScaleFactor, delayScaleFactor, interpolator);
+ mRowTranslationScaler = rowScaler;
+ mAppearing = false;
+ }
+
+ protected long calculateDelay(int row, int col) {
+ return (long) ((row * 60 + col * (Math.pow(row, 0.4) + 0.4) * 10) * mDelayScale);
+ }
+
+ private static final RowTranslationScaler ROW_TRANSLATION_SCALER = new RowTranslationScaler() {
+
+ @Override
+ public float getRowTranslationScale(int row, int numRows) {
+ return (float) (Math.pow((numRows - row), 2) / numRows);
+ }
+ };
+}
diff --git a/library/src/main/res/anim/confirm_credential_close_enter.xml b/library/src/main/res/anim/confirm_credential_close_enter.xml
new file mode 100644
index 0000000..fcc3241
--- /dev/null
+++ b/library/src/main/res/anim/confirm_credential_close_enter.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
+ <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
+ android:interpolator="@*android:interpolator/decelerate_quart"
+ android:fillEnabled="true"
+ android:fillBefore="false" android:fillAfter="true"
+ android:duration="200"/>
+ <translate android:fromYDelta="8%" android:toYDelta="0"
+ android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
+ android:interpolator="@*android:interpolator/decelerate_quint"
+ android:duration="350"/>
+</set>
diff --git a/library/src/main/res/anim/confirm_credential_close_exit.xml b/library/src/main/res/anim/confirm_credential_close_exit.xml
new file mode 100644
index 0000000..5afd8b2
--- /dev/null
+++ b/library/src/main/res/anim/confirm_credential_close_exit.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2015 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:interpolator/linear_out_slow_in"
+ android:fromAlpha="1.0" android:toAlpha="0.0"
+ android:duration="350" />
diff --git a/library/src/main/res/anim/fast_out_linear_in.xml b/library/src/main/res/anim/fast_out_linear_in.xml
new file mode 100644
index 0000000..19f95a6
--- /dev/null
+++ b/library/src/main/res/anim/fast_out_linear_in.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0.4"
+ android:controlY1="0"
+ android:controlX2="1"
+ android:controlY2="1"/>
diff --git a/library/src/main/res/anim/linear_out_slow_in.xml b/library/src/main/res/anim/linear_out_slow_in.xml
new file mode 100644
index 0000000..83fc223
--- /dev/null
+++ b/library/src/main/res/anim/linear_out_slow_in.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0"
+ android:controlY1="0"
+ android:controlX2="0.2"
+ android:controlY2="1"/>
diff --git a/library/src/main/res/values/dimens.xml b/library/src/main/res/values/dimens.xml
index 7a84eac..6d5e6c4 100644
--- a/library/src/main/res/values/dimens.xml
+++ b/library/src/main/res/values/dimens.xml
@@ -1,4 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="fingerprint_animation_size">88dp</dimen>
+
+ <!-- The y translation to apply at the start in appear animations. -->
+ <dimen name="appear_y_translation_start">32dp</dimen>
</resources> \ No newline at end of file