summaryrefslogtreecommitdiffstats
path: root/src/org
diff options
context:
space:
mode:
authorClark Scheff <clark@cyngn.com>2014-07-15 15:38:31 -0700
committerClark Scheff <clark@cyngn.com>2014-07-16 09:47:55 -0700
commitb8cdd6817c45ecd077496f036453012d403d68f5 (patch)
tree9474488ffe6bd29dd298791be3dbd9dfc1f4894b /src/org
parent00e3dddcb33d332ed432ce5e1eba704a91ca58a0 (diff)
downloadpackages_apps_ThemeChooser-b8cdd6817c45ecd077496f036453012d403d68f5.zip
packages_apps_ThemeChooser-b8cdd6817c45ecd077496f036453012d403d68f5.tar.gz
packages_apps_ThemeChooser-b8cdd6817c45ecd077496f036453012d403d68f5.tar.bz2
Animate icon change in card when changing icons.
Change-Id: Ibb4d825c3c1d53006b7f8f6df69ac1b00c95adda
Diffstat (limited to 'src/org')
-rw-r--r--src/org/cyanogenmod/theme/chooserv2/IconTransitionDrawable.java171
-rw-r--r--src/org/cyanogenmod/theme/chooserv2/ThemeFragment.java39
2 files changed, 197 insertions, 13 deletions
diff --git a/src/org/cyanogenmod/theme/chooserv2/IconTransitionDrawable.java b/src/org/cyanogenmod/theme/chooserv2/IconTransitionDrawable.java
new file mode 100644
index 0000000..c0138a1
--- /dev/null
+++ b/src/org/cyanogenmod/theme/chooserv2/IconTransitionDrawable.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 The CyanogenMod 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 org.cyanogenmod.theme.chooserv2;
+
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.os.SystemClock;
+
+/**
+ * An extension of LayerDrawables that is intended to cross-fade between
+ * the first and second layer. To start the transition, call {@link #startTransition(int)}. To
+ * display just the first layer, call {@link #resetTransition()}.
+ * <p>
+ * It can be defined in an XML file with the <code>&lt;transition></code> element.
+ * Each Drawable in the transition is defined in a nested <code>&lt;item></code>. For more
+ * information, see the guide to <a
+ * href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.</p>
+ *
+ * @attr ref android.R.styleable#LayerDrawableItem_left
+ * @attr ref android.R.styleable#LayerDrawableItem_top
+ * @attr ref android.R.styleable#LayerDrawableItem_right
+ * @attr ref android.R.styleable#LayerDrawableItem_bottom
+ * @attr ref android.R.styleable#LayerDrawableItem_drawable
+ * @attr ref android.R.styleable#LayerDrawableItem_id
+ *
+ */
+public class IconTransitionDrawable extends LayerDrawable {
+
+ /**
+ * A transition is about to start.
+ */
+ private static final int TRANSITION_STARTING = 0;
+
+ /**
+ * The transition has started and the animation is in progress
+ */
+ private static final int TRANSITION_RUNNING = 1;
+
+ /**
+ * No transition will be applied
+ */
+ private static final int TRANSITION_NONE = 2;
+
+ /**
+ * The current state of the transition. One of {@link #TRANSITION_STARTING},
+ * {@link #TRANSITION_RUNNING} and {@link #TRANSITION_NONE}
+ */
+ private int mTransitionState = TRANSITION_NONE;
+
+ private long mStartTimeMillis;
+ private int mFrom;
+ private int mTo;
+ private int mDuration;
+ private int mAlpha = 0;
+ private float mFromScale;
+ private float mToScale;
+
+ /**
+ * Create a new transition drawable with the specified list of layers. At least
+ * 2 layers are required for this drawable to work properly.
+ */
+ public IconTransitionDrawable(Drawable[] layers) {
+ super(layers);
+ }
+
+ /**
+ * Begin the second layer on top of the first layer.
+ *
+ * @param durationMillis The length of the transition in milliseconds
+ */
+ public void startTransition(int durationMillis) {
+ mFrom = 0;
+ mTo = 255;
+ mAlpha = 0;
+ mFromScale = 0f;
+ mToScale = 1.0f;
+ mDuration = durationMillis;
+ mTransitionState = TRANSITION_STARTING;
+ invalidateSelf();
+ }
+
+ /**
+ * Show only the first layer.
+ */
+ public void resetTransition() {
+ mAlpha = 0;
+ mTransitionState = TRANSITION_NONE;
+ invalidateSelf();
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ boolean done = true;
+ float scale = 0f;
+
+ switch (mTransitionState) {
+ case TRANSITION_STARTING:
+ mStartTimeMillis = SystemClock.uptimeMillis();
+ done = false;
+ mTransitionState = TRANSITION_RUNNING;
+ break;
+
+ case TRANSITION_RUNNING:
+ if (mStartTimeMillis >= 0) {
+ float normalized = (float)
+ (SystemClock.uptimeMillis() - mStartTimeMillis) / mDuration;
+ done = normalized >= 1.0f;
+ normalized = Math.min(normalized, 1.0f);
+ mAlpha = (int) (mFrom + (mTo - mFrom) * normalized);
+ scale = mFromScale + (mToScale - mFromScale) * normalized;
+ }
+ break;
+ }
+
+ final int alpha = mAlpha;
+
+ if (done) {
+ // the setAlpha() calls below trigger invalidation and redraw. If we're done, just draw
+ // the appropriate drawable[s] and return
+ if (alpha == 0) {
+ getDrawable(0).draw(canvas);
+ }
+ if (alpha == 0xFF) {
+ getDrawable(1).draw(canvas);
+
+ }
+ return;
+ }
+
+ Drawable d;
+ d = getDrawable(0);
+ d.setAlpha(255 - alpha);
+ int cx = getIntrinsicWidth() / 2;
+ int cy = getIntrinsicHeight() / 2;
+ canvas.save();
+ canvas.scale(1.0f - scale, 1.0f - scale, cx, cy);
+ d.draw(canvas);
+ canvas.restore();
+ d.setAlpha(0xFF);
+
+ if (alpha > 0) {
+ d = getDrawable(1);
+ d.setAlpha(alpha);
+ canvas.save();
+ canvas.scale(scale, scale, cx, cy);
+ d.draw(canvas);
+ canvas.restore();
+ d.setAlpha(0xFF);
+ }
+
+ if (!done) {
+ invalidateSelf();
+ }
+ }
+}
diff --git a/src/org/cyanogenmod/theme/chooserv2/ThemeFragment.java b/src/org/cyanogenmod/theme/chooserv2/ThemeFragment.java
index 85fae45..09df7ea 100644
--- a/src/org/cyanogenmod/theme/chooserv2/ThemeFragment.java
+++ b/src/org/cyanogenmod/theme/chooserv2/ThemeFragment.java
@@ -66,12 +66,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import static android.provider.ThemesContract.ThemesColumns.MODIFIES_ALARMS;
-import static android.provider.ThemesContract.ThemesColumns.MODIFIES_BOOT_ANIM;
-import static android.provider.ThemesContract.ThemesColumns.MODIFIES_LAUNCHER;
-import static android.provider.ThemesContract.ThemesColumns.MODIFIES_NOTIFICATIONS;
-import static android.provider.ThemesContract.ThemesColumns.MODIFIES_OVERLAYS;
-import static android.provider.ThemesContract.ThemesColumns.MODIFIES_RINGTONES;
import static android.provider.ThemesContract.ThemesColumns.MODIFIES_STATUS_BAR;
import static android.provider.ThemesContract.ThemesColumns.MODIFIES_NAVIGATION_BAR;
import static android.provider.ThemesContract.ThemesColumns.MODIFIES_ICONS;
@@ -81,6 +75,8 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb
public static final int ANIMATE_START_DELAY = 200;
public static final int ANIMATE_DURATION = 300;
public static final int ANIMATE_INTERPOLATE_FACTOR = 3;
+ public static final int ANIMATE_COMPONENT_CHANGE_DURATION = 200;
+ public static final int ANIMATE_COMPONENT_ICON_DELAY = 50;
public static final String CURRENTLY_APPLIED_THEME = "currently_applied_theme";
@@ -694,7 +690,7 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb
case LOADER_ID_ALL:
loadWallpaper(c);
loadStatusBar(c);
- loadIcons(c);
+ loadIcons(c, false);
loadNavBar(c);
loadTitle(c);
loadFont(c);
@@ -706,7 +702,7 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb
loadFont(c);
break;
case LOADER_ID_ICONS:
- loadIcons(c);
+ loadIcons(c, true);
break;
case LOADER_ID_WALLPAPER:
loadWallpaper(c);
@@ -787,7 +783,7 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb
}
}
- private void loadIcons(Cursor c) {
+ private void loadIcons(Cursor c, boolean animate) {
int[] iconIdx = new int[4];
iconIdx[0] = c.getColumnIndex(PreviewColumns.ICON_PREVIEW_1);
iconIdx[1] = c.getColumnIndex(PreviewColumns.ICON_PREVIEW_2);
@@ -800,15 +796,32 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb
IconPreviewHelper helper = new IconPreviewHelper(getActivity(), "");
ViewGroup container = (ViewGroup) mIconContainer.findViewById(R.id.icon_preview_container);
for(int i=0; i < container.getChildCount() && i < iconIdx.length; i++) {
- ImageView v = (ImageView) ((ViewGroup)mIconContainer.getChildAt(1)).getChildAt(i);
+ final ImageView v = (ImageView) ((ViewGroup)mIconContainer.getChildAt(1)).getChildAt(i);
Bitmap bitmap = Utils.loadBitmapBlob(c, iconIdx[i]);
+ Drawable oldIcon = v.getDrawable();
+ Drawable newIcon;
if (bitmap == null) {
ComponentName component = sIconComponents[i];
- Drawable icon = helper.getDefaultIcon(component.getPackageName(),
+ newIcon = helper.getDefaultIcon(component.getPackageName(),
component.getClassName());
- v.setImageDrawable(icon);
} else {
- v.setImageBitmap(bitmap);
+ newIcon = new BitmapDrawable(getResources(), bitmap);
+ }
+ if (animate) {
+ Drawable[] layers = new Drawable[2];
+ layers[0] = oldIcon instanceof IconTransitionDrawable ?
+ ((IconTransitionDrawable) oldIcon).getDrawable(1) : oldIcon;
+ layers[1] = newIcon;
+ final IconTransitionDrawable itd = new IconTransitionDrawable(layers);
+ v.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ itd.startTransition(ANIMATE_COMPONENT_CHANGE_DURATION);
+ v.setImageDrawable(itd);
+ }
+ }, ANIMATE_COMPONENT_ICON_DELAY * i);
+ } else {
+ v.setImageDrawable(newIcon);
}
}
if (pkgNameIdx > -1) {