summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java196
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/Tweener.java1
-rw-r--r--packages/SystemUI/res/drawable/navbar_search_outerring.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/SearchPanelView.java33
5 files changed, 151 insertions, 85 deletions
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 60cd895..deb09e3 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -79,18 +79,17 @@ public class MultiWaveView extends View {
private static final int SHOW_ANIMATION_DURATION = 200;
private static final int SHOW_ANIMATION_DELAY = 0;
private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
- private static final long RING_EXPAND_DURATION = 200;
private static final float TARGET_INITIAL_POSITION_SCALE = 0.8f;
private TimeInterpolator mChevronAnimationInterpolator = Ease.Quad.easeOut;
private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
private ArrayList<TargetDrawable> mChevronDrawables = new ArrayList<TargetDrawable>();
- private ArrayList<Tweener> mChevronAnimations = new ArrayList<Tweener>();
- private ArrayList<Tweener> mTargetAnimations = new ArrayList<Tweener>();
+ private AnimationBundle mChevronAnimations = new AnimationBundle();
+ private AnimationBundle mTargetAnimations = new AnimationBundle();
+ private AnimationBundle mHandleAnimations = new AnimationBundle();
private ArrayList<String> mTargetDescriptions;
private ArrayList<String> mDirectionDescriptions;
- private Tweener mHandleAnimation;
private OnTriggerListener mOnTriggerListener;
private TargetDrawable mHandleDrawable;
private TargetDrawable mOuterRing;
@@ -114,6 +113,33 @@ public class MultiWaveView extends View {
private boolean mDragging;
private int mNewTargetResources;
+ private class AnimationBundle extends ArrayList<Tweener> {
+ private static final long serialVersionUID = 0xA84D78726F127468L;
+ private boolean mSuspended;
+
+ public void start() {
+ if (mSuspended) return; // ignore attempts to start animations
+ final int count = size();
+ for (int i = 0; i < count; i++) {
+ Tweener anim = get(i);
+ anim.animator.start();
+ }
+ }
+
+ public void stop() {
+ final int count = size();
+ for (int i = 0; i < count; i++) {
+ Tweener anim = get(i);
+ anim.animator.end();
+ }
+ clear();
+ }
+
+ public void setSuspended(boolean suspend) {
+ mSuspended = suspend;
+ }
+ };
+
private AnimatorListener mResetListener = new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animator) {
switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
@@ -239,6 +265,7 @@ public class MultiWaveView extends View {
a.recycle();
setVibrateEnabled(mVibrationDuration > 0);
+ assignDefaultsIfNeeded();
}
private void dump() {
@@ -254,6 +281,21 @@ public class MultiWaveView extends View {
Log.v(TAG, "VerticalOffset = " + mVerticalOffset);
}
+ public void suspendAnimations() {
+ mChevronAnimations.setSuspended(true);
+ mTargetAnimations.setSuspended(true);
+ mHandleAnimations.setSuspended(true);
+ }
+
+ public void resumeAnimations() {
+ mChevronAnimations.setSuspended(false);
+ mTargetAnimations.setSuspended(false);
+ mHandleAnimations.setSuspended(false);
+ mChevronAnimations.start();
+ mTargetAnimations.start();
+ mHandleAnimations.start();
+ }
+
@Override
protected int getSuggestedMinimumWidth() {
// View should be large enough to contain the background + handle and
@@ -340,6 +382,8 @@ public class MultiWaveView extends View {
final int directionCount = mFeedbackCount > 0 ? mChevronDrawables.size()/mFeedbackCount : 0;
+ mChevronAnimations.stop();
+
// Add an animation for all chevron drawables. There are mFeedbackCount drawables
// in each direction and directionCount directions.
for (int direction = 0; direction < directionCount; direction++) {
@@ -367,24 +411,21 @@ public class MultiWaveView extends View {
"onUpdate", mUpdateListener));
}
}
+ mChevronAnimations.start();
}
private void stopChevronAnimation() {
- for (Tweener anim : mChevronAnimations) {
- anim.animator.end();
- }
- mChevronAnimations.clear();
+ mChevronAnimations.stop();
}
private void stopHandleAnimation() {
- if (mHandleAnimation != null) {
- mHandleAnimation.animator.end();
- mHandleAnimation = null;
- }
+ mHandleAnimations.stop();
}
private void deactivateTargets() {
- for (TargetDrawable target : mTargetDrawables) {
+ final int count = mTargetDrawables.size();
+ for (int i = 0; i < count; i++) {
+ TargetDrawable target = mTargetDrawables.get(i);
target.setState(TargetDrawable.STATE_INACTIVE);
}
mActiveTarget = -1;
@@ -445,14 +486,16 @@ public class MultiWaveView extends View {
// Animate handle back to the center based on current state.
int delay = targetHit ? RETURN_TO_HOME_DELAY : 0;
int duration = targetHit ? 0 : RETURN_TO_HOME_DURATION;
- mHandleAnimation = Tweener.to(mHandleDrawable, duration,
+ mHandleAnimations.stop();
+ mHandleAnimations.add(Tweener.to(mHandleDrawable, duration,
"ease", Ease.Quart.easeOut,
"delay", delay,
"alpha", 1.0f,
"x", 0,
"y", 0,
"onUpdate", mUpdateListener,
- "onComplete", (mDragging && !targetHit) ? mResetListenerWithPing : mResetListener);
+ "onComplete", (mDragging && !targetHit) ? mResetListenerWithPing : mResetListener));
+ mHandleAnimations.start();
setGrabbedState(OnTriggerListener.NO_HANDLE);
}
@@ -467,9 +510,7 @@ public class MultiWaveView extends View {
}
private void hideTargets(boolean animate) {
- if (mTargetAnimations.size() > 0) {
- stopTargetAnimation();
- }
+ mTargetAnimations.stop();
// Note: these animations should complete at the same time so that we can swap out
// the target assets asynchronously from the setTargetResources() call.
mAnimatingTargets = animate;
@@ -497,12 +538,12 @@ public class MultiWaveView extends View {
"delay", delay,
"onUpdate", mUpdateListener,
"onComplete", mTargetUpdateListener));
+
+ mTargetAnimations.start();
}
private void showTargets(boolean animate) {
- if (mTargetAnimations.size() > 0) {
- stopTargetAnimation();
- }
+ mTargetAnimations.stop();
mAnimatingTargets = animate;
final int delay = animate ? SHOW_ANIMATION_DELAY : 0;
final int length = mTargetDrawables.size();
@@ -521,7 +562,7 @@ public class MultiWaveView extends View {
}
mOuterRing.setScaleX(0.5f);
mOuterRing.setScaleY(0.5f);
- mTargetAnimations.add(Tweener.to(mOuterRing, animate ? RING_EXPAND_DURATION : 0,
+ mTargetAnimations.add(Tweener.to(mOuterRing, animate ? SHOW_ANIMATION_DURATION : 0,
"ease", Ease.Cubic.easeOut,
"alpha", 1.0f,
"scaleX", 1.0f,
@@ -529,13 +570,12 @@ public class MultiWaveView extends View {
"delay", delay,
"onUpdate", mUpdateListener,
"onComplete", mTargetUpdateListener));
+
+ mTargetAnimations.start();
}
private void stopTargetAnimation() {
- for (Tweener anim : mTargetAnimations) {
- anim.animator.end();
- }
- mTargetAnimations.clear();
+ mTargetAnimations.stop();
}
private void vibrate() {
@@ -658,7 +698,6 @@ public class MultiWaveView extends View {
*
*/
public void ping() {
- stopChevronAnimation();
startChevronAnimation();
}
@@ -721,7 +760,7 @@ public class MultiWaveView extends View {
}
private void handleDown(MotionEvent event) {
- if (!trySwitchToFirstTouchState(event)) {
+ if (!trySwitchToFirstTouchState(event.getX(), event.getY())) {
mDragging = false;
stopTargetAnimation();
ping();
@@ -747,14 +786,11 @@ public class MultiWaveView extends View {
}
private void handleMove(MotionEvent event) {
- if (!mDragging) {
- trySwitchToFirstTouchState(event);
- return;
- }
-
int activeTarget = -1;
final int historySize = event.getHistorySize();
- final boolean singleTarget = mTargetDrawables.size() == 1;
+ ArrayList<TargetDrawable> targets = mTargetDrawables;
+ int ntargets = targets.size();
+ final boolean singleTarget = ntargets == 1;
float x = 0.0f;
float y = 0.0f;
for (int k = 0; k < historySize + 1; k++) {
@@ -768,25 +804,29 @@ public class MultiWaveView extends View {
float limitX = tx * scale;
float limitY = ty * scale;
- if (singleTarget) {
- // Snap to outer ring if there's only one target
- float snapRadius = mOuterRadius - mSnapMargin;
- if (touchRadius > snapRadius) {
- activeTarget = 0;
- }
+ if (!mDragging) {
+ trySwitchToFirstTouchState(eventX, eventY);
} else {
- // If there's more than one target, snap to the closest one less than hitRadius away.
- float best = Float.MAX_VALUE;
- final float hitRadius2 = mHitRadius * mHitRadius;
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- // Snap to the first target in range
- TargetDrawable target = mTargetDrawables.get(i);
- float dx = limitX - target.getX();
- float dy = limitY - target.getY();
- float dist2 = dx*dx + dy*dy;
- if (target.isEnabled() && dist2 < hitRadius2 && dist2 < best) {
- activeTarget = i;
- best = dist2;
+ if (singleTarget) {
+ // Snap to outer ring if there's only one target
+ float snapRadius = mOuterRadius - mSnapMargin;
+ if (touchRadius > snapRadius) {
+ activeTarget = 0;
+ }
+ } else {
+ // For more than one target, snap to the closest one less than hitRadius away.
+ float best = Float.MAX_VALUE;
+ final float hitRadius2 = mHitRadius * mHitRadius;
+ for (int i = 0; i < ntargets; i++) {
+ // Snap to the first target in range
+ TargetDrawable target = targets.get(i);
+ float dx = limitX - target.getX();
+ float dy = limitY - target.getY();
+ float dist2 = dx*dx + dy*dy;
+ if (target.isEnabled() && dist2 < hitRadius2 && dist2 < best) {
+ activeTarget = i;
+ best = dist2;
+ }
}
}
}
@@ -794,9 +834,13 @@ public class MultiWaveView extends View {
y = limitY;
}
+ if (!mDragging) {
+ return;
+ }
+
if (activeTarget != -1) {
switchToState(STATE_SNAP, x,y);
- TargetDrawable target = mTargetDrawables.get(activeTarget);
+ TargetDrawable target = targets.get(activeTarget);
float newX = singleTarget ? x : target.getX();
float newY = singleTarget ? y : target.getY();
moveHandleTo(newX, newY, false);
@@ -812,7 +856,7 @@ public class MultiWaveView extends View {
if (mActiveTarget != activeTarget) {
// Defocus the old target
if (mActiveTarget != -1) {
- TargetDrawable target = mTargetDrawables.get(mActiveTarget);
+ TargetDrawable target = targets.get(mActiveTarget);
if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
target.setState(TargetDrawable.STATE_INACTIVE);
mHandleDrawable.setAlpha(1.0f);
@@ -820,7 +864,7 @@ public class MultiWaveView extends View {
}
// Focus the new target
if (activeTarget != -1) {
- TargetDrawable target = mTargetDrawables.get(activeTarget);
+ TargetDrawable target = targets.get(activeTarget);
if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
target.setState(TargetDrawable.STATE_FOCUSED);
mHandleDrawable.setAlpha(0.0f);
@@ -877,9 +921,7 @@ public class MultiWaveView extends View {
}
}
- private boolean trySwitchToFirstTouchState(MotionEvent event) {
- final float x = event.getX();
- final float y = event.getY();
+ private boolean trySwitchToFirstTouchState(float x, float y) {
final float tx = x - mWaveCenterX;
final float ty = y - mWaveCenterY;
if (mAlwaysTrackFinger || dist2(tx,ty) <= getScaledTapRadiusSquared()) {
@@ -892,9 +934,9 @@ public class MultiWaveView extends View {
return false;
}
- private void assignDefaultsIfNeeded(float centerX, float centerY) {
+ private void assignDefaultsIfNeeded() {
if (mOuterRadius == 0.0f) {
- mOuterRadius = 0.5f*(float) Math.hypot(centerX, centerY);
+ mOuterRadius = Math.max(mOuterRing.getWidth(), mOuterRing.getHeight())/2.0f;
}
if (mHitRadius == 0.0f) {
// Use the radius of inscribed circle of the first target.
@@ -941,6 +983,7 @@ public class MultiWaveView extends View {
super.onLayout(changed, left, top, right, bottom);
final int width = right - left;
final int height = bottom - top;
+
// Target placement width/height. This puts the targets on the greater of the ring
// width or the specified outer radius.
final float placementWidth = Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
@@ -950,8 +993,6 @@ public class MultiWaveView extends View {
float newWaveCenterY = mVerticalOffset + mVerticalInset
+ Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
- assignDefaultsIfNeeded(newWaveCenterX, newWaveCenterY);
-
if (mInitialLayout) {
hideChevrons();
hideTargets(false);
@@ -976,9 +1017,12 @@ public class MultiWaveView extends View {
private void updateTargetPositions(float centerX, float centerY) {
// Reposition the target drawables if the view changed.
- for (int i = 0; i < mTargetDrawables.size(); i++) {
- final TargetDrawable targetIcon = mTargetDrawables.get(i);
- double angle = -2.0f * Math.PI * i / mTargetDrawables.size();
+ ArrayList<TargetDrawable> targets = mTargetDrawables;
+ final int size = targets.size();
+ final float alpha = (float) (-2.0f * Math.PI / size);
+ for (int i = 0; i < size; i++) {
+ final TargetDrawable targetIcon = targets.get(i);
+ final float angle = alpha * i;
targetIcon.setPositionX(centerX);
targetIcon.setPositionY(centerY);
targetIcon.setX(mOuterRadius * (float) Math.cos(angle));
@@ -987,7 +1031,10 @@ public class MultiWaveView extends View {
}
private void updateChevronPositions(float centerX, float centerY) {
- for (TargetDrawable target : mChevronDrawables) {
+ ArrayList<TargetDrawable> chevrons = mChevronDrawables;
+ final int size = chevrons.size();
+ for (int i = 0; i < size; i++) {
+ TargetDrawable target = chevrons.get(i);
if (target != null) {
target.setPositionX(centerX);
target.setPositionY(centerY);
@@ -996,7 +1043,10 @@ public class MultiWaveView extends View {
}
private void hideChevrons() {
- for (TargetDrawable chevron : mChevronDrawables) {
+ ArrayList<TargetDrawable> chevrons = mChevronDrawables;
+ final int size = chevrons.size();
+ for (int i = 0; i < size; i++) {
+ TargetDrawable chevron = chevrons.get(i);
if (chevron != null) {
chevron.setAlpha(0.0f);
}
@@ -1006,14 +1056,18 @@ public class MultiWaveView extends View {
@Override
protected void onDraw(Canvas canvas) {
mOuterRing.draw(canvas);
- for (TargetDrawable target : mTargetDrawables) {
+ final int ntargets = mTargetDrawables.size();
+ for (int i = 0; i < ntargets; i++) {
+ TargetDrawable target = mTargetDrawables.get(i);
if (target != null) {
target.draw(canvas);
}
}
- for (TargetDrawable target : mChevronDrawables) {
- if (target != null) {
- target.draw(canvas);
+ final int nchevrons = mChevronDrawables.size();
+ for (int i = 0; i < nchevrons; i++) {
+ TargetDrawable chevron = mChevronDrawables.get(i);
+ if (chevron != null) {
+ chevron.draw(canvas);
}
}
mHandleDrawable.draw(canvas);
diff --git a/core/java/com/android/internal/widget/multiwaveview/Tweener.java b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
index bc8a62f..1d502ba 100644
--- a/core/java/com/android/internal/widget/multiwaveview/Tweener.java
+++ b/core/java/com/android/internal/widget/multiwaveview/Tweener.java
@@ -122,7 +122,6 @@ class Tweener {
anim.addListener(listener);
}
anim.addListener(mCleanupListener);
- anim.start();
return tween;
}
diff --git a/packages/SystemUI/res/drawable/navbar_search_outerring.xml b/packages/SystemUI/res/drawable/navbar_search_outerring.xml
index 37b6c1c..0dd081d 100644
--- a/packages/SystemUI/res/drawable/navbar_search_outerring.xml
+++ b/packages/SystemUI/res/drawable/navbar_search_outerring.xml
@@ -19,5 +19,5 @@
<size android:height="@dimen/navbar_search_outerring_diameter"
android:width="@dimen/navbar_search_outerring_diameter" />
<solid android:color="#00000000" />
- <stroke android:color="#1affffff" android:width="2dp" />
+ <stroke android:color="#40ffffff" android:width="2dp" />
</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f548166..c29f71b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -112,10 +112,10 @@
<dimen name="navbar_search_hit_radius">60dip</dimen>
<!-- Diameter of outer shape drawable shown in navbar search-->
- <dimen name="navbar_search_outerring_diameter">270dp</dimen>
+ <dimen name="navbar_search_outerring_diameter">340dp</dimen>
<!-- Threshold for swipe-up gesture to activate search dialog -->
- <dimen name="navbar_search_up_threshhold">20dip</dimen>
+ <dimen name="navbar_search_up_threshhold">40dip</dimen>
<!-- Height of search panel including navigation bar height -->
<dimen name="navbar_search_panel_height">230dip</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index 57f15a8..05a3bec 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -23,13 +23,14 @@ import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.speech.RecognizerIntent;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.FrameLayout;
import com.android.internal.widget.multiwaveview.MultiWaveView;
@@ -146,6 +147,14 @@ public class SearchPanelView extends FrameLayout implements
}
}
+ private OnPreDrawListener mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
+ public boolean onPreDraw() {
+ getViewTreeObserver().removeOnPreDrawListener(this);
+ mMultiWaveView.resumeAnimations();
+ return false;
+ }
+ };
+
public void show(final boolean show, boolean animate) {
if (animate) {
if (mShowing != show) {
@@ -156,16 +165,20 @@ public class SearchPanelView extends FrameLayout implements
mShowing = show;
onAnimationEnd(null);
}
- postDelayed(new Runnable() {
- public void run() {
- setVisibility(show ? View.VISIBLE : View.INVISIBLE);
- if (show) {
- setFocusable(true);
- setFocusableInTouchMode(true);
- requestFocus();
- }
+ if (show) {
+ if (getVisibility() != View.VISIBLE) {
+ setVisibility(View.VISIBLE);
+ // Don't start the animation until we've created the layer, which is done
+ // right before we are drawn
+ mMultiWaveView.suspendAnimations();
+ getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
}
- }, show ? 0 : 100);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ requestFocus();
+ } else {
+ setVisibility(View.INVISIBLE);
+ }
}
public void hide(boolean animate) {