summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJim Miller <jaggies@google.com>2012-06-11 21:06:13 -0700
committerJim Miller <jaggies@google.com>2012-06-12 19:16:08 -0700
commit955a016922ea49f154d190b054a202559b41a4d3 (patch)
tree2031ecb839a21630269b8b93cd3b8ca9048aa469
parent1c9581023ced89a209fca9c4e40305f8e0859732 (diff)
downloadframeworks_base-955a016922ea49f154d190b054a202559b41a4d3.zip
frameworks_base-955a016922ea49f154d190b054a202559b41a4d3.tar.gz
frameworks_base-955a016922ea49f154d190b054a202559b41a4d3.tar.bz2
Fix 6613962: Update keyguard to use new GlowPadView UX design.
Change-Id: I4f1ef3107e5550f7df9dcb412943a84b66432b7d
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/GlowPadView.java1226
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java36
-rw-r--r--core/java/com/android/internal/widget/multiwaveview/PointCloud.java235
-rw-r--r--core/res/res/drawable-hdpi/ic_lockscreen_glowdot.pngbin0 -> 738 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lockscreen_glowdot.pngbin0 -> 538 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lockscreen_glowdot.pngbin0 -> 964 bytes
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml16
-rw-r--r--core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml16
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock.xml16
-rw-r--r--core/res/res/layout/keyguard_screen_tab_unlock_land.xml18
-rw-r--r--core/res/res/values-land/arrays.xml2
-rw-r--r--core/res/res/values-sw600dp-land/arrays.xml2
-rw-r--r--core/res/res/values-sw600dp/dimens.xml4
-rw-r--r--core/res/res/values/arrays.xml2
-rwxr-xr-xcore/res/res/values/attrs.xml75
-rw-r--r--core/res/res/values/dimens.xml24
-rw-r--r--packages/SystemUI/res/drawable-hdpi/navbar_search_bg_scrim.9.pngbin21892 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/navbar_search_bg_scrim.9.pngbin11004 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/navbar_search_bg_scrim.9.pngbin34907 -> 0 bytes
-rw-r--r--packages/SystemUI/res/layout-land/status_bar_search_panel.xml14
-rw-r--r--packages/SystemUI/res/layout-port/status_bar_search_panel.xml14
-rw-r--r--packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml13
-rw-r--r--packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml13
-rw-r--r--packages/SystemUI/res/values-sw600dp/dimens.xml3
-rw-r--r--packages/SystemUI/res/values/dimens.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/SearchPanelView.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java1
-rw-r--r--policy/src/com/android/internal/policy/impl/LockScreen.java52
28 files changed, 1655 insertions, 157 deletions
diff --git a/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
new file mode 100644
index 0000000..5096be6
--- /dev/null
+++ b/core/java/com/android/internal/widget/multiwaveview/GlowPadView.java
@@ -0,0 +1,1226 @@
+/*
+ * Copyright (C) 2012 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 com.android.internal.widget.multiwaveview;
+
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Vibrator;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.internal.R;
+
+import java.util.ArrayList;
+
+/**
+ * A re-usable widget containing a center, outer ring and wave animation.
+ */
+public class GlowPadView extends View {
+ private static final String TAG = "GlowPadView";
+ private static final boolean DEBUG = false;
+
+ // Wave state machine
+ private static final int STATE_IDLE = 0;
+ private static final int STATE_START = 1;
+ private static final int STATE_FIRST_TOUCH = 2;
+ private static final int STATE_TRACKING = 3;
+ private static final int STATE_SNAP = 4;
+ private static final int STATE_FINISH = 5;
+
+ // Animation properties.
+ private static final float SNAP_MARGIN_DEFAULT = 20.0f; // distance to ring before we snap to it
+
+ public interface OnTriggerListener {
+ int NO_HANDLE = 0;
+ int CENTER_HANDLE = 1;
+ public void onGrabbed(View v, int handle);
+ public void onReleased(View v, int handle);
+ public void onTrigger(View v, int target);
+ public void onGrabbedStateChange(View v, int handle);
+ public void onFinishFinalAnimation();
+ }
+
+ // Tuneable parameters for animation
+ private static final int WAVE_ANIMATION_DURATION = 1200;
+ private static final int RETURN_TO_HOME_DELAY = 1200;
+ private static final int RETURN_TO_HOME_DURATION = 200;
+ private static final int HIDE_ANIMATION_DELAY = 200;
+ private static final int HIDE_ANIMATION_DURATION = 200;
+ private static final int SHOW_ANIMATION_DURATION = 200;
+ private static final int SHOW_ANIMATION_DELAY = 50;
+ private static final int INITIAL_SHOW_HANDLE_DURATION = 200;
+ private static final int REVEAL_GLOW_DELAY = 0;
+ private static final int REVEAL_GLOW_DURATION = 0;
+
+ private static final float TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.3f;
+ private static final float TARGET_SCALE_EXPANDED = 1.0f;
+ private static final float TARGET_SCALE_COLLAPSED = 0.8f;
+ private static final float RING_SCALE_EXPANDED = 1.0f;
+ private static final float RING_SCALE_COLLAPSED = 0.5f;
+
+ private ArrayList<TargetDrawable> mTargetDrawables = new ArrayList<TargetDrawable>();
+ private AnimationBundle mWaveAnimations = new AnimationBundle();
+ private AnimationBundle mTargetAnimations = new AnimationBundle();
+ private AnimationBundle mGlowAnimations = new AnimationBundle();
+ private ArrayList<String> mTargetDescriptions;
+ private ArrayList<String> mDirectionDescriptions;
+ private OnTriggerListener mOnTriggerListener;
+ private TargetDrawable mHandleDrawable;
+ private TargetDrawable mOuterRing;
+ private Vibrator mVibrator;
+
+ private int mFeedbackCount = 3;
+ private int mVibrationDuration = 0;
+ private int mGrabbedState;
+ private int mActiveTarget = -1;
+ private float mGlowRadius;
+ private float mWaveCenterX;
+ private float mWaveCenterY;
+ private int mMaxTargetHeight;
+ private int mMaxTargetWidth;
+
+ private float mOuterRadius = 0.0f;
+ private float mHitRadius = 0.0f;
+ private float mSnapMargin = 0.0f;
+ 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 cancel() {
+ final int count = size();
+ for (int i = 0; i < count; i++) {
+ Tweener anim = get(i);
+ anim.animator.cancel();
+ }
+ clear();
+ }
+
+ 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);
+ dispatchOnFinishFinalAnimation();
+ }
+ };
+
+ private AnimatorListener mResetListenerWithPing = new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animator) {
+ ping();
+ switchToState(STATE_IDLE, mWaveCenterX, mWaveCenterY);
+ dispatchOnFinishFinalAnimation();
+ }
+ };
+
+ private AnimatorUpdateListener mUpdateListener = new AnimatorUpdateListener() {
+ public void onAnimationUpdate(ValueAnimator animation) {
+ invalidate();
+ }
+ };
+
+ private boolean mAnimatingTargets;
+ private AnimatorListener mTargetUpdateListener = new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animator) {
+ if (mNewTargetResources != 0) {
+ internalSetTargetResources(mNewTargetResources);
+ mNewTargetResources = 0;
+ hideTargets(false, false);
+ }
+ mAnimatingTargets = false;
+ }
+ };
+ private int mTargetResourceId;
+ private int mTargetDescriptionsResourceId;
+ private int mDirectionDescriptionsResourceId;
+ private boolean mAlwaysTrackFinger;
+ private int mHorizontalInset;
+ private int mVerticalInset;
+ private int mGravity = Gravity.TOP;
+ private boolean mInitialLayout = true;
+ private Tweener mBackgroundAnimator;
+ private PointCloud mPointCloud;
+ private float mInnerRadius;
+
+ public GlowPadView(Context context) {
+ this(context, null);
+ }
+
+ public GlowPadView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ Resources res = context.getResources();
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GlowPadView);
+ mInnerRadius = a.getDimension(R.styleable.GlowPadView_innerRadius, mInnerRadius);
+ mOuterRadius = a.getDimension(R.styleable.GlowPadView_outerRadius, mOuterRadius);
+ mHitRadius = a.getDimension(R.styleable.GlowPadView_hitRadius, mHitRadius);
+ mSnapMargin = a.getDimension(R.styleable.GlowPadView_snapMargin, mSnapMargin);
+ mVibrationDuration = a.getInt(R.styleable.GlowPadView_vibrationDuration,
+ mVibrationDuration);
+ mFeedbackCount = a.getInt(R.styleable.GlowPadView_feedbackCount,
+ mFeedbackCount);
+ mHandleDrawable = new TargetDrawable(res,
+ a.peekValue(R.styleable.GlowPadView_handleDrawable).resourceId);
+ mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
+ mOuterRing = new TargetDrawable(res,
+ getResourceId(a, R.styleable.GlowPadView_outerRingDrawable));
+
+ mAlwaysTrackFinger = a.getBoolean(R.styleable.GlowPadView_alwaysTrackFinger, false);
+
+ int pointId = getResourceId(a, R.styleable.GlowPadView_pointDrawable);
+ Drawable pointDrawable = pointId != 0 ? res.getDrawable(pointId) : null;
+ mGlowRadius = a.getDimension(R.styleable.GlowPadView_glowRadius, 0.0f);
+
+ TypedValue outValue = new TypedValue();
+
+ // Read array of target drawables
+ if (a.getValue(R.styleable.GlowPadView_targetDrawables, outValue)) {
+ internalSetTargetResources(outValue.resourceId);
+ }
+ if (mTargetDrawables == null || mTargetDrawables.size() == 0) {
+ throw new IllegalStateException("Must specify at least one target drawable");
+ }
+
+ // Read array of target descriptions
+ if (a.getValue(R.styleable.GlowPadView_targetDescriptions, outValue)) {
+ final int resourceId = outValue.resourceId;
+ if (resourceId == 0) {
+ throw new IllegalStateException("Must specify target descriptions");
+ }
+ setTargetDescriptionsResourceId(resourceId);
+ }
+
+ // Read array of direction descriptions
+ if (a.getValue(R.styleable.GlowPadView_directionDescriptions, outValue)) {
+ final int resourceId = outValue.resourceId;
+ if (resourceId == 0) {
+ throw new IllegalStateException("Must specify direction descriptions");
+ }
+ setDirectionDescriptionsResourceId(resourceId);
+ }
+
+ a.recycle();
+
+ // Use gravity attribute from LinearLayout
+ a = context.obtainStyledAttributes(attrs, android.R.styleable.LinearLayout);
+ mGravity = a.getInt(android.R.styleable.LinearLayout_gravity, Gravity.TOP);
+ a.recycle();
+
+ setVibrateEnabled(mVibrationDuration > 0);
+
+ assignDefaultsIfNeeded();
+
+ mPointCloud = new PointCloud(pointDrawable);
+ mPointCloud.makePointCloud(mInnerRadius, mOuterRadius);
+ mPointCloud.glowManager.setRadius(mGlowRadius);
+ }
+
+ private int getResourceId(TypedArray a, int id) {
+ TypedValue tv = a.peekValue(id);
+ return tv == null ? 0 : tv.resourceId;
+ }
+
+ private void dump() {
+ Log.v(TAG, "Outer Radius = " + mOuterRadius);
+ Log.v(TAG, "HitRadius = " + mHitRadius);
+ Log.v(TAG, "SnapMargin = " + mSnapMargin);
+ Log.v(TAG, "FeedbackCount = " + mFeedbackCount);
+ Log.v(TAG, "VibrationDuration = " + mVibrationDuration);
+ Log.v(TAG, "GlowRadius = " + mGlowRadius);
+ Log.v(TAG, "WaveCenterX = " + mWaveCenterX);
+ Log.v(TAG, "WaveCenterY = " + mWaveCenterY);
+ }
+
+ public void suspendAnimations() {
+ mWaveAnimations.setSuspended(true);
+ mTargetAnimations.setSuspended(true);
+ mGlowAnimations.setSuspended(true);
+ }
+
+ public void resumeAnimations() {
+ mWaveAnimations.setSuspended(false);
+ mTargetAnimations.setSuspended(false);
+ mGlowAnimations.setSuspended(false);
+ mWaveAnimations.start();
+ mTargetAnimations.start();
+ mGlowAnimations.start();
+ }
+
+ @Override
+ protected int getSuggestedMinimumWidth() {
+ // View should be large enough to contain the background + handle and
+ // target drawable on either edge.
+ return (int) (Math.max(mOuterRing.getWidth(), 2 * mOuterRadius) + mMaxTargetWidth);
+ }
+
+ @Override
+ protected int getSuggestedMinimumHeight() {
+ // View should be large enough to contain the unlock ring + target and
+ // target drawable on either edge
+ return (int) (Math.max(mOuterRing.getHeight(), 2 * mOuterRadius) + mMaxTargetHeight);
+ }
+
+ private int resolveMeasured(int measureSpec, int desired)
+ {
+ int result = 0;
+ int specSize = MeasureSpec.getSize(measureSpec);
+ switch (MeasureSpec.getMode(measureSpec)) {
+ case MeasureSpec.UNSPECIFIED:
+ result = desired;
+ break;
+ case MeasureSpec.AT_MOST:
+ result = Math.min(specSize, desired);
+ break;
+ case MeasureSpec.EXACTLY:
+ default:
+ result = specSize;
+ }
+ return result;
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int minimumWidth = getSuggestedMinimumWidth();
+ final int minimumHeight = getSuggestedMinimumHeight();
+ int computedWidth = resolveMeasured(widthMeasureSpec, minimumWidth);
+ int computedHeight = resolveMeasured(heightMeasureSpec, minimumHeight);
+ computeInsets((computedWidth - minimumWidth), (computedHeight - minimumHeight));
+ setMeasuredDimension(computedWidth, computedHeight);
+ }
+
+ private void switchToState(int state, float x, float y) {
+ switch (state) {
+ case STATE_IDLE:
+ deactivateTargets();
+ hideGlow(0, 0, 0.0f, null);
+ startBackgroundAnimation(0, 0.0f);
+ mHandleDrawable.setState(TargetDrawable.STATE_INACTIVE);
+ mHandleDrawable.setAlpha(1.0f);
+ break;
+
+ case STATE_START:
+ startBackgroundAnimation(0, 0.0f);
+ break;
+
+ case STATE_FIRST_TOUCH:
+ mHandleDrawable.setAlpha(0.0f);
+ deactivateTargets();
+ showTargets(true);
+ startBackgroundAnimation(INITIAL_SHOW_HANDLE_DURATION, 1.0f);
+ setGrabbedState(OnTriggerListener.CENTER_HANDLE);
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ announceTargets();
+ }
+ break;
+
+ case STATE_TRACKING:
+ mHandleDrawable.setAlpha(0.0f);
+ showGlow(REVEAL_GLOW_DURATION , REVEAL_GLOW_DELAY, 1.0f, null);
+ break;
+
+ case STATE_SNAP:
+ // TODO: Add transition states (see list_selector_background_transition.xml)
+ mHandleDrawable.setAlpha(0.0f);
+ showGlow(REVEAL_GLOW_DURATION , REVEAL_GLOW_DELAY, 0.0f, null);
+ break;
+
+ case STATE_FINISH:
+ doFinish();
+ break;
+ }
+ }
+
+ private void showGlow(int duration, int delay, float finalAlpha,
+ AnimatorListener finishListener) {
+ mGlowAnimations.cancel();
+ mGlowAnimations.add(Tweener.to(mPointCloud.glowManager, duration,
+ "ease", Ease.Cubic.easeIn,
+ "delay", delay,
+ "alpha", finalAlpha,
+ "onUpdate", mUpdateListener,
+ "onComplete", finishListener));
+ mGlowAnimations.start();
+ }
+
+ private void hideGlow(int duration, int delay, float finalAlpha,
+ AnimatorListener finishListener) {
+ mGlowAnimations.cancel();
+ mGlowAnimations.add(Tweener.to(mPointCloud.glowManager, duration,
+ "ease", Ease.Quart.easeOut,
+ "delay", delay,
+ "alpha", finalAlpha,
+ "x", 0.0f,
+ "y", 0.0f,
+ "onUpdate", mUpdateListener,
+ "onComplete", finishListener));
+ mGlowAnimations.start();
+ }
+
+ private void deactivateTargets() {
+ final int count = mTargetDrawables.size();
+ for (int i = 0; i < count; i++) {
+ TargetDrawable target = mTargetDrawables.get(i);
+ target.setState(TargetDrawable.STATE_INACTIVE);
+ }
+ mActiveTarget = -1;
+ }
+
+ /**
+ * Dispatches a trigger event to listener. Ignored if a listener is not set.
+ * @param whichTarget the target that was triggered.
+ */
+ private void dispatchTriggerEvent(int whichTarget) {
+ vibrate();
+ if (mOnTriggerListener != null) {
+ mOnTriggerListener.onTrigger(this, whichTarget);
+ }
+ }
+
+ private void dispatchOnFinishFinalAnimation() {
+ if (mOnTriggerListener != null) {
+ mOnTriggerListener.onFinishFinalAnimation();
+ }
+ }
+
+ private void doFinish() {
+ final int activeTarget = mActiveTarget;
+ final boolean targetHit = activeTarget != -1;
+
+ if (targetHit) {
+ if (DEBUG) Log.v(TAG, "Finish with target hit = " + targetHit);
+
+ highlightSelected(activeTarget);
+
+ // Inform listener of any active targets. Typically only one will be active.
+ hideGlow(RETURN_TO_HOME_DURATION, RETURN_TO_HOME_DELAY, 0.0f, mResetListener);
+ dispatchTriggerEvent(activeTarget);
+ if (!mAlwaysTrackFinger) {
+ // Force ring and targets to finish animation to final expanded state
+ mTargetAnimations.stop();
+ }
+ } else {
+ // Animate handle back to the center based on current state.
+ hideGlow(HIDE_ANIMATION_DURATION, 0, 0.0f, mResetListenerWithPing);
+ hideTargets(true, false);
+ }
+
+ setGrabbedState(OnTriggerListener.NO_HANDLE);
+ }
+
+ private void highlightSelected(int activeTarget) {
+ // Highlight the given target and fade others
+ mTargetDrawables.get(activeTarget).setState(TargetDrawable.STATE_ACTIVE);
+ hideUnselected(activeTarget);
+ }
+
+ private void hideUnselected(int active) {
+ for (int i = 0; i < mTargetDrawables.size(); i++) {
+ if (i != active) {
+ mTargetDrawables.get(i).setAlpha(0.0f);
+ }
+ }
+ }
+
+ private void hideTargets(boolean animate, boolean expanded) {
+ mTargetAnimations.cancel();
+ // 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;
+ final int duration = animate ? HIDE_ANIMATION_DURATION : 0;
+ final int delay = animate ? HIDE_ANIMATION_DELAY : 0;
+
+ final float targetScale = expanded ? TARGET_SCALE_EXPANDED : TARGET_SCALE_COLLAPSED;
+ final int length = mTargetDrawables.size();
+ final TimeInterpolator interpolator = Ease.Cubic.easeOut;
+ for (int i = 0; i < length; i++) {
+ TargetDrawable target = mTargetDrawables.get(i);
+ target.setState(TargetDrawable.STATE_INACTIVE);
+ mTargetAnimations.add(Tweener.to(target, duration,
+ "ease", interpolator,
+ "alpha", 0.0f,
+ "scaleX", targetScale,
+ "scaleY", targetScale,
+ "delay", delay,
+ "onUpdate", mUpdateListener));
+ }
+
+ final float ringScaleTarget = expanded ? RING_SCALE_EXPANDED : RING_SCALE_COLLAPSED;
+ mTargetAnimations.add(Tweener.to(mOuterRing, duration,
+ "ease", interpolator,
+ "alpha", 0.0f,
+ "scaleX", ringScaleTarget,
+ "scaleY", ringScaleTarget,
+ "delay", delay,
+ "onUpdate", mUpdateListener,
+ "onComplete", mTargetUpdateListener));
+
+ mTargetAnimations.start();
+ }
+
+ private void showTargets(boolean animate) {
+ mTargetAnimations.stop();
+ mAnimatingTargets = animate;
+ final int delay = animate ? SHOW_ANIMATION_DELAY : 0;
+ final int duration = animate ? SHOW_ANIMATION_DURATION : 0;
+ final int length = mTargetDrawables.size();
+ for (int i = 0; i < length; i++) {
+ TargetDrawable target = mTargetDrawables.get(i);
+ target.setState(TargetDrawable.STATE_INACTIVE);
+ mTargetAnimations.add(Tweener.to(target, duration,
+ "ease", Ease.Cubic.easeOut,
+ "alpha", 1.0f,
+ "scaleX", 1.0f,
+ "scaleY", 1.0f,
+ "delay", delay,
+ "onUpdate", mUpdateListener));
+ }
+ mTargetAnimations.add(Tweener.to(mOuterRing, duration,
+ "ease", Ease.Cubic.easeOut,
+ "alpha", 1.0f,
+ "scaleX", 1.0f,
+ "scaleY", 1.0f,
+ "delay", delay,
+ "onUpdate", mUpdateListener,
+ "onComplete", mTargetUpdateListener));
+
+ mTargetAnimations.start();
+ }
+
+ private void vibrate() {
+ if (mVibrator != null) {
+ mVibrator.vibrate(mVibrationDuration);
+ }
+ }
+
+ private ArrayList<TargetDrawable> loadDrawableArray(int resourceId) {
+ Resources res = getContext().getResources();
+ TypedArray array = res.obtainTypedArray(resourceId);
+ final int count = array.length();
+ ArrayList<TargetDrawable> drawables = new ArrayList<TargetDrawable>(count);
+ for (int i = 0; i < count; i++) {
+ TypedValue value = array.peekValue(i);
+ TargetDrawable target = new TargetDrawable(res, value != null ? value.resourceId : 0);
+ drawables.add(target);
+ }
+ array.recycle();
+ return drawables;
+ }
+
+ private void internalSetTargetResources(int resourceId) {
+ final ArrayList<TargetDrawable> targets = loadDrawableArray(resourceId);
+ mTargetDrawables = targets;
+ mTargetResourceId = resourceId;
+
+ int maxWidth = mHandleDrawable.getWidth();
+ int maxHeight = mHandleDrawable.getHeight();
+ final int count = targets.size();
+ for (int i = 0; i < count; i++) {
+ TargetDrawable target = targets.get(i);
+ maxWidth = Math.max(maxWidth, target.getWidth());
+ maxHeight = Math.max(maxHeight, target.getHeight());
+ }
+ if (mMaxTargetWidth != maxWidth || mMaxTargetHeight != maxHeight) {
+ mMaxTargetWidth = maxWidth;
+ mMaxTargetHeight = maxHeight;
+ requestLayout(); // required to resize layout and call updateTargetPositions()
+ } else {
+ updateTargetPositions(mWaveCenterX, mWaveCenterY);
+ updatePointCloudPosition(mWaveCenterX, mWaveCenterY);
+ }
+ }
+
+ /**
+ * Loads an array of drawables from the given resourceId.
+ *
+ * @param resourceId
+ */
+ public void setTargetResources(int resourceId) {
+ if (mAnimatingTargets) {
+ // postpone this change until we return to the initial state
+ mNewTargetResources = resourceId;
+ } else {
+ internalSetTargetResources(resourceId);
+ }
+ }
+
+ public int getTargetResourceId() {
+ return mTargetResourceId;
+ }
+
+ /**
+ * Sets the resource id specifying the target descriptions for accessibility.
+ *
+ * @param resourceId The resource id.
+ */
+ public void setTargetDescriptionsResourceId(int resourceId) {
+ mTargetDescriptionsResourceId = resourceId;
+ if (mTargetDescriptions != null) {
+ mTargetDescriptions.clear();
+ }
+ }
+
+ /**
+ * Gets the resource id specifying the target descriptions for accessibility.
+ *
+ * @return The resource id.
+ */
+ public int getTargetDescriptionsResourceId() {
+ return mTargetDescriptionsResourceId;
+ }
+
+ /**
+ * Sets the resource id specifying the target direction descriptions for accessibility.
+ *
+ * @param resourceId The resource id.
+ */
+ public void setDirectionDescriptionsResourceId(int resourceId) {
+ mDirectionDescriptionsResourceId = resourceId;
+ if (mDirectionDescriptions != null) {
+ mDirectionDescriptions.clear();
+ }
+ }
+
+ /**
+ * Gets the resource id specifying the target direction descriptions.
+ *
+ * @return The resource id.
+ */
+ public int getDirectionDescriptionsResourceId() {
+ return mDirectionDescriptionsResourceId;
+ }
+
+ /**
+ * Enable or disable vibrate on touch.
+ *
+ * @param enabled
+ */
+ public void setVibrateEnabled(boolean enabled) {
+ if (enabled && mVibrator == null) {
+ mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ } else {
+ mVibrator = null;
+ }
+ }
+
+ /**
+ * Starts wave animation.
+ *
+ */
+ public void ping() {
+ if (mFeedbackCount > 0) {
+ startWaveAnimation();
+ }
+ }
+
+ private void stopAndHideWaveAnimation() {
+ mWaveAnimations.cancel();
+ mPointCloud.waveManager.setAlpha(0.0f);
+ }
+
+ private void startWaveAnimation() {
+ mWaveAnimations.cancel();
+ mPointCloud.waveManager.setAlpha(1.0f);
+ mPointCloud.waveManager.setRadius(mHandleDrawable.getWidth()/2.0f);
+ mWaveAnimations.add(Tweener.to(mPointCloud.waveManager, WAVE_ANIMATION_DURATION,
+ "ease", Ease.Linear.easeNone,
+ "delay", 0,
+ "radius", 2.0f * mOuterRadius,
+ "onUpdate", mUpdateListener,
+ "onComplete",
+ new AnimatorListenerAdapter() {
+ public void onAnimationEnd(Animator animator) {
+ mPointCloud.waveManager.setRadius(0.0f);
+ mPointCloud.waveManager.setAlpha(0.0f);
+ }
+ }));
+ mWaveAnimations.start();
+ }
+
+ /**
+ * Resets the widget to default state and cancels all animation. If animate is 'true', will
+ * animate objects into place. Otherwise, objects will snap back to place.
+ *
+ * @param animate
+ */
+ public void reset(boolean animate) {
+ mGlowAnimations.stop();
+ mTargetAnimations.stop();
+ startBackgroundAnimation(0, 0.0f);
+ stopAndHideWaveAnimation();
+ hideTargets(animate, false);
+ hideGlow(0, 0, 1.0f, null);
+ Tweener.reset();
+ }
+
+ private void startBackgroundAnimation(int duration, float alpha) {
+ final Drawable background = getBackground();
+ if (mAlwaysTrackFinger && background != null) {
+ if (mBackgroundAnimator != null) {
+ mBackgroundAnimator.animator.cancel();
+ }
+ mBackgroundAnimator = Tweener.to(background, duration,
+ "ease", Ease.Cubic.easeIn,
+ "alpha", (int)(255.0f * alpha),
+ "delay", SHOW_ANIMATION_DELAY);
+ mBackgroundAnimator.animator.start();
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ final int action = event.getAction();
+ boolean handled = false;
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ if (DEBUG) Log.v(TAG, "*** DOWN ***");
+ handleDown(event);
+ handleMove(event);
+ handled = true;
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ if (DEBUG) Log.v(TAG, "*** MOVE ***");
+ handleMove(event);
+ handled = true;
+ break;
+
+ case MotionEvent.ACTION_UP:
+ if (DEBUG) Log.v(TAG, "*** UP ***");
+ handleMove(event);
+ handleUp(event);
+ handled = true;
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ if (DEBUG) Log.v(TAG, "*** CANCEL ***");
+ handleMove(event);
+ handleCancel(event);
+ handled = true;
+ break;
+ }
+ invalidate();
+ return handled ? true : super.onTouchEvent(event);
+ }
+
+ private void updateGlowPosition(float x, float y) {
+ mPointCloud.glowManager.setX(x);
+ mPointCloud.glowManager.setY(y);
+ }
+
+ private void handleDown(MotionEvent event) {
+ float eventX = event.getX();
+ float eventY = event.getY();
+ switchToState(STATE_START, eventX, eventY);
+ if (!trySwitchToFirstTouchState(eventX, eventY)) {
+ mDragging = false;
+ } else {
+ updateGlowPosition(eventX, eventY);
+ }
+ }
+
+ private void handleUp(MotionEvent event) {
+ if (DEBUG && mDragging) Log.v(TAG, "** Handle RELEASE");
+ switchToState(STATE_FINISH, event.getX(), event.getY());
+ }
+
+ private void handleCancel(MotionEvent event) {
+ if (DEBUG && mDragging) Log.v(TAG, "** Handle CANCEL");
+
+ // We should drop the active target here but it interferes with
+ // moving off the screen in the direction of the navigation bar. At some point we may
+ // want to revisit how we handle this. For now we'll allow a canceled event to
+ // activate the current target.
+
+ // mActiveTarget = -1; // Drop the active target if canceled.
+
+ switchToState(STATE_FINISH, event.getX(), event.getY());
+ }
+
+ private void handleMove(MotionEvent event) {
+ int activeTarget = -1;
+ final int historySize = event.getHistorySize();
+ 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++) {
+ float eventX = k < historySize ? event.getHistoricalX(k) : event.getX();
+ float eventY = k < historySize ? event.getHistoricalY(k) : event.getY();
+ // tx and ty are relative to wave center
+ float tx = eventX - mWaveCenterX;
+ float ty = eventY - mWaveCenterY;
+ float touchRadius = (float) Math.sqrt(dist2(tx, ty));
+ final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
+ float limitX = tx * scale;
+ float limitY = ty * scale;
+
+ if (!mDragging) {
+ trySwitchToFirstTouchState(eventX, eventY);
+ }
+
+ if (mDragging) {
+ 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;
+ // Find first target in range
+ for (int i = 0; i < ntargets; i++) {
+ 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;
+ }
+ }
+ }
+ }
+ x = limitX;
+ y = limitY;
+ }
+
+ if (!mDragging) {
+ return;
+ }
+
+ if (activeTarget != -1) {
+ switchToState(STATE_SNAP, x,y);
+ TargetDrawable target = targets.get(activeTarget);
+ final float newX = singleTarget ? x : target.getX();
+ final float newY = singleTarget ? y : target.getY();
+ updateGlowPosition(newX, newY);
+ } else {
+ switchToState(STATE_TRACKING, x, y);
+ updateGlowPosition(x, y);
+ }
+
+ if (mActiveTarget != activeTarget) {
+ // Defocus the old target
+ if (mActiveTarget != -1) {
+ TargetDrawable target = targets.get(mActiveTarget);
+ if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
+ target.setState(TargetDrawable.STATE_INACTIVE);
+ }
+ }
+ // Focus the new target
+ if (activeTarget != -1) {
+ TargetDrawable target = targets.get(activeTarget);
+ if (target.hasState(TargetDrawable.STATE_FOCUSED)) {
+ target.setState(TargetDrawable.STATE_FOCUSED);
+ }
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ String targetContentDescription = getTargetDescription(activeTarget);
+ announceText(targetContentDescription);
+ }
+ }
+ }
+ mActiveTarget = activeTarget;
+ }
+
+ @Override
+ public boolean onHoverEvent(MotionEvent event) {
+ if (AccessibilityManager.getInstance(mContext).isTouchExplorationEnabled()) {
+ final int action = event.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ event.setAction(MotionEvent.ACTION_DOWN);
+ break;
+ case MotionEvent.ACTION_HOVER_MOVE:
+ event.setAction(MotionEvent.ACTION_MOVE);
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ event.setAction(MotionEvent.ACTION_UP);
+ break;
+ }
+ onTouchEvent(event);
+ event.setAction(action);
+ }
+ return super.onHoverEvent(event);
+ }
+
+ /**
+ * Sets the current grabbed state, and dispatches a grabbed state change
+ * event to our listener.
+ */
+ private void setGrabbedState(int newState) {
+ if (newState != mGrabbedState) {
+ if (newState != OnTriggerListener.NO_HANDLE) {
+ vibrate();
+ }
+ mGrabbedState = newState;
+ if (mOnTriggerListener != null) {
+ if (newState == OnTriggerListener.NO_HANDLE) {
+ mOnTriggerListener.onReleased(this, OnTriggerListener.CENTER_HANDLE);
+ } else {
+ mOnTriggerListener.onGrabbed(this, OnTriggerListener.CENTER_HANDLE);
+ }
+ mOnTriggerListener.onGrabbedStateChange(this, newState);
+ }
+ }
+ }
+
+ private boolean trySwitchToFirstTouchState(float x, float y) {
+ final float tx = x - mWaveCenterX;
+ final float ty = y - mWaveCenterY;
+ if (mAlwaysTrackFinger || dist2(tx,ty) <= getScaledGlowRadiusSquared()) {
+ if (DEBUG) Log.v(TAG, "** Handle HIT");
+ switchToState(STATE_FIRST_TOUCH, x, y);
+ updateGlowPosition(tx, ty);
+ mDragging = true;
+ return true;
+ }
+ return false;
+ }
+
+ private void assignDefaultsIfNeeded() {
+ if (mOuterRadius == 0.0f) {
+ mOuterRadius = Math.max(mOuterRing.getWidth(), mOuterRing.getHeight())/2.0f;
+ }
+ if (mHitRadius == 0.0f) {
+ // Use the radius of inscribed circle of the first target.
+ mHitRadius = mTargetDrawables.get(0).getWidth() / 2.0f;
+ }
+ if (mSnapMargin == 0.0f) {
+ mSnapMargin = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
+ SNAP_MARGIN_DEFAULT, getContext().getResources().getDisplayMetrics());
+ }
+ if (mInnerRadius == 0.0f) {
+ mInnerRadius = mHandleDrawable.getWidth() / 10.0f;
+ }
+ }
+
+ private void computeInsets(int dx, int dy) {
+ final int layoutDirection = getResolvedLayoutDirection();
+ final int absoluteGravity = Gravity.getAbsoluteGravity(mGravity, layoutDirection);
+
+ switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+ case Gravity.LEFT:
+ mHorizontalInset = 0;
+ break;
+ case Gravity.RIGHT:
+ mHorizontalInset = dx;
+ break;
+ case Gravity.CENTER_HORIZONTAL:
+ default:
+ mHorizontalInset = dx / 2;
+ break;
+ }
+ switch (absoluteGravity & Gravity.VERTICAL_GRAVITY_MASK) {
+ case Gravity.TOP:
+ mVerticalInset = 0;
+ break;
+ case Gravity.BOTTOM:
+ mVerticalInset = dy;
+ break;
+ case Gravity.CENTER_VERTICAL:
+ default:
+ mVerticalInset = dy / 2;
+ break;
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ 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);
+ final float placementHeight = Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
+ float newWaveCenterX = mHorizontalInset
+ + Math.max(width, mMaxTargetWidth + placementWidth) / 2;
+ float newWaveCenterY = mVerticalInset
+ + Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
+
+ if (mInitialLayout) {
+ stopAndHideWaveAnimation();
+ hideTargets(false, false);
+ mInitialLayout = false;
+ }
+
+ mOuterRing.setPositionX(newWaveCenterX);
+ mOuterRing.setPositionY(newWaveCenterY);
+
+ mHandleDrawable.setPositionX(newWaveCenterX);
+ mHandleDrawable.setPositionY(newWaveCenterY);
+
+ updateTargetPositions(newWaveCenterX, newWaveCenterY);
+ updatePointCloudPosition(newWaveCenterX, newWaveCenterY);
+ updateGlowPosition(newWaveCenterX, newWaveCenterY);
+
+ mWaveCenterX = newWaveCenterX;
+ mWaveCenterY = newWaveCenterY;
+
+ if (DEBUG) dump();
+ }
+
+ private void updateTargetPositions(float centerX, float centerY) {
+ // Reposition the target drawables if the view changed.
+ 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));
+ targetIcon.setY(mOuterRadius * (float) Math.sin(angle));
+ }
+ }
+
+ private void updatePointCloudPosition(float centerX, float centerY) {
+ mPointCloud.setCenter(centerX, centerY);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ mPointCloud.draw(canvas);
+ mOuterRing.draw(canvas);
+ final int ntargets = mTargetDrawables.size();
+ for (int i = 0; i < ntargets; i++) {
+ TargetDrawable target = mTargetDrawables.get(i);
+ if (target != null) {
+ target.draw(canvas);
+ }
+ }
+ mHandleDrawable.draw(canvas);
+ }
+
+ public void setOnTriggerListener(OnTriggerListener listener) {
+ mOnTriggerListener = listener;
+ }
+
+ private float square(float d) {
+ return d * d;
+ }
+
+ private float dist2(float dx, float dy) {
+ return dx*dx + dy*dy;
+ }
+
+ private float getScaledGlowRadiusSquared() {
+ final float scaledTapRadius;
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ scaledTapRadius = TAP_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mGlowRadius;
+ } else {
+ scaledTapRadius = mGlowRadius;
+ }
+ return square(scaledTapRadius);
+ }
+
+ private void announceTargets() {
+ StringBuilder utterance = new StringBuilder();
+ final int targetCount = mTargetDrawables.size();
+ for (int i = 0; i < targetCount; i++) {
+ String targetDescription = getTargetDescription(i);
+ String directionDescription = getDirectionDescription(i);
+ if (!TextUtils.isEmpty(targetDescription)
+ && !TextUtils.isEmpty(directionDescription)) {
+ String text = String.format(directionDescription, targetDescription);
+ utterance.append(text);
+ }
+ if (utterance.length() > 0) {
+ announceText(utterance.toString());
+ }
+ }
+ }
+
+ private void announceText(String text) {
+ setContentDescription(text);
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+ setContentDescription(null);
+ }
+
+ private String getTargetDescription(int index) {
+ if (mTargetDescriptions == null || mTargetDescriptions.isEmpty()) {
+ mTargetDescriptions = loadDescriptions(mTargetDescriptionsResourceId);
+ if (mTargetDrawables.size() != mTargetDescriptions.size()) {
+ Log.w(TAG, "The number of target drawables must be"
+ + " equal to the number of target descriptions.");
+ return null;
+ }
+ }
+ return mTargetDescriptions.get(index);
+ }
+
+ private String getDirectionDescription(int index) {
+ if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) {
+ mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId);
+ if (mTargetDrawables.size() != mDirectionDescriptions.size()) {
+ Log.w(TAG, "The number of target drawables must be"
+ + " equal to the number of direction descriptions.");
+ return null;
+ }
+ }
+ return mDirectionDescriptions.get(index);
+ }
+
+ private ArrayList<String> loadDescriptions(int resourceId) {
+ TypedArray array = getContext().getResources().obtainTypedArray(resourceId);
+ final int count = array.length();
+ ArrayList<String> targetContentDescriptions = new ArrayList<String>(count);
+ for (int i = 0; i < count; i++) {
+ String contentDescription = array.getString(i);
+ targetContentDescriptions.add(contentDescription);
+ }
+ array.recycle();
+ return targetContentDescriptions;
+ }
+
+ public int getResourceIdForTarget(int index) {
+ final TargetDrawable drawable = mTargetDrawables.get(index);
+ return drawable == null ? 0 : drawable.getResourceId();
+ }
+
+ public void setEnableTarget(int resourceId, boolean enabled) {
+ for (int i = 0; i < mTargetDrawables.size(); i++) {
+ final TargetDrawable target = mTargetDrawables.get(i);
+ if (target.getResourceId() == resourceId) {
+ target.setEnabled(enabled);
+ break; // should never be more than one match
+ }
+ }
+ }
+
+ /**
+ * Gets the position of a target in the array that matches the given resource.
+ * @param resourceId
+ * @return the index or -1 if not found
+ */
+ public int getTargetPosition(int resourceId) {
+ for (int i = 0; i < mTargetDrawables.size(); i++) {
+ final TargetDrawable target = mTargetDrawables.get(i);
+ if (target.getResourceId() == resourceId) {
+ return i; // should never be more than one match
+ }
+ }
+ return -1;
+ }
+
+ private boolean replaceTargetDrawables(Resources res, int existingResourceId,
+ int newResourceId) {
+ if (existingResourceId == 0 || newResourceId == 0) {
+ return false;
+ }
+
+ boolean result = false;
+ final ArrayList<TargetDrawable> drawables = mTargetDrawables;
+ final int size = drawables.size();
+ for (int i = 0; i < size; i++) {
+ final TargetDrawable target = drawables.get(i);
+ if (target != null && target.getResourceId() == existingResourceId) {
+ target.setDrawable(res, newResourceId);
+ result = true;
+ }
+ }
+
+ if (result) {
+ requestLayout(); // in case any given drawable's size changes
+ }
+
+ return result;
+ }
+
+ /**
+ * Searches the given package for a resource to use to replace the Drawable on the
+ * target with the given resource id
+ * @param component of the .apk that contains the resource
+ * @param name of the metadata in the .apk
+ * @param existingResId the resource id of the target to search for
+ * @return true if found in the given package and replaced at least one target Drawables
+ */
+ public boolean replaceTargetDrawablesIfPresent(ComponentName component, String name,
+ int existingResId) {
+ if (existingResId == 0) return false;
+
+ try {
+ PackageManager packageManager = mContext.getPackageManager();
+ // Look for the search icon specified in the activity meta-data
+ Bundle metaData = packageManager.getActivityInfo(
+ component, PackageManager.GET_META_DATA).metaData;
+ if (metaData != null) {
+ int iconResId = metaData.getInt(name);
+ if (iconResId != 0) {
+ Resources res = packageManager.getResourcesForActivity(component);
+ return replaceTargetDrawables(res, existingResId, iconResId);
+ }
+ }
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Failed to swap drawable; "
+ + component.flattenToShortString() + " not found", e);
+ } catch (Resources.NotFoundException nfe) {
+ Log.w(TAG, "Failed to swap drawable from "
+ + component.flattenToShortString(), nfe);
+ }
+ return false;
+ }
+}
diff --git a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
index 89dbd1b..afeac00 100644
--- a/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
+++ b/core/java/com/android/internal/widget/multiwaveview/MultiWaveView.java
@@ -117,8 +117,6 @@ public class MultiWaveView extends View {
private float mWaveCenterY;
private int mMaxTargetHeight;
private int mMaxTargetWidth;
- private float mHorizontalOffset;
- private float mVerticalOffset;
private float mOuterRadius = 0.0f;
private float mHitRadius = 0.0f;
@@ -215,9 +213,6 @@ public class MultiWaveView extends View {
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiWaveView);
mOuterRadius = a.getDimension(R.styleable.MultiWaveView_outerRadius, mOuterRadius);
-// mHorizontalOffset = a.getDimension(R.styleable.MultiWaveView_horizontalOffset,
-// mHorizontalOffset);
-// mVerticalOffset = a.getDimension(R.styleable.MultiWaveView_verticalOffset, mVerticalOffset);
mHitRadius = a.getDimension(R.styleable.MultiWaveView_hitRadius, mHitRadius);
mSnapMargin = a.getDimension(R.styleable.MultiWaveView_snapMargin, mSnapMargin);
mVibrationDuration = a.getInt(R.styleable.MultiWaveView_vibrationDuration,
@@ -230,7 +225,6 @@ public class MultiWaveView extends View {
mOuterRing = new TargetDrawable(res,
a.peekValue(R.styleable.MultiWaveView_waveDrawable).resourceId);
mAlwaysTrackFinger = a.getBoolean(R.styleable.MultiWaveView_alwaysTrackFinger, false);
- mGravity = a.getInt(R.styleable.MultiWaveView_gravity, Gravity.TOP);
// Read array of chevron drawables
TypedValue outValue = new TypedValue();
@@ -244,24 +238,6 @@ public class MultiWaveView extends View {
}
}
- // Support old-style chevron specification if new specification not found
- if (mChevronDrawables.size() == 0) {
- final int chevronResIds[] = {
- R.styleable.MultiWaveView_rightChevronDrawable,
- R.styleable.MultiWaveView_topChevronDrawable,
- R.styleable.MultiWaveView_leftChevronDrawable,
- R.styleable.MultiWaveView_bottomChevronDrawable
- };
-
- for (int i = 0; i < chevronResIds.length; i++) {
- TypedValue typedValue = a.peekValue(chevronResIds[i]);
- for (int k = 0; k < mFeedbackCount; k++) {
- mChevronDrawables.add(
- typedValue != null ? new TargetDrawable(res, typedValue.resourceId) : null);
- }
- }
- }
-
// Read array of target drawables
if (a.getValue(R.styleable.MultiWaveView_targetDrawables, outValue)) {
internalSetTargetResources(outValue.resourceId);
@@ -289,6 +265,12 @@ public class MultiWaveView extends View {
}
a.recycle();
+
+ // Use gravity attribute from LinearLayout
+ a = context.obtainStyledAttributes(attrs, android.R.styleable.LinearLayout);
+ mGravity = a.getInt(android.R.styleable.LinearLayout_gravity, Gravity.TOP);
+ a.recycle();
+
setVibrateEnabled(mVibrationDuration > 0);
assignDefaultsIfNeeded();
}
@@ -302,8 +284,6 @@ public class MultiWaveView extends View {
Log.v(TAG, "TapRadius = " + mTapRadius);
Log.v(TAG, "WaveCenterX = " + mWaveCenterX);
Log.v(TAG, "WaveCenterY = " + mWaveCenterY);
- Log.v(TAG, "HorizontalOffset = " + mHorizontalOffset);
- Log.v(TAG, "VerticalOffset = " + mVerticalOffset);
}
public void suspendAnimations() {
@@ -1042,9 +1022,9 @@ public class MultiWaveView extends View {
// width or the specified outer radius.
final float placementWidth = Math.max(mOuterRing.getWidth(), 2 * mOuterRadius);
final float placementHeight = Math.max(mOuterRing.getHeight(), 2 * mOuterRadius);
- float newWaveCenterX = mHorizontalOffset + mHorizontalInset
+ float newWaveCenterX = mHorizontalInset
+ Math.max(width, mMaxTargetWidth + placementWidth) / 2;
- float newWaveCenterY = mVerticalOffset + mVerticalInset
+ float newWaveCenterY = mVerticalInset
+ Math.max(height, + mMaxTargetHeight + placementHeight) / 2;
if (mInitialLayout) {
diff --git a/core/java/com/android/internal/widget/multiwaveview/PointCloud.java b/core/java/com/android/internal/widget/multiwaveview/PointCloud.java
new file mode 100644
index 0000000..2ef8c78
--- /dev/null
+++ b/core/java/com/android/internal/widget/multiwaveview/PointCloud.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2012 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 com.android.internal.widget.multiwaveview;
+
+import java.util.ArrayList;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.util.FloatMath;
+import android.util.Log;
+
+public class PointCloud {
+ private static final float MIN_POINT_SIZE = 2.0f;
+ private static final float MAX_POINT_SIZE = 4.0f;
+ private static final int INNER_POINTS = 8;
+ private static final String TAG = "PointCloud";
+ private ArrayList<Point> mPointCloud = new ArrayList<Point>();
+ private Drawable mDrawable;
+ private float mCenterX;
+ private float mCenterY;
+ private Paint mPaint;
+ private float mScale = 1.0f;
+ private static final float PI = (float) Math.PI;
+
+ // These allow us to have multiple concurrent animations.
+ WaveManager waveManager = new WaveManager();
+ GlowManager glowManager = new GlowManager();
+ private float mOuterRadius;
+
+ public class WaveManager {
+ private float radius = 50;
+ private float width = 200.0f; // TODO: Make configurable
+ private float alpha = 0.0f;
+ public void setRadius(float r) {
+ radius = r;
+ }
+
+ public float getRadius() {
+ return radius;
+ }
+
+ public void setAlpha(float a) {
+ alpha = a;
+ }
+
+ public float getAlpha() {
+ return alpha;
+ }
+ };
+
+ public class GlowManager {
+ private float x;
+ private float y;
+ private float radius = 0.0f;
+ private float alpha = 0.0f;
+
+ public void setX(float x1) {
+ x = x1;
+ }
+
+ public float getX() {
+ return x;
+ }
+
+ public void setY(float y1) {
+ y = y1;
+ }
+
+ public float getY() {
+ return y;
+ }
+
+ public void setAlpha(float a) {
+ alpha = a;
+ }
+
+ public float getAlpha() {
+ return alpha;
+ }
+
+ public void setRadius(float r) {
+ radius = r;
+ }
+
+ public float getRadius() {
+ return radius;
+ }
+ }
+
+ class Point {
+ float x;
+ float y;
+ float radius;
+
+ public Point(float x2, float y2, float r) {
+ x = (float) x2;
+ y = (float) y2;
+ radius = r;
+ }
+ }
+
+ public PointCloud(Drawable drawable) {
+ mPaint = new Paint();
+ mPaint.setFilterBitmap(true);
+ mPaint.setColor(Color.rgb(255, 255, 255)); // TODO: make configurable
+ mPaint.setAntiAlias(true);
+ mPaint.setDither(true);
+
+ mDrawable = drawable;
+ if (mDrawable != null) {
+ drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
+ }
+ }
+
+ public void setCenter(float x, float y) {
+ mCenterX = x;
+ mCenterY = y;
+ }
+
+ public void makePointCloud(float innerRadius, float outerRadius) {
+ if (innerRadius == 0) {
+ Log.w(TAG, "Must specify an inner radius");
+ return;
+ }
+ mOuterRadius = outerRadius;
+ mPointCloud.clear();
+ final float pointAreaRadius = (outerRadius - innerRadius);
+ final float ds = (2.0f * PI * innerRadius / INNER_POINTS);
+ final int bands = (int) Math.round(pointAreaRadius / ds);
+ final float dr = pointAreaRadius / bands;
+ float r = innerRadius;
+ for (int b = 0; b <= bands; b++, r += dr) {
+ float circumference = 2.0f * PI * r;
+ final int pointsInBand = (int) (circumference / ds);
+ float eta = PI/2.0f;
+ float dEta = 2.0f * PI / pointsInBand;
+ for (int i = 0; i < pointsInBand; i++) {
+ float x = r * FloatMath.cos(eta);
+ float y = r * FloatMath.sin(eta);
+ eta += dEta;
+ mPointCloud.add(new Point(x, y, r));
+ }
+ }
+ }
+
+ public void setScale(float scale) {
+ mScale = scale;
+ }
+
+ public float getScale() {
+ return mScale;
+ }
+
+ private static float hypot(float x, float y) {
+ return FloatMath.sqrt(x*x + y*y);
+ }
+
+ private static float max(float a, float b) {
+ return a > b ? a : b;
+ }
+
+ public int getAlphaForPoint(Point point) {
+ // Contribution from positional glow
+ float glowDistance = hypot(glowManager.x - point.x, glowManager.y - point.y);
+ float glowAlpha = 0.0f;
+ if (glowDistance < glowManager.radius) {
+ float cosf = FloatMath.cos(PI * 0.5f * glowDistance / glowManager.radius);
+ glowAlpha = glowManager.alpha * max(0.0f, (float) Math.pow(cosf, 0.5f));
+ }
+
+ // Compute contribution from Wave
+ float radius = hypot(point.x, point.y);
+ float distanceToWaveRing = Math.abs(radius - waveManager.radius);
+ float waveAlpha = 0.0f;
+ if (distanceToWaveRing < waveManager.width * 0.5f) {
+ float cosf = FloatMath.cos(PI * 0.5f * distanceToWaveRing / waveManager.width);
+ waveAlpha = waveManager.alpha * max(0.0f, (float) Math.pow(cosf, 15.0f));
+ }
+
+ return (int) (max(glowAlpha, waveAlpha) * 255);
+ }
+
+ private float interp(float min, float max, float f) {
+ return min + (max - min) * f;
+ }
+
+ public void draw(Canvas canvas) {
+ ArrayList<Point> points = mPointCloud;
+ final float cx = mDrawable != null ? (-mDrawable.getIntrinsicWidth() / 2) : 0;
+ final float cy = mDrawable != null ? (-mDrawable.getIntrinsicHeight() / 2) : 0;
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ canvas.scale(mScale, mScale, mCenterX, mCenterY);
+ for (int i = 0; i < points.size(); i++) {
+ Point point = points.get(i);
+ final float pointSize = interp(MAX_POINT_SIZE, MIN_POINT_SIZE,
+ point.radius / mOuterRadius);
+ final float px = point.x + cx + mCenterX;
+ final float py = point.y + cy + mCenterY;
+ int alpha = getAlphaForPoint(point);
+
+ if (alpha == 0) continue;
+
+ if (mDrawable != null) {
+ canvas.save(Canvas.MATRIX_SAVE_FLAG);
+ float s = pointSize / MAX_POINT_SIZE;
+ canvas.scale(s, s, px, py);
+ canvas.translate(px, py);
+ mDrawable.setAlpha(alpha);
+ mDrawable.draw(canvas);
+ canvas.restore();
+ } else {
+ mPaint.setAlpha(alpha);
+ canvas.drawCircle(px, py, pointSize, mPaint);
+ }
+ }
+ canvas.restore();
+ }
+
+}
diff --git a/core/res/res/drawable-hdpi/ic_lockscreen_glowdot.png b/core/res/res/drawable-hdpi/ic_lockscreen_glowdot.png
new file mode 100644
index 0000000..983c45e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lockscreen_glowdot.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lockscreen_glowdot.png b/core/res/res/drawable-mdpi/ic_lockscreen_glowdot.png
new file mode 100644
index 0000000..056c3f17
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lockscreen_glowdot.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lockscreen_glowdot.png b/core/res/res/drawable-xhdpi/ic_lockscreen_glowdot.png
new file mode 100644
index 0000000..cbd039a
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_lockscreen_glowdot.png
Binary files differ
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
index a666077..cd9c913 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock.xml
@@ -82,7 +82,7 @@
android:drawablePadding="4dip"
/>
- <com.android.internal.widget.multiwaveview.MultiWaveView
+ <com.android.internal.widget.multiwaveview.GlowPadView
android:id="@+id/unlock_widget"
android:orientation="horizontal"
android:layout_width="wrap_content"
@@ -94,13 +94,15 @@
android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
android:directionDescriptions="@array/lockscreen_direction_descriptions"
android:handleDrawable="@drawable/ic_lockscreen_handle"
- android:waveDrawable="@drawable/ic_lockscreen_outerring"
- android:outerRadius="@dimen/multiwaveview_target_placement_radius"
- android:snapMargin="@dimen/multiwaveview_snap_margin"
- android:hitRadius="@dimen/multiwaveview_hit_radius"
- android:chevronDrawables="@array/lockscreen_chevron_drawables"
- android:feedbackCount="3"
+ android:outerRingDrawable="@drawable/ic_lockscreen_outerring"
+ android:outerRadius="@dimen/glowpadview_target_placement_radius"
+ android:innerRadius="@dimen/glowpadview_inner_radius"
+ android:snapMargin="@dimen/glowpadview_snap_margin"
+ android:hitRadius="@dimen/glowpadview_hit_radius"
+ android:feedbackCount="1"
android:vibrationDuration="20"
+ android:glowRadius="@dimen/glowpadview_glow_radius"
+ android:pointDrawable="@drawable/ic_lockscreen_glowdot"
/>
<!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->
diff --git a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
index 17a3c84..32ca602 100644
--- a/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout-sw600dp/keyguard_screen_tab_unlock_land.xml
@@ -82,7 +82,7 @@
android:layout_alignParentTop="true"
android:drawablePadding="4dip"/>
- <com.android.internal.widget.multiwaveview.MultiWaveView
+ <com.android.internal.widget.multiwaveview.GlowPadView
android:id="@+id/unlock_widget"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -94,13 +94,15 @@
android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
android:directionDescriptions="@array/lockscreen_direction_descriptions"
android:handleDrawable="@drawable/ic_lockscreen_handle"
- android:waveDrawable="@drawable/ic_lockscreen_outerring"
- android:outerRadius="@dimen/multiwaveview_target_placement_radius"
- android:snapMargin="@dimen/multiwaveview_snap_margin"
- android:hitRadius="@dimen/multiwaveview_hit_radius"
- android:chevronDrawables="@array/lockscreen_chevron_drawables"
- android:feedbackCount="3"
+ android:outerRingDrawable="@drawable/ic_lockscreen_outerring"
+ android:outerRadius="@dimen/glowpadview_target_placement_radius"
+ android:innerRadius="@dimen/glowpadview_inner_radius"
+ android:snapMargin="@dimen/glowpadview_snap_margin"
+ android:hitRadius="@dimen/glowpadview_hit_radius"
+ android:feedbackCount="1"
android:vibrationDuration="20"
+ android:glowRadius="@dimen/glowpadview_glow_radius"
+ android:pointDrawable="@drawable/ic_lockscreen_glowdot"
/>
<!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock.xml b/core/res/res/layout/keyguard_screen_tab_unlock.xml
index 2dcb774..4e646a6 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock.xml
@@ -123,7 +123,7 @@
android:layout_width="match_parent"
android:layout_height="302dip">
- <com.android.internal.widget.multiwaveview.MultiWaveView
+ <com.android.internal.widget.multiwaveview.GlowPadView
android:id="@+id/unlock_widget"
android:orientation="horizontal"
android:layout_width="match_parent"
@@ -135,13 +135,15 @@
android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
android:directionDescriptions="@array/lockscreen_direction_descriptions"
android:handleDrawable="@drawable/ic_lockscreen_handle"
- android:waveDrawable="@drawable/ic_lockscreen_outerring"
- android:outerRadius="@dimen/multiwaveview_target_placement_radius"
- android:snapMargin="@dimen/multiwaveview_snap_margin"
- android:hitRadius="@dimen/multiwaveview_hit_radius"
- android:chevronDrawables="@array/lockscreen_chevron_drawables"
- android:feedbackCount="3"
+ android:outerRingDrawable="@drawable/ic_lockscreen_outerring"
+ android:outerRadius="@dimen/glowpadview_target_placement_radius"
+ android:innerRadius="@dimen/glowpadview_inner_radius"
+ android:snapMargin="@dimen/glowpadview_snap_margin"
+ android:hitRadius="@dimen/glowpadview_hit_radius"
+ android:feedbackCount="1"
android:vibrationDuration="20"
+ android:glowRadius="@dimen/glowpadview_glow_radius"
+ android:pointDrawable="@drawable/ic_lockscreen_glowdot"
/>
<TextView
diff --git a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
index 10ddd1e..5a357fb 100644
--- a/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
+++ b/core/res/res/layout/keyguard_screen_tab_unlock_land.xml
@@ -129,24 +129,26 @@
<Space android:layout_width="64dip" android:layout_rowSpan="7" />
<!-- Column 2 -->
- <com.android.internal.widget.multiwaveview.MultiWaveView
+ <com.android.internal.widget.multiwaveview.GlowPadView
android:id="@+id/unlock_widget"
android:layout_width="302dip"
android:layout_height="match_parent"
android:layout_rowSpan="7"
- android:gravity="center"
+ android:gravity="left|center_vertical"
android:targetDrawables="@array/lockscreen_targets_with_camera"
android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"
android:directionDescriptions="@array/lockscreen_direction_descriptions"
android:handleDrawable="@drawable/ic_lockscreen_handle"
- android:waveDrawable="@drawable/ic_lockscreen_outerring"
- android:outerRadius="@dimen/multiwaveview_target_placement_radius"
- android:snapMargin="@dimen/multiwaveview_snap_margin"
- android:hitRadius="@dimen/multiwaveview_hit_radius"
- android:chevronDrawables="@array/lockscreen_chevron_drawables"
- android:feedbackCount="3"
+ android:outerRingDrawable="@drawable/ic_lockscreen_outerring"
+ android:outerRadius="@dimen/glowpadview_target_placement_radius"
+ android:innerRadius="@dimen/glowpadview_inner_radius"
+ android:snapMargin="@dimen/glowpadview_snap_margin"
+ android:hitRadius="@dimen/glowpadview_hit_radius"
+ android:feedbackCount="1"
android:vibrationDuration="20"
+ android:glowRadius="@dimen/glowpadview_glow_radius"
+ android:pointDrawable="@drawable/ic_lockscreen_glowdot"
/>
<!-- Music transport control -->
diff --git a/core/res/res/values-land/arrays.xml b/core/res/res/values-land/arrays.xml
index 7095c02..f2df3fa 100644
--- a/core/res/res/values-land/arrays.xml
+++ b/core/res/res/values-land/arrays.xml
@@ -19,7 +19,7 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Resources for MultiWaveView in LockScreen -->
+ <!-- Resources for GlowPadView in LockScreen -->
<array name="lockscreen_targets_when_silent">
<item>@null</item>"
<item>@drawable/ic_lockscreen_unlock</item>
diff --git a/core/res/res/values-sw600dp-land/arrays.xml b/core/res/res/values-sw600dp-land/arrays.xml
index 6a09cf8..2b5fd99 100644
--- a/core/res/res/values-sw600dp-land/arrays.xml
+++ b/core/res/res/values-sw600dp-land/arrays.xml
@@ -19,7 +19,7 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Resources for MultiWaveView in LockScreen -->
+ <!-- Resources for GlowPadView in LockScreen -->
<array name="lockscreen_targets_when_silent">
<item>@drawable/ic_lockscreen_unlock</item>
<item>@null</item>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index d26666e..8937c2a 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -45,8 +45,8 @@
<!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
<dimen name="keyguard_lockscreen_outerring_diameter">364dp</dimen>
- <!-- target placement radius for MultiWaveView -->
- <dimen name="multiwaveview_target_placement_radius">182dip</dimen>
+ <!-- target placement radius for GlowPadView. Should be 1/2 of outerring diameter. -->
+ <dimen name="glowpadview_target_placement_radius">182dip</dimen>
<!-- Size of status line font in LockScreen. -->
<dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index 1eeca59..aeb6b4f 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -350,7 +350,7 @@
<item>中文 (繁體)</item>
</string-array>
- <!-- Resources for MultiWaveView in LockScreen -->
+ <!-- Resources for GlowPadView in LockScreen -->
<array name="lockscreen_targets_when_silent">
<item>@drawable/ic_lockscreen_unlock</item>
<item>@drawable/ic_lockscreen_search</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a68011d..00077512 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5377,6 +5377,54 @@
</declare-styleable>
<!-- =============================== -->
+ <!-- GlowPadView class attributes -->
+ <!-- =============================== -->
+ <eat-comment />
+ <declare-styleable name="GlowPadView">
+ <!-- Reference to an array resource that be shown as targets around a circle. -->
+ <attr name="targetDrawables"/>
+
+ <!-- Reference to an array resource that be used as description for the targets around the circle. -->
+ <attr name="targetDescriptions"/>
+
+ <!-- Reference to an array resource that be used to announce the directions with targets around the circle. -->
+ <attr name="directionDescriptions"/>
+
+ <!-- Sets a drawable as the center. -->
+ <attr name="handleDrawable"/>
+
+ <!-- Drawable to use for wave ripple animation. -->
+ <attr name="outerRingDrawable" format="reference"/>
+
+ <!-- Drawble used for drawing points -->
+ <attr name="pointDrawable" format="reference" />
+
+ <!-- Inner radius of glow area. -->
+ <attr name="innerRadius"/>
+
+ <!-- Outer radius of glow area. Target icons will be drawn on this circle. -->
+ <attr name="outerRadius"/>
+
+ <!-- Size of target radius. Points within this distance of target center is a "hit". -->
+ <attr name="hitRadius"/>
+
+ <!-- Radius of glow under finger. -->
+ <attr name="glowRadius" format="dimension" />
+
+ <!-- Tactile feedback duration for actions. Set to '0' for no vibration. -->
+ <attr name="vibrationDuration"/>
+
+ <!-- How close we need to be before snapping to a target. -->
+ <attr name="snapMargin"/>
+
+ <!-- Number of waves/chevrons to show in animation. -->
+ <attr name="feedbackCount"/>
+
+ <!-- Used when the handle shouldn't wait to be hit before following the finger -->
+ <attr name="alwaysTrackFinger"/>
+ </declare-styleable>
+
+ <!-- =============================== -->
<!-- MultiWaveView class attributes -->
<!-- =============================== -->
<eat-comment />
@@ -5393,22 +5441,6 @@
<!-- Sets a drawable as the drag center. -->
<attr name="handleDrawable" format="reference" />
- <!-- Drawable to use for chevron animation on the left. May be null.
- @deprecated use chevronDrawables instead -->
- <attr name="leftChevronDrawable" format="reference" />
-
- <!-- Drawable to use for chevron animation on the right. May be null.
- @deprecated use chevronDrawables instead -->
- <attr name="rightChevronDrawable" format="reference" />
-
- <!-- Drawable to use for chevron animation on the top. May be null.
- @deprecated use chevronDrawables instead -->
- <attr name="topChevronDrawable" format="reference" />
-
- <!-- Drawable to use for chevron animation on the bottom. May be null.
- @deprecated use chevronDrawables instead -->
- <attr name="bottomChevronDrawable" format="reference" />
-
<!-- Drawables to use for chevron animations. May be null. -->
<attr name="chevronDrawables" format="reference"/>
@@ -5430,17 +5462,6 @@
<!-- Number of waves/chevrons to show in animation. -->
<attr name="feedbackCount" format="integer" />
- <!-- {@deprecated Not used by the framework. Use android:gravity instead}
- Used to shift center of pattern vertically. -->
- <attr name="verticalOffset" format="dimension" />
-
- <!-- {@deprecated Not used by the framework. Use android:gravity instead}
- Used to shift center of pattern horizontally. -->
- <attr name="horizontalOffset" format="dimension" />
-
- <!-- How the items in this layout should be positioned -->
- <attr name="gravity" />
-
<!-- Used when the handle shouldn't wait to be hit before following the finger -->
<attr name="alwaysTrackFinger" format="boolean" />
</declare-styleable>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index d549644..ffbcb95 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -73,14 +73,20 @@
<!-- Size of lockscreen outerring on unsecure unlock LockScreen -->
<dimen name="keyguard_lockscreen_outerring_diameter">270dp</dimen>
- <!-- Default target placement radius for MultiWaveView -->
- <dimen name="multiwaveview_target_placement_radius">135dip</dimen>
+ <!-- Default target placement radius for GlowPadView. Should be 1/2 of outerring diameter. -->
+ <dimen name="glowpadview_target_placement_radius">135dip</dimen>
- <!-- Default distance beyond which MultiWaveView snaps to the target radius -->
- <dimen name="multiwaveview_snap_margin">20dip</dimen>
+ <!-- Default glow radius for GlowPadView -->
+ <dimen name="glowpadview_glow_radius">75dip</dimen>
- <!-- Default distance from each snap target that MultiWaveView considers a "hit" -->
- <dimen name="multiwaveview_hit_radius">60dip</dimen>
+ <!-- Default distance beyond which GlowPadView snaps to the target radius -->
+ <dimen name="glowpadview_snap_margin">20dip</dimen>
+
+ <!-- Default distance from each snap target that GlowPadView considers a "hit" -->
+ <dimen name="glowpadview_hit_radius">60dip</dimen>
+
+ <!-- Default distance from each snap target that GlowPadView considers a "hit" -->
+ <dimen name="glowpadview_inner_radius">15dip</dimen>
<!-- Preference activity side margins -->
<dimen name="preference_screen_side_margin">0dp</dimen>
@@ -228,10 +234,10 @@
a few are present. -->
<dimen name="action_bar_stacked_tab_max_width">180dp</dimen>
- <!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
+ <!-- Size of notification text (see TextAppearance.StatusBar.EventContent) -->
<dimen name="notification_text_size">14dp</dimen>
- <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) -->
+ <!-- Size of notification text titles (see TextAppearance.StatusBar.EventContent.Title) -->
<dimen name="notification_title_text_size">18dp</dimen>
- <!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
+ <!-- Size of smaller notification text (see TextAppearance.StatusBar.EventContent.Line2, Info, Time) -->
<dimen name="notification_subtext_size">12dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/drawable-hdpi/navbar_search_bg_scrim.9.png b/packages/SystemUI/res/drawable-hdpi/navbar_search_bg_scrim.9.png
deleted file mode 100644
index 4c163a2..0000000
--- a/packages/SystemUI/res/drawable-hdpi/navbar_search_bg_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/navbar_search_bg_scrim.9.png b/packages/SystemUI/res/drawable-mdpi/navbar_search_bg_scrim.9.png
deleted file mode 100644
index 21c5abd..0000000
--- a/packages/SystemUI/res/drawable-mdpi/navbar_search_bg_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/navbar_search_bg_scrim.9.png b/packages/SystemUI/res/drawable-xhdpi/navbar_search_bg_scrim.9.png
deleted file mode 100644
index 7874c63..0000000
--- a/packages/SystemUI/res/drawable-xhdpi/navbar_search_bg_scrim.9.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
index ae81167..e6c0087 100644
--- a/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-land/status_bar_search_panel.xml
@@ -38,25 +38,29 @@
android:layout_height="match_parent"
android:layout_alignParentRight="true">
- <com.android.internal.widget.multiwaveview.MultiWaveView
- android:id="@+id/multi_wave_view"
+ <com.android.internal.widget.multiwaveview.GlowPadView
+ android:id="@+id/glow_pad_view"
android:orientation="vertical"
android:layout_width="@dimen/navbar_search_panel_height"
android:layout_height="match_parent"
android:layout_alignParentBottom="true"
- android:background="@drawable/navbar_search_bg_scrim"
android:gravity="left"
prvandroid:targetDrawables="@array/navbar_search_targets"
prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
prvandroid:handleDrawable="@drawable/navbar_search_handle"
- prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
+ prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
prvandroid:feedbackCount="0"
prvandroid:vibrationDuration="@integer/config_vibration_duration"
- prvandroid:alwaysTrackFinger="true"/>
+ prvandroid:alwaysTrackFinger="true"
+ prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+ prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"
+ />
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
index 785d5dd..3828136 100644
--- a/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-port/status_bar_search_panel.xml
@@ -38,25 +38,29 @@
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
- <com.android.internal.widget.multiwaveview.MultiWaveView
- android:id="@+id/multi_wave_view"
+ <com.android.internal.widget.multiwaveview.GlowPadView
+ android:id="@+id/glow_pad_view"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="@dimen/navbar_search_panel_height"
android:layout_alignParentBottom="true"
- android:background="@drawable/navbar_search_bg_scrim"
android:gravity="top"
prvandroid:targetDrawables="@array/navbar_search_targets"
prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
prvandroid:handleDrawable="@drawable/navbar_search_handle"
- prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
+ prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
prvandroid:feedbackCount="0"
prvandroid:vibrationDuration="@integer/config_vibration_duration"
- prvandroid:alwaysTrackFinger="true"/>
+ prvandroid:alwaysTrackFinger="true"
+ prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+ prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"
+ />
</RelativeLayout>
diff --git a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
index 74a15f2..c17f858 100644
--- a/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-sw600dp/status_bar_search_panel.xml
@@ -25,23 +25,26 @@
android:layout_height="match_parent"
android:layout_width="match_parent">
- <com.android.internal.widget.multiwaveview.MultiWaveView
- android:id="@+id/multi_wave_view"
+ <com.android.internal.widget.multiwaveview.GlowPadView
+ android:id="@+id/glow_pad_view"
android:layout_width="wrap_content"
android:layout_height="@dimen/navbar_search_panel_height"
android:layout_gravity="center_horizontal|bottom"
android:gravity="center_horizontal|top"
- android:background="@drawable/navbar_search_bg_scrim"
prvandroid:targetDrawables="@array/navbar_search_targets"
prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
prvandroid:handleDrawable="@drawable/navbar_search_handle"
- prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
+ prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
prvandroid:feedbackCount="0"
prvandroid:vibrationDuration="@integer/config_vibration_duration"
- prvandroid:alwaysTrackFinger="true"/>
+ prvandroid:alwaysTrackFinger="true"
+ prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+ prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"/>
</com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml b/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
index 2a97307..100f81d 100644
--- a/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
+++ b/packages/SystemUI/res/layout-sw720dp/status_bar_search_panel.xml
@@ -25,24 +25,27 @@
android:layout_height="match_parent"
android:layout_width="match_parent">
- <com.android.internal.widget.multiwaveview.MultiWaveView
- android:id="@+id/multi_wave_view"
+ <com.android.internal.widget.multiwaveview.GlowPadView
+ android:id="@+id/glow_pad_view"
android:layout_width="wrap_content"
android:layout_height="@dimen/navbar_search_panel_height"
android:layout_gravity="left|bottom"
android:gravity="top|right"
android:layout_marginLeft="-150dip"
- android:background="@drawable/navbar_search_bg_scrim"
prvandroid:targetDrawables="@array/navbar_search_targets"
prvandroid:targetDescriptions="@array/navbar_search_target_descriptions"
prvandroid:directionDescriptions="@array/navbar_search_direction_descriptions"
prvandroid:handleDrawable="@drawable/navbar_search_handle"
- prvandroid:waveDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRingDrawable="@drawable/navbar_search_outerring"
+ prvandroid:outerRadius="@dimen/navbar_search_outerring_radius"
+ prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"
prvandroid:snapMargin="@dimen/navbar_search_snap_margin"
prvandroid:hitRadius="@dimen/navbar_search_hit_radius"
prvandroid:feedbackCount="0"
prvandroid:vibrationDuration="@integer/config_vibration_duration"
- prvandroid:alwaysTrackFinger="true"/>
+ prvandroid:alwaysTrackFinger="true"
+ prvandroid:glowRadius="@*android:dimen/glowpadview_glow_radius"
+ prvandroid:pointDrawable="@*android:drawable/ic_lockscreen_glowdot"/>
</com.android.systemui.SearchPanelView>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 1bf59b0..2b5248f 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -30,6 +30,9 @@
<!-- Diameter of outer shape drawable shown in navbar search-->
<dimen name="navbar_search_outerring_diameter">430dip</dimen>
+ <!-- Diameter of outer shape drawable shown in navbar search. Should be 1/2 of above value. -->
+ <dimen name="navbar_search_outerring_radius">215dip</dimen>
+
<!-- Height of search panel including navigation bar height -->
<dimen name="navbar_search_panel_height">280dip</dimen>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index f40ffd4..c88ae2a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -119,6 +119,9 @@
<!-- Diameter of outer shape drawable shown in navbar search-->
<dimen name="navbar_search_outerring_diameter">340dp</dimen>
+ <!-- Diameter of outer shape drawable shown in navbar search. Should be 1/2 of above value -->
+ <dimen name="navbar_search_outerring_radius">170dp</dimen>
+
<!-- Threshold for swipe-up gesture to activate search dialog -->
<dimen name="navbar_search_up_threshhold">40dip</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index 8b8a814..923bcba 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -35,8 +35,8 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.FrameLayout;
-import com.android.internal.widget.multiwaveview.MultiWaveView;
-import com.android.internal.widget.multiwaveview.MultiWaveView.OnTriggerListener;
+import com.android.internal.widget.multiwaveview.GlowPadView;
+import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
import com.android.systemui.R;
import com.android.systemui.recent.StatusBarTouchProxy;
import com.android.systemui.statusbar.BaseStatusBar;
@@ -58,7 +58,7 @@ public class SearchPanelView extends FrameLayout implements
private boolean mShowing;
private View mSearchTargetsContainer;
- private MultiWaveView mMultiWaveView;
+ private GlowPadView mGlowPadView;
public SearchPanelView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
@@ -125,7 +125,7 @@ public class SearchPanelView extends FrameLayout implements
}
}
- class MultiWaveTriggerListener implements MultiWaveView.OnTriggerListener {
+ class GlowPadTriggerListener implements GlowPadView.OnTriggerListener {
boolean mWaitingForLaunch;
public void onGrabbed(View v, int handle) {
@@ -141,7 +141,7 @@ public class SearchPanelView extends FrameLayout implements
}
public void onTrigger(View v, final int target) {
- final int resId = mMultiWaveView.getResourceIdForTarget(target);
+ final int resId = mGlowPadView.getResourceIdForTarget(target);
switch (resId) {
case com.android.internal.R.drawable.ic_lockscreen_search:
mWaitingForLaunch = true;
@@ -154,13 +154,13 @@ public class SearchPanelView extends FrameLayout implements
public void onFinishFinalAnimation() {
}
}
- final MultiWaveTriggerListener mMultiWaveViewListener = new MultiWaveTriggerListener();
+ final GlowPadTriggerListener mGlowPadViewListener = new GlowPadTriggerListener();
@Override
public void onAnimationStarted() {
postDelayed(new Runnable() {
public void run() {
- mMultiWaveViewListener.mWaitingForLaunch = false;
+ mGlowPadViewListener.mWaitingForLaunch = false;
mBar.hideSearchPanel();
}
}, SEARCH_PANEL_HOLD_DURATION);
@@ -173,13 +173,13 @@ public class SearchPanelView extends FrameLayout implements
mSearchTargetsContainer = findViewById(R.id.search_panel_container);
mStatusBarTouchProxy = (StatusBarTouchProxy) findViewById(R.id.status_bar_touch_proxy);
// TODO: fetch views
- mMultiWaveView = (MultiWaveView) findViewById(R.id.multi_wave_view);
- mMultiWaveView.setOnTriggerListener(mMultiWaveViewListener);
+ mGlowPadView = (GlowPadView) findViewById(R.id.glow_pad_view);
+ mGlowPadView.setOnTriggerListener(mGlowPadViewListener);
SearchManager searchManager = getSearchManager();
if (searchManager != null) {
ComponentName component = searchManager.getGlobalSearchActivity();
if (component != null) {
- if (!mMultiWaveView.replaceTargetDrawablesIfPresent(component,
+ if (!mGlowPadView.replaceTargetDrawablesIfPresent(component,
ASSIST_ICON_METADATA_NAME,
com.android.internal.R.drawable.ic_lockscreen_search)) {
Slog.w(TAG, "Couldn't grab icon from component " + component);
@@ -214,7 +214,7 @@ public class SearchPanelView extends FrameLayout implements
private final OnPreDrawListener mPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
public boolean onPreDraw() {
getViewTreeObserver().removeOnPreDrawListener(this);
- mMultiWaveView.resumeAnimations();
+ mGlowPadView.resumeAnimations();
return false;
}
};
@@ -240,7 +240,8 @@ public class SearchPanelView extends FrameLayout implements
setVisibility(View.VISIBLE);
// Don't start the animation until we've created the layer, which is done
// right before we are drawn
- mMultiWaveView.suspendAnimations();
+ mGlowPadView.suspendAnimations();
+ mGlowPadView.ping();
getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
vibrate();
}
@@ -299,7 +300,7 @@ public class SearchPanelView extends FrameLayout implements
public void setStatusBarView(final View statusBarView) {
if (mStatusBarTouchProxy != null) {
mStatusBarTouchProxy.setStatusBar(statusBarView);
-// mMultiWaveView.setOnTouchListener(new OnTouchListener() {
+// mGlowPadView.setOnTouchListener(new OnTouchListener() {
// public boolean onTouch(View v, MotionEvent event) {
// return statusBarView.onTouchEvent(event);
// }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index 8df9b85..9b46af8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -404,6 +404,7 @@ public class TabletStatusBar extends BaseStatusBar implements
mRecentsPanel.updateValuesFromResources();
mShowSearchHoldoff = mContext.getResources().getInteger(
R.integer.config_show_search_delay);
+ updateSearchPanel();
}
protected void loadDimens() {
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index d37207c..c9388cb 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -23,7 +23,7 @@ import com.android.internal.telephony.IccCard.State;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.SlidingTab;
import com.android.internal.widget.WaveView;
-import com.android.internal.widget.multiwaveview.MultiWaveView;
+import com.android.internal.widget.multiwaveview.GlowPadView;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
@@ -286,16 +286,16 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
return mSearchManager;
}
- class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,
+ class GlowPadViewMethods implements GlowPadView.OnTriggerListener,
UnlockWidgetCommonMethods {
- private final MultiWaveView mMultiWaveView;
+ private final GlowPadView mGlowPadView;
- MultiWaveViewMethods(MultiWaveView multiWaveView) {
- mMultiWaveView = multiWaveView;
+ GlowPadViewMethods(GlowPadView glowPadView) {
+ mGlowPadView = glowPadView;
}
public boolean isTargetPresent(int resId) {
- return mMultiWaveView.getTargetPosition(resId) != -1;
+ return mGlowPadView.getTargetPosition(resId) != -1;
}
public void updateResources() {
@@ -307,8 +307,8 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
} else {
resId = R.array.lockscreen_targets_with_camera;
}
- if (mMultiWaveView.getTargetResourceId() != resId) {
- mMultiWaveView.setTargetResources(resId);
+ if (mGlowPadView.getTargetResourceId() != resId) {
+ mGlowPadView.setTargetResources(resId);
}
// Update the search icon with drawable from the search .apk
@@ -317,7 +317,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
if (searchManager != null) {
ComponentName component = searchManager.getGlobalSearchActivity();
if (component != null) {
- if (!mMultiWaveView.replaceTargetDrawablesIfPresent(component,
+ if (!mGlowPadView.replaceTargetDrawablesIfPresent(component,
ASSIST_ICON_METADATA_NAME,
com.android.internal.R.drawable.ic_lockscreen_search)) {
Slog.w(TAG, "Couldn't grab icon from package " + component);
@@ -343,7 +343,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
}
public void onTrigger(View v, int target) {
- final int resId = mMultiWaveView.getResourceIdForTarget(target);
+ final int resId = mGlowPadView.getResourceIdForTarget(target);
switch (resId) {
case com.android.internal.R.drawable.ic_lockscreen_search:
Intent assistIntent = getAssistIntent();
@@ -393,33 +393,33 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
// Don't poke the wake lock when returning to a state where the handle is
// not grabbed since that can happen when the system (instead of the user)
// cancels the grab.
- if (handle != MultiWaveView.OnTriggerListener.NO_HANDLE) {
+ if (handle != GlowPadView.OnTriggerListener.NO_HANDLE) {
mCallback.pokeWakelock();
}
}
public View getView() {
- return mMultiWaveView;
+ return mGlowPadView;
}
public void reset(boolean animate) {
- mMultiWaveView.reset(animate);
+ mGlowPadView.reset(animate);
}
public void ping() {
- mMultiWaveView.ping();
+ mGlowPadView.ping();
}
public void setEnabled(int resourceId, boolean enabled) {
- mMultiWaveView.setEnableTarget(resourceId, enabled);
+ mGlowPadView.setEnableTarget(resourceId, enabled);
}
public int getTargetPosition(int resourceId) {
- return mMultiWaveView.getTargetPosition(resourceId);
+ return mGlowPadView.getTargetPosition(resourceId);
}
public void cleanUp() {
- mMultiWaveView.setOnTriggerListener(null);
+ mGlowPadView.setOnTriggerListener(null);
}
public void onFinishFinalAnimation() {
@@ -531,11 +531,11 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);
waveView.setOnTriggerListener(waveViewMethods);
return waveViewMethods;
- } else if (unlockWidget instanceof MultiWaveView) {
- MultiWaveView multiWaveView = (MultiWaveView) unlockWidget;
- MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);
- multiWaveView.setOnTriggerListener(multiWaveViewMethods);
- return multiWaveViewMethods;
+ } else if (unlockWidget instanceof GlowPadView) {
+ GlowPadView glowPadView = (GlowPadView) unlockWidget;
+ GlowPadViewMethods glowPadViewMethods = new GlowPadViewMethods(glowPadView);
+ glowPadView.setOnTriggerListener(glowPadViewMethods);
+ return glowPadViewMethods;
} else {
throw new IllegalStateException("Unrecognized unlock widget: " + unlockWidget);
}
@@ -545,12 +545,12 @@ class LockScreen extends LinearLayout implements KeyguardScreen {
boolean disabledByAdmin = mLockPatternUtils.getDevicePolicyManager()
.getCameraDisabled(null);
boolean disabledBySimState = mUpdateMonitor.isSimLocked();
- boolean cameraTargetPresent = (mUnlockWidgetMethods instanceof MultiWaveViewMethods)
- ? ((MultiWaveViewMethods) mUnlockWidgetMethods)
+ boolean cameraTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
+ ? ((GlowPadViewMethods) mUnlockWidgetMethods)
.isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_camera)
: false;
- boolean searchTargetPresent = (mUnlockWidgetMethods instanceof MultiWaveViewMethods)
- ? ((MultiWaveViewMethods) mUnlockWidgetMethods)
+ boolean searchTargetPresent = (mUnlockWidgetMethods instanceof GlowPadViewMethods)
+ ? ((GlowPadViewMethods) mUnlockWidgetMethods)
.isTargetPresent(com.android.internal.R.drawable.ic_lockscreen_search)
: false;