diff options
14 files changed, 158 insertions, 20 deletions
diff --git a/core/res/res/layout/keyguard_widget_remove_drop_target.xml b/core/res/res/layout/keyguard_widget_remove_drop_target.xml index c4fe9e0..f9f40ab 100644 --- a/core/res/res/layout/keyguard_widget_remove_drop_target.xml +++ b/core/res/res/layout/keyguard_widget_remove_drop_target.xml @@ -24,9 +24,10 @@ android:paddingRight="40dp" android:drawableLeft="@drawable/kg_widget_delete_drop_target" android:drawablePadding="4dp" + android:text="@string/kg_reordering_delete_drop_target_text" android:textColor="#FFF" android:textSize="13sp" android:shadowColor="#000" android:shadowDy="1.0" android:shadowRadius="1.0" - android:visibility="gone" />
\ No newline at end of file + android:visibility="gone" /> diff --git a/core/res/res/values-land/bools.xml b/core/res/res/values-land/bools.xml index 85c64d9..a1dd2e4 100644 --- a/core/res/res/values-land/bools.xml +++ b/core/res/res/values-land/bools.xml @@ -16,6 +16,7 @@ <resources> <bool name="kg_enable_camera_default_widget">false</bool> + <bool name="kg_top_align_page_shrink_on_bouncer_visible">true</bool> <bool name="kg_share_status_area">false</bool> <bool name="kg_sim_puk_account_full_screen">false</bool> </resources> diff --git a/core/res/res/values-sw600dp/bools.xml b/core/res/res/values-sw600dp/bools.xml index eae4f87..00f45c1 100644 --- a/core/res/res/values-sw600dp/bools.xml +++ b/core/res/res/values-sw600dp/bools.xml @@ -21,4 +21,6 @@ <bool name="kg_sim_puk_account_full_screen">false</bool> <!-- No camera for you, tablet user --> <bool name="kg_enable_camera_default_widget">false</bool> + <bool name="kg_center_small_widgets_vertically">true</bool> + <bool name="kg_top_align_page_shrink_on_bouncer_visible">false</bool> </resources> diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index d4ead01..457131a 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -16,6 +16,8 @@ <resources> <bool name="kg_enable_camera_default_widget">true</bool> + <bool name="kg_center_small_widgets_vertically">false</bool> + <bool name="kg_top_align_page_shrink_on_bouncer_visible">true</bool> <bool name="action_bar_embed_tabs">true</bool> <bool name="action_bar_embed_tabs_pre_jb">false</bool> <bool name="split_action_bar_is_narrow">true</bool> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index 3a24cc1..b8ec138 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -335,4 +335,9 @@ due to the appearance of the IME), then drop the multiuser selector. --> <dimen name="kg_squashed_layout_threshold">600dp</dimen> + <!-- The height of widgets which do not support vertical resizing. This is only + used on tablets; on phones, this size is determined by the space left by the + security mode. --> + <dimen name="kg_small_widget_height">160dp</dimen> + </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 73b9021..9932d1e 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3970,6 +3970,8 @@ <!-- Sequence of characters used to separate message strings in keyguard. Typically just em-dash with spaces on either side. [CHAR LIMIT=3] --> <string name="kg_text_message_separator" product="default">" \u2014 "</string> + <!-- The delete-widget drop target button text --> + <string name="kg_reordering_delete_drop_target_text">Remove</string> <!-- Message shown in dialog when user is attempting to set the music volume above the recommended maximum level for headphones --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index dfa2b4a..cd21d80 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1215,7 +1215,9 @@ <java-symbol type="bool" name="kg_enable_camera_default_widget" /> <java-symbol type="bool" name="kg_share_status_area" /> <java-symbol type="bool" name="kg_sim_puk_account_full_screen" /> + <java-symbol type="bool" name="kg_top_align_page_shrink_on_bouncer_visible" /> <java-symbol type="bool" name="target_honeycomb_needs_options_menu" /> + <java-symbol type="bool" name="kg_center_small_widgets_vertically" /> <java-symbol type="color" name="kg_multi_user_text_active" /> <java-symbol type="color" name="kg_multi_user_text_inactive" /> <java-symbol type="color" name="kg_widget_pager_gradient" /> @@ -1235,6 +1237,7 @@ <java-symbol type="dimen" name="keyguard_avatar_frame_shadow_radius" /> <java-symbol type="dimen" name="kg_edge_swipe_region_size" /> <java-symbol type="dimen" name="kg_squashed_layout_threshold" /> + <java-symbol type="dimen" name="kg_small_widget_height" /> <java-symbol type="drawable" name="ic_jog_dial_sound_off" /> <java-symbol type="drawable" name="ic_jog_dial_sound_on" /> <java-symbol type="drawable" name="ic_jog_dial_unlock" /> diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java index 1f31482..f165b61 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardHostView.java @@ -162,9 +162,11 @@ public class KeyguardHostView extends KeyguardViewBase { mAppWidgetContainer.setViewStateManager(mViewStateManager); mAppWidgetContainer.setLockPatternUtils(mLockPatternUtils); + ChallengeLayout challenge = slider != null ? slider : + (ChallengeLayout) findViewById(R.id.multi_pane_challenge); + challenge.setOnBouncerStateChangedListener(mViewStateManager); mViewStateManager.setPagedView(mAppWidgetContainer); - mViewStateManager.setChallengeLayout(slider != null ? slider : - (ChallengeLayout) findViewById(R.id.multi_pane_challenge)); + mViewStateManager.setChallengeLayout(challenge); mSecurityViewContainer = (KeyguardSecurityViewFlipper) findViewById(R.id.view_flipper); mKeyguardSelectorView = (KeyguardSelectorView) findViewById(R.id.keyguard_selector_view); mViewStateManager.setSecurityViewContainer(mSecurityViewContainer); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java index 7c117d9..6d88652 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewManager.java @@ -122,6 +122,7 @@ public class KeyguardViewManager { class ViewManagerHost extends FrameLayout { public ViewManagerHost(Context context) { super(context); + setFitsSystemWindows(true); } @Override @@ -164,7 +165,8 @@ public class KeyguardViewManager { mKeyguardHost = new ViewManagerHost(mContext); - int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN + int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; if (!mNeedsInput) { diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java index 969b65e..e53358b 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardViewStateManager.java @@ -19,7 +19,9 @@ import android.os.Handler; import android.os.Looper; import android.view.View; -public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChallengeScrolledListener { +public class KeyguardViewStateManager implements + SlidingChallengeLayout.OnChallengeScrolledListener, + ChallengeLayout.OnBouncerStateChangedListener { private KeyguardWidgetPager mKeyguardWidgetPager; private ChallengeLayout mChallengeLayout; @@ -196,6 +198,7 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle @Override public void onScrollStateChanged(int scrollState) { if (mKeyguardWidgetPager == null || mChallengeLayout == null) return; + boolean challengeOverlapping = mChallengeLayout.isChallengeOverlapping(); if (scrollState == SlidingChallengeLayout.SCROLL_STATE_IDLE) { @@ -226,15 +229,24 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle KeyguardWidgetFrame frame = mKeyguardWidgetPager.getWidgetPageAt(mPageListeningToSlider); if (frame == null) return; - frame.showFrame(this); + // Skip showing the frame and shrinking the widget if we are + if (!mChallengeLayout.isBouncing()) { + frame.showFrame(this); - // As soon as the security begins sliding, the widget becomes small (if it wasn't - // small to begin with). - if (!frame.isSmall()) { - // We need to fetch the final page, in case the pages are in motion. - mPageListeningToSlider = mKeyguardWidgetPager.getNextPage(); - frame.shrinkWidget(); + // As soon as the security begins sliding, the widget becomes small (if it wasn't + // small to begin with). + if (!frame.isSmall()) { + // We need to fetch the final page, in case the pages are in motion. + mPageListeningToSlider = mKeyguardWidgetPager.getNextPage(); + frame.shrinkWidget(); + } + } else { + if (!frame.isSmall()) { + // We need to fetch the final page, in case the pages are in motion. + mPageListeningToSlider = mKeyguardWidgetPager.getNextPage(); + } } + // View is on the move. Pause the security view until it completes. mKeyguardSecurityContainer.onPause(); } @@ -279,4 +291,14 @@ public class KeyguardViewStateManager implements SlidingChallengeLayout.OnChalle public int getTransportState() { return mTransportState; } + + // ChallengeLayout.OnBouncerStateChangedListener + @Override + public void onBouncerStateChanged(boolean bouncerActive) { + if (bouncerActive) { + mKeyguardWidgetPager.zoomOutToBouncer(); + } else { + mKeyguardWidgetPager.zoomInFromBouncer(); + } + } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java index 213b82f..fa1a1ae 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java @@ -112,6 +112,10 @@ public class KeyguardWidgetFrame extends FrameLayout { mFrameStrokeAdjustment = (int) (2 * density); + // This will be overriden on phones based on the current security mode, however on tablets + // we need to specify a height. + mSmallWidgetHeight = + res.getDimensionPixelSize(com.android.internal.R.dimen.kg_small_widget_height); mBackgroundDrawable = res.getDrawable(R.drawable.kg_bouncer_bg_white); mGradientColor = res.getColor(com.android.internal.R.color.kg_widget_pager_gradient); mGradientPaint.setXfermode(sAddBlendMode); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java index 7943b23..274e12b 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java @@ -44,7 +44,7 @@ import com.android.internal.widget.LockPatternUtils; import java.util.ArrayList; public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwitchListener, - OnLongClickListener { + OnLongClickListener, ChallengeLayout.OnBouncerStateChangedListener { ZInterpolator mZInterpolator = new ZInterpolator(0.5f); private static float CAMERA_DISTANCE = 10000; @@ -64,6 +64,7 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit private static final long CUSTOM_WIDGET_USER_ACTIVITY_TIMEOUT = 30000; private static final String TAG = "KeyguardWidgetPager"; + private boolean mCenterSmallWidgetsVertically; private int mPage = 0; private Callbacks mCallbacks; @@ -72,6 +73,10 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit private int mWidgetToResetAfterFadeOut; + // Bouncer + protected int BOUNCER_ZOOM_IN_OUT_DURATION = 250; + private float BOUNCER_SCALE_FACTOR = 0.67f; + // Background worker thread: used here for persistence, also made available to widget frames private final HandlerThread mBackgroundWorkerThread; private final Handler mBackgroundWorkerHandler; @@ -94,6 +99,8 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit Resources r = getResources(); mCameraWidgetEnabled = r.getBoolean(R.bool.kg_enable_camera_default_widget); + mCenterSmallWidgetsVertically = + r.getBoolean(com.android.internal.R.bool.kg_center_small_widgets_vertically); mBackgroundWorkerThread = new HandlerThread("KeyguardWidgetPager Worker"); mBackgroundWorkerThread.start(); mBackgroundWorkerHandler = new Handler(mBackgroundWorkerThread.getLooper()); @@ -277,6 +284,9 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit } else { // Lock the widget to be small. frame.setWidgetLockedSmall(true); + if (mCenterSmallWidgetsVertically) { + lp.gravity = Gravity.CENTER; + } } } } else { @@ -706,4 +716,46 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit KeyguardWidgetFrame child = getWidgetPageAt(viewIndex); child.setIsHoveringOverDeleteDropTarget(isHovering); } + + // ChallengeLayout.OnBouncerStateChangedListener + @Override + public void onBouncerStateChanged(boolean bouncerActive) { + if (bouncerActive) { + zoomOutToBouncer(); + } else { + zoomInFromBouncer(); + } + } + + // Zoom in after the bouncer is dismissed + void zoomInFromBouncer() { + if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) { + mZoomInOutAnim.cancel(); + } + final View currentPage = getPageAt(getCurrentPage()); + if (currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f) { + mZoomInOutAnim = new AnimatorSet(); + mZoomInOutAnim.setDuration(BOUNCER_ZOOM_IN_OUT_DURATION); + mZoomInOutAnim.playTogether( + ObjectAnimator.ofFloat(currentPage, "scaleX", 1f), + ObjectAnimator.ofFloat(currentPage , "scaleY", 1f)); + mZoomInOutAnim.start(); + } + } + + // Zoom out after the bouncer is initiated + void zoomOutToBouncer() { + if (mZoomInOutAnim != null && mZoomInOutAnim.isRunning()) { + mZoomInOutAnim.cancel(); + } + View currentPage = getPageAt(getCurrentPage()); + if (!(currentPage.getScaleX() < 1f || currentPage.getScaleY() < 1f)) { + mZoomInOutAnim = new AnimatorSet(); + mZoomInOutAnim.setDuration(BOUNCER_ZOOM_IN_OUT_DURATION); + mZoomInOutAnim.playTogether( + ObjectAnimator.ofFloat(currentPage, "scaleX", BOUNCER_SCALE_FACTOR), + ObjectAnimator.ofFloat(currentPage, "scaleY", BOUNCER_SCALE_FACTOR)); + mZoomInOutAnim.start(); + } + } } diff --git a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java index 00a0aed..8f47578 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/PagedView.java @@ -24,6 +24,7 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; +import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Matrix; @@ -209,7 +210,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc private long REORDERING_DELETE_DROP_TARGET_FADE_DURATION = 150; private float mMinScale = 1f; protected View mDragView; - private AnimatorSet mZoomInOutAnim; + protected AnimatorSet mZoomInOutAnim; private Runnable mSidePageHoverRunnable; private int mSidePageHoverIndex = -1; // This variable's scope is only for the duration of startReordering() and endReordering() @@ -246,6 +247,9 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc // Drop to delete private View mDeleteDropTarget; + // Bouncer + private boolean mTopAlignPageWhenShrinkingForBouncer = false; + public interface PageSwitchListener { void onPageSwitching(View newPage, int newPageIndex); void onPageSwitched(View newPage, int newPageIndex); @@ -270,8 +274,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc a.getDimensionPixelSize(R.styleable.PagedView_scrollIndicatorPaddingRight, 0); a.recycle(); - mEdgeSwipeRegionSize = - getResources().getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size); + Resources r = getResources(); + mEdgeSwipeRegionSize = r.getDimensionPixelSize(R.dimen.kg_edge_swipe_region_size); + mTopAlignPageWhenShrinkingForBouncer = + r.getBoolean(R.bool.kg_top_align_page_shrink_on_bouncer_visible); setHapticFeedbackEnabled(false); init(); @@ -645,6 +651,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc MeasureSpec.makeMeasureSpec(heightSize - verticalPadding, childHeightMode); child.measure(childWidthMeasureSpec, childHeightMeasureSpec); + if (mTopAlignPageWhenShrinkingForBouncer) { + child.setPivotX(child.getWidth() / 2); + child.setPivotY(0f); + } } setMeasuredDimension(scaledWidthSize, scaledHeightSize); diff --git a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java index 2712494..16ec8c5 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/SlidingChallengeLayout.java @@ -29,6 +29,7 @@ import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.util.DisplayMetrics; import android.util.FloatProperty; import android.util.Log; import android.util.Property; @@ -64,6 +65,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout private Drawable mFrameDrawable; private boolean mEdgeCaptured; + private DisplayMetrics mDisplayMetrics; + // Initialized during measurement from child layoutparams private View mExpandChallengeView; private KeyguardSecurityContainer mChallengeView; @@ -264,7 +267,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mTouchSlopSquare = mTouchSlop * mTouchSlop; - final float density = res.getDisplayMetrics().density; + mDisplayMetrics = res.getDisplayMetrics(); + final float density = mDisplayMetrics.density; // top half of the lock icon, plus another 25% to be sure mDragHandleClosedAbove = (int) (DRAG_HANDLE_CLOSED_ABOVE * density + 0.5f); @@ -481,6 +485,14 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout return; } mChallengeShowing = showChallenge; + + if (mExpandChallengeView == null || mChallengeView == null) { + // These might not be here yet if we haven't been through layout. + // If we haven't, the first layout pass will set everything up correctly + // based on mChallengeShowing as set above. + return; + } + if (mChallengeShowing) { mExpandChallengeView.setVisibility(View.INVISIBLE); mChallengeView.setVisibility(View.VISIBLE); @@ -520,8 +532,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout @Override public void showBouncer() { if (mIsBouncing) return; - showChallenge(true); mIsBouncing = true; + showChallenge(true); if (mScrimView != null) { mScrimView.setVisibility(VISIBLE); } @@ -887,9 +899,27 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout continue; } // Don't measure the challenge view twice! - if (child != mChallengeView) { - measureChildWithMargins(child, widthSpec, 0, heightSpec, 0); + if (child == mChallengeView) continue; + + // Measure children. Widget frame measures special, so that we can ignore + // insets for the IME. + int parentWidthSpec = widthSpec, parentHeightSpec = heightSpec; + final LayoutParams lp = (LayoutParams) child.getLayoutParams(); + if (lp.childType == LayoutParams.CHILD_TYPE_WIDGETS) { + final View root = getRootView(); + if (root != null) { + // This calculation is super dodgy and relies on several assumptions. + // Specifically that the root of the window will be padded in for insets + // and that the window is LAYOUT_IN_SCREEN. + final int windowWidth = mDisplayMetrics.widthPixels; + final int windowHeight = mDisplayMetrics.heightPixels - root.getPaddingTop(); + parentWidthSpec = MeasureSpec.makeMeasureSpec( + windowWidth, MeasureSpec.EXACTLY); + parentHeightSpec = MeasureSpec.makeMeasureSpec( + windowHeight, MeasureSpec.EXACTLY); + } } + measureChildWithMargins(child, parentWidthSpec, 0, parentHeightSpec, 0); } } |
