summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Lehmann <lehmannd@google.com>2012-05-10 18:41:21 -0700
committerDaniel Lehmann <lehmannd@google.com>2012-05-10 18:41:21 -0700
commit2426cb015ba4cb679a525bd1ffe223527375468c (patch)
tree0c0eec9fc2a0795f55f2224810b2217593544c1e
parentfcaad61ff3101f449c2ec8601d0d27a107c67cc6 (diff)
downloadpackages_apps_Contacts-2426cb015ba4cb679a525bd1ffe223527375468c.tar.gz
packages_apps_Contacts-2426cb015ba4cb679a525bd1ffe223527375468c.tar.bz2
packages_apps_Contacts-2426cb015ba4cb679a525bd1ffe223527375468c.zip
Fix some QC issues
Bug:6449630 Change-Id: I5aec3ffdd3032bd3d037a053f5cb86fc9f0f16e0
-rw-r--r--src/com/android/contacts/quickcontact/FloatingChildLayout.java101
-rw-r--r--src/com/android/contacts/quickcontact/QuickContactActivity.java58
2 files changed, 92 insertions, 67 deletions
diff --git a/src/com/android/contacts/quickcontact/FloatingChildLayout.java b/src/com/android/contacts/quickcontact/FloatingChildLayout.java
index 6302c5d9b..dca738c4b 100644
--- a/src/com/android/contacts/quickcontact/FloatingChildLayout.java
+++ b/src/com/android/contacts/quickcontact/FloatingChildLayout.java
@@ -23,15 +23,13 @@ import android.animation.AnimatorListenerAdapter;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.graphics.drawable.TransitionDrawable;
-import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewPropertyAnimator;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.PopupWindow;
@@ -53,11 +51,30 @@ public class FloatingChildLayout extends FrameLayout {
private static final String TAG = "FloatingChildLayout";
private int mFixedTopPosition;
private View mChild;
- private boolean mIsShowingChild;
private Rect mTargetScreen = new Rect();
private final int mAnimationDuration;
private final TransitionDrawable mBackground;
+ /** The phase of the background dim. This is one of the values of {@link BackgroundPhase} */
+ private int mBackgroundPhase = BackgroundPhase.BEFORE;
+
+ private interface BackgroundPhase {
+ public static final int BEFORE = 0;
+ public static final int APPEARING_OR_VISIBLE = 1;
+ public static final int DISAPPEARING_OR_GONE = 3;
+ }
+
+ /** The phase of the contents window. This is one of the values of {@link ForegroundPhase} */
+ private int mForegroundPhase = ForegroundPhase.BEFORE;
+
+ private interface ForegroundPhase {
+ public static final int BEFORE = 0;
+ public static final int APPEARING = 1;
+ public static final int IDLE = 2;
+ public static final int DISAPPEARING = 3;
+ public static final int AFTER = 4;
+ }
+
// Black, 50% alpha as per the system default.
private static final int DIM_BACKGROUND_COLOR = 0x7F000000;
@@ -83,8 +100,6 @@ public class FloatingChildLayout extends FrameLayout {
mChild.setScaleX(0.5f);
mChild.setScaleY(0.5f);
mChild.setAlpha(0.0f);
-
- mIsShowingChild = false;
}
public View getChild() {
@@ -163,43 +178,51 @@ public class FloatingChildLayout extends FrameLayout {
child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
}
- /** Begin animating {@link #getChild()} visible. */
- public void showChild(final Runnable onAnimationEndRunnable) {
- if (mIsShowingChild) return;
- mIsShowingChild = true;
-
- // TODO: understand this.
- // For some reason this needs wait a tick in order to avoid jank.
- // Maybe because we set up a hardware layer in animateScale()?
- // Probably not, since it should also be required in hideChild().
- new Handler().post(new Runnable() {
- @Override public void run() {
- animateBackground(false);
- }
- });
+ public void fadeInBackground() {
+ if (mBackgroundPhase == BackgroundPhase.BEFORE) {
+ mBackgroundPhase = BackgroundPhase.APPEARING_OR_VISIBLE;
+ mBackground.startTransition(mAnimationDuration);
+ }
+ }
- animateScale(false, onAnimationEndRunnable);
+ public void fadeOutBackground() {
+ if (mBackgroundPhase == BackgroundPhase.APPEARING_OR_VISIBLE) {
+ mBackgroundPhase = BackgroundPhase.DISAPPEARING_OR_GONE;
+ mBackground.reverseTransition(mAnimationDuration);
+ }
}
- /** Begin animating {@link #getChild()} invisible. */
- public void hideChild(final Runnable onAnimationEndRunnable) {
- if (!mIsShowingChild) return;
- mIsShowingChild = false;
+ public boolean isContentFullyVisible() {
+ return mForegroundPhase == ForegroundPhase.IDLE;
+ }
- animateBackground(true);
- animateScale(true, onAnimationEndRunnable);
+ /** Begin animating {@link #getChild()} visible. */
+ public void showContent(final Runnable onAnimationEndRunnable) {
+ if (mForegroundPhase == ForegroundPhase.BEFORE) {
+ mForegroundPhase = ForegroundPhase.APPEARING;
+ animateScale(false, onAnimationEndRunnable);
+ }
}
- private void animateBackground(boolean isExitAnimation) {
- if (isExitAnimation) {
- mBackground.reverseTransition(mAnimationDuration);
+ /**
+ * Begin animating {@link #getChild()} invisible. Returns false if animation is not valid in
+ * this state
+ */
+ public boolean hideContent(final Runnable onAnimationEndRunnable) {
+ if (mForegroundPhase == ForegroundPhase.APPEARING ||
+ mForegroundPhase == ForegroundPhase.IDLE) {
+ mForegroundPhase = ForegroundPhase.DISAPPEARING;
+ animateScale(true, onAnimationEndRunnable);
+ return true;
} else {
- mBackground.startTransition(mAnimationDuration);
+ return false;
}
}
/** Creates the open/close animation */
- private void animateScale(boolean isExitAnimation, final Runnable onAnimationEndRunnable) {
+ private void animateScale(
+ final boolean isExitAnimation,
+ final Runnable onAnimationEndRunnable) {
mChild.setPivotX(mTargetScreen.centerX() - mChild.getLeft());
mChild.setPivotY(mTargetScreen.centerY() - mChild.getTop());
@@ -208,7 +231,7 @@ public class FloatingChildLayout extends FrameLayout {
: android.R.interpolator.decelerate_quint;
final float scaleTarget = isExitAnimation ? 0.5f : 1.0f;
- ViewPropertyAnimator animator = mChild.animate().withLayer()
+ mChild.animate().withLayer()
.setDuration(mAnimationDuration)
.setInterpolator(AnimationUtils.loadInterpolator(getContext(), scaleInterpolator))
.scaleX(scaleTarget)
@@ -217,7 +240,17 @@ public class FloatingChildLayout extends FrameLayout {
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- if (onAnimationEndRunnable != null) onAnimationEndRunnable.run();
+ if (isExitAnimation) {
+ if (mForegroundPhase == ForegroundPhase.DISAPPEARING) {
+ mForegroundPhase = ForegroundPhase.AFTER;
+ if (onAnimationEndRunnable != null) onAnimationEndRunnable.run();
+ }
+ } else {
+ if (mForegroundPhase == ForegroundPhase.APPEARING) {
+ mForegroundPhase = ForegroundPhase.IDLE;
+ if (onAnimationEndRunnable != null) onAnimationEndRunnable.run();
+ }
+ }
}
});
}
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
index b65696906..5fe34e001 100644
--- a/src/com/android/contacts/quickcontact/QuickContactActivity.java
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -98,9 +98,6 @@ public class QuickContactActivity extends Activity {
private String[] mExcludeMimes;
private List<String> mSortedActionMimeTypes = Lists.newArrayList();
- private boolean mHasFinishedAnimatingIn = false;
- private boolean mHasStartedAnimatingOut = false;
-
private FloatingChildLayout mFloatingLayout;
private View mPhotoContainer;
@@ -154,6 +151,8 @@ public class QuickContactActivity extends Activity {
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ if (TRACE_LAUNCH) android.os.Debug.startMethodTracing(TRACE_TAG);
+
// Show QuickContact in front of soft input
getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
@@ -172,7 +171,8 @@ public class QuickContactActivity extends Activity {
mFloatingLayout.setOnOutsideTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
- return handleOutsideTouch();
+ handleOutsideTouch();
+ return true;
}
});
@@ -183,7 +183,7 @@ public class QuickContactActivity extends Activity {
mContactLoader.cacheResult();
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
startActivity(intent);
- hide(false);
+ close(false);
}
};
mOpenDetailsButton.setOnClickListener(openDetailsClickHandler);
@@ -191,15 +191,6 @@ public class QuickContactActivity extends Activity {
mListPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
mListPager.setOnPageChangeListener(new PageChangeListener());
- show();
- }
-
- private void show() {
-
- if (TRACE_LAUNCH) {
- android.os.Debug.startMethodTracing(TRACE_TAG);
- }
-
final Intent intent = getIntent();
Uri lookupUri = intent.getData();
@@ -226,23 +217,23 @@ public class QuickContactActivity extends Activity {
mContactLoader = (ContactLoader) getLoaderManager().initLoader(
LOADER_ID, null, mLoaderCallbacks);
- }
- private boolean handleOutsideTouch() {
- if (!mHasFinishedAnimatingIn) return false;
- if (mHasStartedAnimatingOut) return false;
+ mFloatingLayout.fadeInBackground();
+ }
- mHasStartedAnimatingOut = true;
- hide(true);
- return true;
+ private void handleOutsideTouch() {
+ if (mFloatingLayout.isContentFullyVisible()) {
+ close(true);
+ }
}
- private void hide(boolean withAnimation) {
+ private void close(boolean withAnimation) {
// cancel any pending queries
getLoaderManager().destroyLoader(LOADER_ID);
if (withAnimation) {
- mFloatingLayout.hideChild(new Runnable() {
+ mFloatingLayout.fadeOutBackground();
+ final boolean animated = mFloatingLayout.hideContent(new Runnable() {
@Override
public void run() {
// Wait until the final animation frame has been drawn, otherwise
@@ -266,15 +257,19 @@ public class QuickContactActivity extends Activity {
});
}
});
+ if (!animated) {
+ // If we were in the wrong state, simply quit (this can happen for example
+ // if the user pushes BACK before anything has loaded)
+ finish();
+ }
} else {
- mFloatingLayout.hideChild(null);
finish();
}
}
@Override
public void onBackPressed() {
- hide(true);
+ close(true);
}
/** Assign this string to the view if it is not empty. */
@@ -480,7 +475,7 @@ public class QuickContactActivity extends Activity {
@Override
public void onLoadFinished(Loader<ContactLoader.Result> loader, ContactLoader.Result data) {
if (isFinishing()) {
- hide(false);
+ close(false);
return;
}
if (data.isError()) {
@@ -492,25 +487,22 @@ public class QuickContactActivity extends Activity {
Log.i(TAG, "No contact found: " + ((ContactLoader)loader).getLookupUri());
Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage,
Toast.LENGTH_LONG).show();
- hide(false);
+ close(false);
return;
}
bindData(data);
- if (TRACE_LAUNCH) {
- android.os.Debug.stopMethodTracing();
- }
+ if (TRACE_LAUNCH) android.os.Debug.stopMethodTracing();
// Data bound and ready, pull curtain to show. Put this on the Handler to ensure
// that the layout passes are completed
SchedulingUtils.doAfterLayout(mFloatingLayout, new Runnable() {
@Override
public void run() {
- mFloatingLayout.showChild(new Runnable() {
+ mFloatingLayout.showContent(new Runnable() {
@Override
public void run() {
- mHasFinishedAnimatingIn = true;
mContactLoader.upgradeToFullContact();
}
});
@@ -599,7 +591,7 @@ public class QuickContactActivity extends Activity {
Toast.LENGTH_SHORT).show();
}
- hide(false);
+ close(false);
}
};
// Defer the action to make the window properly repaint