From accf71cc2f859c8c8d241e7f67fe118ac82bf6f5 Mon Sep 17 00:00:00 2001 From: Clark Scheff Date: Wed, 16 Jul 2014 16:53:08 -0700 Subject: Add applying theme progress along with animations. Change-Id: Id7835d3be0b9d9c8d861e820e63b45e17235ef68 --- AndroidManifest.xml | 1 + res/drawable/apply_progress_background.xml | 8 ++ res/drawable/apply_progress_bar.xml | 12 ++ res/drawable/apply_progress_indicator.xml | 8 ++ res/layout/v2_fragment_pager_list.xml | 67 +++++++---- res/values/colors.xml | 3 + res/values/dimens.xml | 1 + src/android/support/v4/view/ThemeViewPager.java | 2 +- .../theme/chooserv2/ChooserActivity.java | 23 +++- .../cyanogenmod/theme/chooserv2/ThemeFragment.java | 133 +++++++++++++++++++-- 10 files changed, 218 insertions(+), 40 deletions(-) create mode 100644 res/drawable/apply_progress_background.xml create mode 100644 res/drawable/apply_progress_bar.xml create mode 100644 res/drawable/apply_progress_indicator.xml diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 92cd060..c11a5a9 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -44,6 +44,7 @@ diff --git a/res/drawable/apply_progress_background.xml b/res/drawable/apply_progress_background.xml new file mode 100644 index 0000000..47c2530 --- /dev/null +++ b/res/drawable/apply_progress_background.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/res/drawable/apply_progress_bar.xml b/res/drawable/apply_progress_bar.xml new file mode 100644 index 0000000..a3cbc6f --- /dev/null +++ b/res/drawable/apply_progress_bar.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/apply_progress_indicator.xml b/res/drawable/apply_progress_indicator.xml new file mode 100644 index 0000000..0f332ed --- /dev/null +++ b/res/drawable/apply_progress_indicator.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/res/layout/v2_fragment_pager_list.xml b/res/layout/v2_fragment_pager_list.xml index 70c1b3c..fc3c26e 100644 --- a/res/layout/v2_fragment_pager_list.xml +++ b/res/layout/v2_fragment_pager_list.xml @@ -40,39 +40,56 @@ - - + + - + - + + - + android:layout_gravity="center_vertical|right" + android:padding="@dimen/apply_progress_padding" + android:indeterminate="false" + android:max="100" + android:progress="0" + android:progressDrawable="@drawable/apply_progress_bar" + android:visibility="gone" + style="@android:style/Widget.ProgressBar.Horizontal"/> + \ No newline at end of file diff --git a/res/values/colors.xml b/res/values/colors.xml index c25d282..cdc1eca 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -41,4 +41,7 @@ #cd00b3e6 #cd1fcdff #cd0093bd + + #e0dfe1 + #00b3e6 diff --git a/res/values/dimens.xml b/res/values/dimens.xml index a6586ed..346c22f 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -65,4 +65,5 @@ 4dp 10dp + 10dp diff --git a/src/android/support/v4/view/ThemeViewPager.java b/src/android/support/v4/view/ThemeViewPager.java index 9a4ce9d..cf13871 100644 --- a/src/android/support/v4/view/ThemeViewPager.java +++ b/src/android/support/v4/view/ThemeViewPager.java @@ -49,7 +49,7 @@ public class ThemeViewPager extends ViewPager { public boolean onInterceptTouchEvent(MotionEvent ev) { boolean intercept = false; - if (!mExpanded) { + if (!mExpanded && isEnabled()) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: intercept = !isTouchingApplyButton(ev); diff --git a/src/org/cyanogenmod/theme/chooserv2/ChooserActivity.java b/src/org/cyanogenmod/theme/chooserv2/ChooserActivity.java index 72b936e..3c4adca 100644 --- a/src/org/cyanogenmod/theme/chooserv2/ChooserActivity.java +++ b/src/org/cyanogenmod/theme/chooserv2/ChooserActivity.java @@ -35,19 +35,15 @@ import android.support.v4.view.ViewPager; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.View; -import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.Button; -import android.widget.TextView; import org.cyanogenmod.theme.chooser.R; import org.cyanogenmod.theme.chooserv2.ComponentSelector.OnOpenCloseListener; import org.cyanogenmod.theme.util.TypefaceHelperCache; import org.cyanogenmod.theme.util.Utils; -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_NOTIFICATIONS; @@ -156,6 +152,25 @@ public class ChooserActivity extends FragmentActivity }); } + /** + * Disable the ViewPager while a theme change is occuring + */ + public void themeChangeStarted() { + mPager.setEnabled(false); + } + + /** + * Re-enable the ViewPager and update the "My theme" fragment if available + */ + public void themeChangeEnded() { + ThemeFragment f = (ThemeFragment) getSupportFragmentManager() + .findFragmentByTag(getFragmentTag(0)); + if (f != null) { + f.clearChanges(); + mPager.setEnabled(true); + } + } + public ComponentSelector getComponentSelector() { return mSelector; } diff --git a/src/org/cyanogenmod/theme/chooserv2/ThemeFragment.java b/src/org/cyanogenmod/theme/chooserv2/ThemeFragment.java index 26fad1b..cf0202d 100644 --- a/src/org/cyanogenmod/theme/chooserv2/ThemeFragment.java +++ b/src/org/cyanogenmod/theme/chooserv2/ThemeFragment.java @@ -48,9 +48,13 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.Animation; import android.view.animation.DecelerateInterpolator; +import android.view.animation.ScaleAnimation; import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.TextView; @@ -71,12 +75,17 @@ import static android.provider.ThemesContract.ThemesColumns.MODIFIES_NAVIGATION_ import static android.provider.ThemesContract.ThemesColumns.MODIFIES_ICONS; import static android.provider.ThemesContract.ThemesColumns.MODIFIES_FONTS; -public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallbacks { +public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallbacks, + ThemeManager.ThemeChangeListener { 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 int ANIMATE_PROGRESS_IN_DURATION = 500; + public static final int ANIMATE_TITLE_OUT_DURATION = 400; + public static final int ANIMATE_PROGRESS_OUT_DURATION = 400; + public static final int ANIMATE_TITLE_IN_DURATION = 500; public static final String CURRENTLY_APPLIED_THEME = "currently_applied_theme"; @@ -142,9 +151,11 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb // Title Card Views private ViewGroup mTitleCard; + private ViewGroup mTitleLayout; private TextView mTitle; private ImageView mApply; private ImageView mOverflow; + private ProgressBar mProgress; private Handler mHandler; @@ -186,7 +197,7 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb mHandler = new Handler(); // populate mSelectedComponentsMap with supported components for this theme - if (CURRENTLY_APPLIED_THEME.equals(mPkgName)) { + if (!CURRENTLY_APPLIED_THEME.equals(mPkgName)) { List components = ThemeUtils.getSupportedComponents(getActivity(), mPkgName); mSelectedComponentsMap = new HashMap(components.size()); for (String component : components) { @@ -229,19 +240,14 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb // Title Card mTitleCard = (ViewGroup)v.findViewById(R.id.title_card); + mTitleLayout = (ViewGroup) v.findViewById(R.id.title_layout); mTitle = (TextView) v.findViewById(R.id.title); + mProgress = (ProgressBar) v.findViewById(R.id.apply_progress); mOverflow = (ImageView) v.findViewById(R.id.overflow); mApply = (ImageView) v.findViewById(R.id.apply); mApply.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - Context context = getActivity(); - if (context != null) { - if (mSelectedComponentsMap != null && mSelectedComponentsMap.size() > 0) { - ThemeManager mService = - (ThemeManager) context.getSystemService(Context.THEME_SERVICE); - mService.requestThemeChange(mSelectedComponentsMap); - } - } + applyTheme(); } }); @@ -262,6 +268,28 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb } } + @Override + public void onProgress(int progress) { + mProgress.setProgress(progress); + } + + @Override + public void onFinish(boolean isSuccess) { + // We post a runnable to mHandler so the client is removed from the same thread + mHandler.post(new Runnable() { + @Override + public void run() { + ThemeManager tm = getThemeManager(); + if (tm != null) tm.removeClient(ThemeFragment.this); + } + }); + if (isSuccess) { + mProgress.setProgress(100); + animateProgressOut(); + ((ChooserActivity) getActivity()).themeChangeEnded(); + } + } + public void expand() { // Full width and height! ViewGroup content = (ViewGroup) mScrollView.getParent(); @@ -566,6 +594,14 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb ThemeConfig.getSystemTheme().getFontPkgName(); } + private ThemeManager getThemeManager() { + final Context context = getActivity(); + if (context != null) { + return (ThemeManager) context.getSystemService(Context.THEME_SERVICE); + } + return null; + } + @Override public Loader onCreateLoader(int id, Bundle args) { String pkgName = mPkgName; @@ -982,6 +1018,83 @@ public class ThemeFragment extends Fragment implements LoaderManager.LoaderCallb .animateContentChange(viewToAnimate, overlay, ANIMATE_COMPONENT_CHANGE_DURATION); } + private Runnable mApplyThemeRunnable = new Runnable() { + @Override + public void run() { + final Context context = getActivity(); + if (context != null) { + if (mSelectedComponentsMap != null && mSelectedComponentsMap.size() > 0) { + // Post this on mHandler so the client is added and removed from the same + // thread + mHandler.post(new Runnable() { + @Override + public void run() { + ThemeManager tm = getThemeManager(); + if (tm != null) { + tm.addClient(ThemeFragment.this); + tm.requestThemeChange(mSelectedComponentsMap); + } + } + }); + } + } + } + }; + + private void applyTheme() { + if (mSelectedComponentsMap == null || mSelectedComponentsMap.size() <= 0) return; + ((ChooserActivity) getActivity()).themeChangeStarted(); + animateProgressIn(mApplyThemeRunnable); + } + + private void animateProgressIn(Runnable endAction) { + mProgress.setVisibility(View.VISIBLE); + mProgress.setProgress(0); + float pivotX = mTitleLayout.getWidth() - + getResources().getDimensionPixelSize(R.dimen.apply_progress_padding); + ScaleAnimation scaleAnim = new ScaleAnimation(0f, 1f, 1f, 1f, + pivotX, 0f); + scaleAnim.setDuration(ANIMATE_PROGRESS_IN_DURATION); + + mTitleLayout.animate() + .translationXBy(-(pivotX / 4)) + .alpha(0f) + .setDuration(ANIMATE_TITLE_OUT_DURATION) + .setInterpolator(new AccelerateInterpolator()) + .withEndAction(endAction).start(); + mProgress.startAnimation(scaleAnim); + } + + private void animateProgressOut() { + mProgress.setVisibility(View.VISIBLE); + float pivotX = mTitleLayout.getWidth() - + getResources().getDimensionPixelSize(R.dimen.apply_progress_padding); + ScaleAnimation scaleAnim = new ScaleAnimation(1f, 0f, 1f, 1f, + pivotX, 0f); + scaleAnim.setDuration(ANIMATE_PROGRESS_OUT_DURATION); + scaleAnim.setFillAfter(false); + scaleAnim.setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) {} + + @Override + public void onAnimationEnd(Animation animation) { + mProgress.setVisibility(View.GONE); + } + + @Override + public void onAnimationRepeat(Animation animation) {} + }); + + mTitleLayout.animate() + .translationXBy((pivotX / 4)) + .alpha(1f) + .setDuration(ANIMATE_TITLE_IN_DURATION) + .setInterpolator(new AccelerateInterpolator()) + .start(); + mProgress.startAnimation(scaleAnim); + } + public void fadeInCards() { mActiveCardId = -1; for (int i = 0; i < sCardIdsToComponentTypes.size(); i++) { -- cgit v1.1