diff options
author | Selim Cinek <cinek@google.com> | 2014-06-20 16:37:04 -0700 |
---|---|---|
committer | Selim Cinek <cinek@google.com> | 2014-06-30 18:48:41 +0000 |
commit | 4e8b9ed30b67e5449d987e674b2966dc7f3ac224 (patch) | |
tree | 7294d84b5c57aca74731b95b6888095bdd55845f | |
parent | 5f834774c77b290e951c712608d1dde2251cd0a5 (diff) | |
download | frameworks_base-4e8b9ed30b67e5449d987e674b2966dc7f3ac224.zip frameworks_base-4e8b9ed30b67e5449d987e674b2966dc7f3ac224.tar.gz frameworks_base-4e8b9ed30b67e5449d987e674b2966dc7f3ac224.tar.bz2 |
Implemented new PIN unlock design
The pin unlock design was changed according to the spec
and new animations where introduced for the password field.
Bug: 13735707
Change-Id: I76f5e873bd0ea4f34ca3d2cd971223f0a83e2f28
32 files changed, 1626 insertions, 970 deletions
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index e7e750d..c2e1b96 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -7001,11 +7001,6 @@ <attr name="layout_maxHeight" /> </declare-styleable> - <declare-styleable name="NumPadKey"> - <attr name="digit" format="integer" /> - <attr name="textView" format="reference" /> - </declare-styleable> - <declare-styleable name="Toolbar"> <attr name="titleTextAppearance" format="reference" /> <attr name="subtitleTextAppearance" format="reference" /> diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml index d6be3133..5055854 100644 --- a/core/res/res/values/styles.xml +++ b/core/res/res/values/styles.xml @@ -2583,33 +2583,6 @@ please see styles_device_defaults.xml. <item name="android:externalRouteEnabledDrawable">@drawable/ic_media_route_holo_light</item> </style> - <!-- Keyguard PIN pad styles --> - <style name="Widget.Button.NumPadKey" - parent="@android:style/Widget.Button"> - <item name="android:singleLine">true</item> - <item name="android:gravity">left|center_vertical</item> - <item name="android:background">?android:attr/selectableItemBackground</item> - <item name="android:textSize">34dp</item> - <item name="android:fontFamily">sans-serif</item> - <item name="android:textStyle">normal</item> - <item name="android:textColor">#ffffff</item> - <item name="android:paddingBottom">10dp</item> - <item name="android:paddingLeft">20dp</item> - </style> - <style name="TextAppearance.NumPadKey" - parent="@android:style/TextAppearance"> - <item name="android:textSize">34dp</item> - <item name="android:fontFamily">sans-serif</item> - <item name="android:textStyle">normal</item> - <item name="android:textColor">#ffffff</item> - </style> - <style name="TextAppearance.NumPadKey.Klondike"> - <item name="android:textSize">20dp</item> - <item name="android:fontFamily">sans-serif-condensed</item> - <item name="android:textStyle">normal</item> - <item name="android:textColor">#80ffffff</item> - </style> - <style name="TextAppearance.TimePicker.TimeLabel" parent="TextAppearance"> </style> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 7442459..dac3352 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1431,9 +1431,6 @@ <java-symbol type="style" name="Animation.LockScreen" /> <java-symbol type="style" name="Theme.Dialog.RecentApplications" /> <java-symbol type="style" name="Theme.ExpandedMenu" /> - <java-symbol type="style" name="Widget.Button.NumPadKey" /> - <java-symbol type="style" name="TextAppearance.NumPadKey" /> - <java-symbol type="style" name="TextAppearance.NumPadKey.Klondike" /> <!-- From services --> <java-symbol type="anim" name="screen_rotate_0_enter" /> diff --git a/packages/Keyguard/res/drawable-hdpi/ic_done_wht.png b/packages/Keyguard/res/drawable-hdpi/ic_done_wht.png Binary files differnew file mode 100644 index 0000000..82c01ef --- /dev/null +++ b/packages/Keyguard/res/drawable-hdpi/ic_done_wht.png diff --git a/packages/Keyguard/res/drawable-hdpi/ic_input_delete.png b/packages/Keyguard/res/drawable-hdpi/ic_input_delete.png Binary files differdeleted file mode 100644 index 5d638bd..0000000 --- a/packages/Keyguard/res/drawable-hdpi/ic_input_delete.png +++ /dev/null diff --git a/packages/Keyguard/res/drawable-mdpi/ic_done_wht.png b/packages/Keyguard/res/drawable-mdpi/ic_done_wht.png Binary files differnew file mode 100644 index 0000000..8c16930 --- /dev/null +++ b/packages/Keyguard/res/drawable-mdpi/ic_done_wht.png diff --git a/packages/Keyguard/res/drawable-mdpi/ic_input_delete.png b/packages/Keyguard/res/drawable-mdpi/ic_input_delete.png Binary files differdeleted file mode 100644 index 47c8708..0000000 --- a/packages/Keyguard/res/drawable-mdpi/ic_input_delete.png +++ /dev/null diff --git a/packages/Keyguard/res/drawable-xhdpi/ic_done_wht.png b/packages/Keyguard/res/drawable-xhdpi/ic_done_wht.png Binary files differnew file mode 100644 index 0000000..6a4d8a7 --- /dev/null +++ b/packages/Keyguard/res/drawable-xhdpi/ic_done_wht.png diff --git a/packages/Keyguard/res/drawable-xhdpi/ic_input_delete.png b/packages/Keyguard/res/drawable-xhdpi/ic_input_delete.png Binary files differdeleted file mode 100644 index 8b822d9..0000000 --- a/packages/Keyguard/res/drawable-xhdpi/ic_input_delete.png +++ /dev/null diff --git a/packages/Keyguard/res/drawable-xxhdpi/ic_done_wht.png b/packages/Keyguard/res/drawable-xxhdpi/ic_done_wht.png Binary files differnew file mode 100644 index 0000000..4c04ba2 --- /dev/null +++ b/packages/Keyguard/res/drawable-xxhdpi/ic_done_wht.png diff --git a/packages/Keyguard/res/drawable-xxxhdpi/ic_done_wht.png b/packages/Keyguard/res/drawable-xxxhdpi/ic_done_wht.png Binary files differnew file mode 100644 index 0000000..bd6c4df --- /dev/null +++ b/packages/Keyguard/res/drawable-xxxhdpi/ic_done_wht.png diff --git a/packages/Keyguard/res/drawable/ic_backspace_24dp.xml b/packages/Keyguard/res/drawable/ic_backspace_24dp.xml new file mode 100644 index 0000000..9e5016d --- /dev/null +++ b/packages/Keyguard/res/drawable/ic_backspace_24dp.xml @@ -0,0 +1,28 @@ +<!-- +Copyright (C) 2014 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" > + <size + android:width="24dp" + android:height="24dp"/> + + <viewport + android:viewportWidth="48.0" + android:viewportHeight="48.0"/> + + <path + android:fill="#ffffffff" + android:pathData="M44.0,6.0L14.0,6.0c-1.4,0.0 -2.5,0.7 -3.2,1.8L0.0,24.0l10.8,16.2c0.7,1.1 1.8,1.8 3.2,1.8l30.0,0.0c2.2,0.0 4.0,-1.8 4.0,-4.0L48.0,10.0C48.0,7.8 46.2,6.0 44.0,6.0zM38.0,31.2L35.2,34.0L28.0,26.8L20.8,34.0L18.0,31.2l7.2,-7.2L18.0,16.8l2.8,-2.8l7.2,7.2l7.2,-7.2l2.8,2.8L30.8,24.0L38.0,31.2z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/ripple_drawable.xml b/packages/Keyguard/res/drawable/ripple_drawable.xml index af7941f..af7941f 100644 --- a/packages/SystemUI/res/drawable/ripple_drawable.xml +++ b/packages/Keyguard/res/drawable/ripple_drawable.xml diff --git a/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml deleted file mode 100644 index 49b4212..0000000 --- a/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml +++ /dev/null @@ -1,49 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- -** -** Copyright 2014, 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. -*/ ---> - -<!-- This is the host view that generally contains two sub views: the widget view - and the security view. --> -<com.android.keyguard.KeyguardSimpleHostView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:androidprv="http://schemas.android.com/apk/res-auto" - android:id="@+id/keyguard_host_view" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <com.android.keyguard.KeyguardSecurityContainer - android:id="@+id/keyguard_security_container" - android:layout_width="wrap_content" - android:layout_height="@dimen/keyguard_security_height" - android:clipChildren="false" - android:clipToPadding="false" - android:padding="0dp" - android:layout_gravity="center"> - <com.android.keyguard.KeyguardSecurityViewFlipper - android:id="@+id/view_flipper" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:clipChildren="false" - android:clipToPadding="false" - android:paddingTop="@dimen/keyguard_security_view_margin" - android:gravity="center"> - </com.android.keyguard.KeyguardSecurityViewFlipper> - </com.android.keyguard.KeyguardSecurityContainer> - -</com.android.keyguard.KeyguardSimpleHostView> - diff --git a/packages/Keyguard/res/layout/keyguard_bouncer.xml b/packages/Keyguard/res/layout/keyguard_bouncer.xml index 489c5f5..c85f04c 100644 --- a/packages/Keyguard/res/layout/keyguard_bouncer.xml +++ b/packages/Keyguard/res/layout/keyguard_bouncer.xml @@ -16,7 +16,8 @@ <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="match_parent"> + android:layout_height="match_parent" + android:background="@android:color/transparent" > <include style="@style/BouncerSecurityContainer" diff --git a/packages/Keyguard/res/layout/keyguard_num_pad_key.xml b/packages/Keyguard/res/layout/keyguard_num_pad_key.xml new file mode 100644 index 0000000..72591d4 --- /dev/null +++ b/packages/Keyguard/res/layout/keyguard_num_pad_key.xml @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ Copyright (C) 2014 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 + --> + +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <TextView + android:id="@+id/digit_text" + style="@style/Widget.TextView.NumPadKey" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + /> + <TextView + android:id="@+id/klondike_text" + style="@style/Widget.TextView.NumPadKey.Klondike" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + /> +</merge> + diff --git a/packages/Keyguard/res/layout/keyguard_pin_view.xml b/packages/Keyguard/res/layout/keyguard_pin_view.xml index a8e330b..a33f95b 100644 --- a/packages/Keyguard/res/layout/keyguard_pin_view.xml +++ b/packages/Keyguard/res/layout/keyguard_pin_view.xml @@ -18,215 +18,202 @@ --> <com.android.keyguard.KeyguardPINView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:androidprv="http://schemas.android.com/apk/res-auto" - android:id="@+id/keyguard_pin_view" - android:layout_width="match_parent" - android:layout_height="match_parent" - androidprv:layout_maxWidth="@dimen/keyguard_security_width" - androidprv:layout_maxHeight="@dimen/keyguard_security_height" - android:orientation="vertical" - android:contentDescription="@string/keyguard_accessibility_pin_unlock" - > - <include layout="@layout/keyguard_message_area" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/res-auto" + android:id="@+id/keyguard_pin_view" android:layout_width="match_parent" - android:layout_height="wrap_content" - /> + android:layout_height="match_parent" + androidprv:layout_maxWidth="@dimen/keyguard_security_width" + androidprv:layout_maxHeight="@dimen/keyguard_security_max_height" + android:orientation="vertical" + android:contentDescription="@string/keyguard_accessibility_pin_unlock" + > + <include layout="@layout/keyguard_message_area" + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> <LinearLayout - android:id="@+id/keyguard_bouncer_frame" - android:background="@drawable/kg_bouncer_bg_white" - android:layout_width="match_parent" - android:layout_height="0dp" - android:orientation="vertical" - android:layout_weight="1" - android:layoutDirection="ltr" - > - <RelativeLayout - android:id="@+id/row0" - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - > - <ImageButton android:id="@+id/delete_button" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:layout_alignParentEnd="true" - android:gravity="center_vertical" - android:src="@drawable/ic_input_delete" - android:clickable="true" - android:paddingTop="8dip" - android:paddingBottom="8dip" - android:paddingLeft="24dp" - android:paddingRight="24dp" - android:background="?android:attr/selectableItemBackground" - android:contentDescription="@string/keyboardview_keycode_delete" - /> - <TextView android:id="@+id/pinEntry" - android:editable="true" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_toStartOf="@+id/delete_button" - android:layout_alignParentStart="true" - android:gravity="center" - android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left" - android:singleLine="true" - android:cursorVisible="false" - android:background="@null" - android:textAppearance="@style/TextAppearance.NumPadKey" - android:imeOptions="flagForceAscii|actionDone" - /> + android:id="@+id/keyguard_bouncer_frame" + android:layout_width="match_parent" + android:layout_height="0dp" + android:orientation="vertical" + android:layout_weight="1" + android:layoutDirection="ltr" + > + <RelativeLayout + android:id="@+id/row0" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:paddingBottom="16dp" + > + <com.android.keyguard.PasswordTextView + android:id="@+id/pinEntry" + android:layout_width="@dimen/keyguard_security_width" + android:layout_height="match_parent" + android:gravity="center" + android:layout_centerHorizontal="true" + android:layout_marginRight="72dp" + androidprv:scaledTextSize="28" + /> + <ImageButton + android:id="@+id/delete_button" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:src="@drawable/ic_backspace_24dp" + android:clickable="true" + android:paddingTop="8dip" + android:paddingBottom="8dip" + android:paddingRight="8dp" + android:paddingLeft="24dp" + android:background="@drawable/ripple_drawable" + android:contentDescription="@string/keyboardview_keycode_delete" + android:layout_alignEnd="@+id/pinEntry" + android:layout_alignParentRight="true" + /> <View - android:id="@+id/divider" - android:layout_width="match_parent" - android:layout_height="1dp" - android:layout_alignParentBottom="true" - android:background="#55FFFFFF" - /> - </RelativeLayout> - <LinearLayout - android:id="@+id/row1" - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="horizontal" - > - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key1" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="1" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key2" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="2" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key3" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="3" - /> - </LinearLayout> - <LinearLayout - android:id="@+id/row2" - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="horizontal" - > - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key4" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="4" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key5" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="5" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key6" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="6" - /> - </LinearLayout> - <LinearLayout - android:id="@+id/row3" - android:layout_width="match_parent" - android:layout_height="0dp" - android:orientation="horizontal" - android:layout_weight="1" - > - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key7" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="7" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key8" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="8" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key9" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="9" - /> - </LinearLayout> - <LinearLayout - android:id="@+id/row4" - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="horizontal" - > - <Space - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key0" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pinEntry" - androidprv:digit="0" - /> - <ImageButton - android:id="@+id/key_enter" - style="@style/Widget.Button.NumPadKey" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - android:paddingRight="30dp" - android:src="@drawable/sym_keyboard_return_holo" - android:contentDescription="@string/keyboardview_keycode_enter" - /> - </LinearLayout> + android:id="@+id/divider" + android:layout_width="match_parent" + android:layout_height="1dp" + android:layout_alignParentBottom="true" + android:background="#28FFFFFF" + /> + </RelativeLayout> + <LinearLayout + android:id="@+id/row1" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="horizontal" + > + <com.android.keyguard.NumPadKey + android:id="@+id/key1" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="1" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key2" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="2" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key3" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="3" + /> + </LinearLayout> + <LinearLayout + android:id="@+id/row2" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="horizontal" + > + <com.android.keyguard.NumPadKey + android:id="@+id/key4" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="4" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key5" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="5" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key6" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="6" + /> + </LinearLayout> + <LinearLayout + android:id="@+id/row3" + android:layout_width="match_parent" + android:layout_height="0dp" + android:orientation="horizontal" + android:layout_weight="1" + > + <com.android.keyguard.NumPadKey + android:id="@+id/key7" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="7" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key8" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="8" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key9" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="9" + /> + </LinearLayout> + <LinearLayout + android:id="@+id/row4" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="horizontal" + > + <Space + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key0" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pinEntry" + androidprv:digit="0" + /> + <ImageButton + android:id="@+id/key_enter" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + android:paddingBottom="11sp" + android:src="@drawable/ic_done_wht" + android:background="@drawable/ripple_drawable" + android:contentDescription="@string/keyboardview_keycode_enter" + /> + </LinearLayout> </LinearLayout> <include layout="@layout/keyguard_eca" - android:id="@+id/keyguard_selector_fade_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:layout_gravity="bottom|center_horizontal" - android:gravity="center_horizontal" /> + android:id="@+id/keyguard_selector_fade_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_gravity="bottom|center_horizontal" + android:gravity="center_horizontal"/> </com.android.keyguard.KeyguardPINView> diff --git a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml index e167817..4f35daf 100644 --- a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml +++ b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml @@ -18,213 +18,205 @@ --> <!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. --> <com.android.keyguard.KeyguardSimPinView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:androidprv="http://schemas.android.com/apk/res-auto" - android:id="@+id/keyguard_sim_pin_view" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="match_parent" - androidprv:layout_maxWidth="@dimen/keyguard_security_width" - androidprv:layout_maxHeight="@dimen/keyguard_security_height" - android:gravity="center_horizontal"> + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/res-auto" + android:id="@+id/keyguard_sim_pin_view" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + androidprv:layout_maxWidth="@dimen/keyguard_security_width" + androidprv:layout_maxHeight="@dimen/keyguard_security_max_height" + android:gravity="center_horizontal" + android:contentDescription="@string/keyguard_accessibility_pin_unlock"> <ImageView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:src="@drawable/ic_lockscreen_sim"/> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:src="@drawable/ic_lockscreen_sim"/> <include layout="@layout/keyguard_message_area" - android:layout_width="match_parent" - android:layout_height="wrap_content" - /> + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> <LinearLayout - android:id="@+id/keyguard_bouncer_frame" - android:background="@drawable/kg_bouncer_bg_white" - android:layout_width="match_parent" - android:layout_height="0dp" - android:orientation="vertical" - android:layout_weight="1" - android:layoutDirection="ltr" - > - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:orientation="horizontal" - android:layout_weight="1" - > - <TextView android:id="@+id/simPinEntry" - android:editable="true" - android:layout_width="0dip" - android:layout_height="match_parent" - android:layout_weight="1" - android:gravity="center" - android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left" - android:singleLine="true" - android:cursorVisible="false" - android:background="@null" - android:textAppearance="@style/TextAppearance.NumPadKey" - android:imeOptions="flagForceAscii|actionDone" - /> - <ImageButton android:id="@+id/delete_button" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:gravity="center_vertical" - android:src="@drawable/ic_input_delete" - android:clickable="true" - android:paddingTop="8dip" - android:paddingBottom="8dip" - android:paddingLeft="24dp" - android:paddingRight="24dp" - android:background="?android:attr/selectableItemBackground" - android:contentDescription="@string/keyboardview_keycode_delete" - /> - </LinearLayout> - <View - android:layout_width="wrap_content" - android:layout_height="1dp" - android:background="#55FFFFFF" - /> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="horizontal" - > - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key1" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="1" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key2" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="2" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key3" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="3" - /> - </LinearLayout> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="horizontal" - > - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key4" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="4" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key5" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="5" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key6" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="6" - /> - </LinearLayout> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:orientation="horizontal" - android:layout_weight="1" - > - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key7" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="7" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key8" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="8" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key9" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="9" - /> - </LinearLayout> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="horizontal" - > - <Space - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key0" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/simPinEntry" - androidprv:digit="0" - /> - <ImageButton - android:id="@+id/key_enter" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - android:paddingRight="30dp" - android:src="@drawable/sym_keyboard_return_holo" - android:contentDescription="@string/keyboardview_keycode_enter" - /> - </LinearLayout> + android:id="@+id/keyguard_bouncer_frame" + android:layout_width="match_parent" + android:layout_height="0dp" + android:orientation="vertical" + android:layout_weight="1" + android:layoutDirection="ltr" + > + <RelativeLayout + android:id="@+id/row0" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:paddingBottom="16dp" + > + <com.android.keyguard.PasswordTextView + android:id="@+id/simPinEntry" + android:layout_width="@dimen/keyguard_security_width" + android:layout_height="match_parent" + android:gravity="center" + android:layout_centerHorizontal="true" + android:layout_marginRight="72dp" + androidprv:scaledTextSize="28" + /> + <ImageButton + android:id="@+id/delete_button" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:src="@drawable/ic_backspace_24dp" + android:clickable="true" + android:paddingTop="8dip" + android:paddingBottom="8dip" + android:paddingRight="8dp" + android:paddingLeft="24dp" + android:background="@drawable/ripple_drawable" + android:contentDescription="@string/keyboardview_keycode_delete" + android:layout_alignEnd="@+id/pinEntry" + android:layout_alignParentRight="true" + /> + <View + android:id="@+id/divider" + android:layout_width="match_parent" + android:layout_height="1dp" + android:layout_alignParentBottom="true" + android:background="#28FFFFFF" + /> + </RelativeLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="horizontal" + > + <com.android.keyguard.NumPadKey + android:id="@+id/key1" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="1" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key2" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="2" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key3" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="3" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="horizontal" + > + <com.android.keyguard.NumPadKey + android:id="@+id/key4" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="4" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key5" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="5" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key6" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="6" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:orientation="horizontal" + android:layout_weight="1" + > + <com.android.keyguard.NumPadKey + android:id="@+id/key7" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="7" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key8" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="8" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key9" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="9" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="horizontal" + > + <Space + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key0" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/simPinEntry" + androidprv:digit="0" + /> + <ImageButton + android:id="@+id/key_enter" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + android:paddingBottom="11sp" + android:src="@drawable/ic_done_wht" + android:background="@drawable/ripple_drawable" + android:contentDescription="@string/keyboardview_keycode_enter" + /> + </LinearLayout> </LinearLayout> <include layout="@layout/keyguard_eca" - android:id="@+id/keyguard_selector_fade_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:layout_gravity="bottom|center_horizontal" - android:gravity="center_horizontal" /> + android:id="@+id/keyguard_selector_fade_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_gravity="bottom|center_horizontal" + android:gravity="center_horizontal"/> </com.android.keyguard.KeyguardSimPinView> diff --git a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml index ac798ca..41484e2 100644 --- a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml +++ b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml @@ -19,212 +19,203 @@ <!-- This is the SIM PUK view that allows the user to recover their device by entering the carrier-provided PUK code and entering a new SIM PIN for it. --> <com.android.keyguard.KeyguardSimPukView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:androidprv="http://schemas.android.com/apk/res-auto" - android:id="@+id/keyguard_sim_puk_view" - android:orientation="vertical" - android:layout_width="match_parent" - android:layout_height="match_parent" - androidprv:layout_maxWidth="@dimen/keyguard_security_width" - androidprv:layout_maxHeight="@dimen/keyguard_security_height" - android:gravity="center_horizontal"> + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/res-auto" + android:id="@+id/keyguard_sim_puk_view" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + androidprv:layout_maxWidth="@dimen/keyguard_security_width" + androidprv:layout_maxHeight="@dimen/keyguard_security_max_height" + android:gravity="center_horizontal"> <ImageView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:src="@drawable/ic_lockscreen_sim"/> + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:src="@drawable/ic_lockscreen_sim"/> <include layout="@layout/keyguard_message_area" - android:layout_width="match_parent" - android:layout_height="wrap_content" - /> + android:layout_width="match_parent" + android:layout_height="wrap_content" + /> <LinearLayout - android:id="@+id/keyguard_bouncer_frame" - android:background="@drawable/kg_bouncer_bg_white" - android:layout_width="match_parent" - android:layout_height="0dp" - android:orientation="vertical" - android:layout_weight="1" - android:layoutDirection="ltr" - > - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:orientation="horizontal" - android:layout_weight="1" - > - <TextView android:id="@+id/pukEntry" - android:editable="true" - android:layout_width="0dip" - android:layout_height="match_parent" - android:layout_weight="1" - android:gravity="center" - android:layout_marginStart="@dimen/keyguard_lockscreen_pin_margin_left" - android:singleLine="true" - android:cursorVisible="false" - android:background="@null" - android:textAppearance="@style/TextAppearance.NumPadKey" - android:imeOptions="flagForceAscii|actionDone" - /> - <ImageButton android:id="@+id/delete_button" - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:gravity="center_vertical" - android:src="@drawable/ic_input_delete" - android:clickable="true" - android:paddingTop="8dip" - android:paddingBottom="8dip" - android:paddingLeft="24dp" - android:paddingRight="24dp" - android:background="?android:attr/selectableItemBackground" - android:contentDescription="@string/keyboardview_keycode_delete" - /> - </LinearLayout> - <View - android:layout_width="wrap_content" - android:layout_height="1dp" - android:background="#55FFFFFF" - /> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="horizontal" - > - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key1" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="1" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key2" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="2" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key3" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="3" - /> - </LinearLayout> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="horizontal" - > - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key4" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="4" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key5" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="5" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key6" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="6" - /> - </LinearLayout> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:orientation="horizontal" - android:layout_weight="1" - > - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key7" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="7" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key8" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="8" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key9" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="9" - /> - </LinearLayout> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - android:orientation="horizontal" - > - <Space - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - /> - <view class="com.android.keyguard.NumPadKey" - android:id="@+id/key0" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - androidprv:textView="@+id/pukEntry" - androidprv:digit="0" - /> - <ImageButton - android:id="@+id/key_enter" - style="@style/Widget.Button.NumPadKey.Sim" - android:layout_width="0px" - android:layout_height="match_parent" - android:layout_weight="1" - android:paddingRight="30dp" - android:src="@drawable/sym_keyboard_return_holo" - android:contentDescription="@string/keyboardview_keycode_enter" - /> - </LinearLayout> + android:id="@+id/keyguard_bouncer_frame" + android:layout_width="match_parent" + android:layout_height="0dp" + android:orientation="vertical" + android:layout_weight="1" + android:layoutDirection="ltr" + > + <RelativeLayout + android:id="@+id/row0" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:paddingBottom="16dp" + > + <com.android.keyguard.PasswordTextView + android:id="@+id/pukEntry" + android:layout_width="@dimen/keyguard_security_width" + android:layout_height="match_parent" + android:gravity="center" + android:layout_centerHorizontal="true" + android:layout_marginRight="72dp" + androidprv:scaledTextSize="28" + /> + <ImageButton + android:id="@+id/delete_button" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:gravity="center_vertical" + android:src="@drawable/ic_backspace_24dp" + android:clickable="true" + android:paddingTop="8dip" + android:paddingBottom="8dip" + android:paddingRight="8dp" + android:paddingLeft="24dp" + android:background="@drawable/ripple_drawable" + android:contentDescription="@string/keyboardview_keycode_delete" + android:layout_alignEnd="@+id/pinEntry" + android:layout_alignParentRight="true" + /> + <View + android:id="@+id/divider" + android:layout_width="match_parent" + android:layout_height="1dp" + android:layout_alignParentBottom="true" + android:background="#28FFFFFF" + /> + </RelativeLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="horizontal" + > + <com.android.keyguard.NumPadKey + android:id="@+id/key1" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="1" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key2" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="2" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key3" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="3" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="horizontal" + > + <com.android.keyguard.NumPadKey + android:id="@+id/key4" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="4" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key5" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="5" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key6" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="6" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:orientation="horizontal" + android:layout_weight="1" + > + <com.android.keyguard.NumPadKey + android:id="@+id/key7" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="7" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key8" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="8" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key9" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="9" + /> + </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:orientation="horizontal" + > + <Space + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + /> + <com.android.keyguard.NumPadKey + android:id="@+id/key0" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + androidprv:textView="@+id/pukEntry" + androidprv:digit="0" + /> + <ImageButton + android:id="@+id/key_enter" + android:layout_width="0px" + android:layout_height="match_parent" + android:layout_weight="1" + android:paddingBottom="11sp" + android:src="@drawable/ic_done_wht" + android:background="@drawable/ripple_drawable" + android:contentDescription="@string/keyboardview_keycode_enter" + /> + </LinearLayout> </LinearLayout> <include layout="@layout/keyguard_eca" - android:id="@+id/keyguard_selector_fade_container" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="vertical" - android:layout_gravity="bottom|center_horizontal" - android:gravity="center_horizontal" /> + android:id="@+id/keyguard_selector_fade_container" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:layout_gravity="bottom|center_horizontal" + android:gravity="center_horizontal"/> </com.android.keyguard.KeyguardSimPukView> diff --git a/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout/keyguard_simple_host_view.xml index ed600b0..4336e1c 100644 --- a/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml +++ b/packages/Keyguard/res/layout/keyguard_simple_host_view.xml @@ -29,7 +29,8 @@ <com.android.keyguard.KeyguardSecurityContainer android:id="@+id/keyguard_security_container" android:layout_width="wrap_content" - android:layout_height="@dimen/keyguard_security_height" + android:layout_height="wrap_content" + androidprv:layout_maxHeight="@dimen/keyguard_security_max_height" android:clipChildren="false" android:clipToPadding="false" android:padding="0dp" diff --git a/packages/Keyguard/res/values/arrays.xml b/packages/Keyguard/res/values/arrays.xml index 550f80c..291f776 100644 --- a/packages/Keyguard/res/values/arrays.xml +++ b/packages/Keyguard/res/values/arrays.xml @@ -79,7 +79,7 @@ <!-- list of 3- or 4-letter mnemonics for a 10-key numeric keypad --> <string-array translatable="false" name="lockscreen_num_pad_klondike"> - <item></item><!-- 0 --> + <item>+</item><!-- 0 --> <item></item><!-- 1 --> <item>ABC</item><!-- 2 --> <item>DEF</item><!-- 3 --> diff --git a/packages/Keyguard/res/values/attrs.xml b/packages/Keyguard/res/values/attrs.xml index 2410b6a..9100140 100644 --- a/packages/Keyguard/res/values/attrs.xml +++ b/packages/Keyguard/res/values/attrs.xml @@ -134,6 +134,10 @@ <attr name="textView" format="reference" /> </declare-styleable> + <declare-styleable name="PasswordTextView"> + <attr name="scaledTextSize" format="integer" /> + </declare-styleable> + <declare-styleable name="CarrierText"> <attr name="allCaps" format="boolean" /> </declare-styleable> diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml index 4b113ff..375cf32 100644 --- a/packages/Keyguard/res/values/dimens.xml +++ b/packages/Keyguard/res/values/dimens.xml @@ -119,6 +119,9 @@ <!-- Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> <dimen name="keyguard_security_height">400dp</dimen> + <!-- Max Height of the sliding KeyguardSecurityContainer (includes 2x keyguard_security_view_margin) --> + <dimen name="keyguard_security_max_height">460dp</dimen> + <!-- Margin around the various security views --> <dimen name="keyguard_security_view_margin">8dp</dimen> @@ -164,6 +167,12 @@ <!-- The y translation to apply at the start in appear animations. --> <dimen name="appear_y_translation_start">32dp</dimen> + <!-- The size of the dots in the PIN unlock method. --> + <dimen name="password_dot_size">9dp</dimen> + + <!-- The padding between chars of the password view. --> + <dimen name="password_char_padding">8dp</dimen> + <!-- The vertical margin between the date and the owner info. --> <dimen name="date_owner_info_margin">10dp</dimen> </resources> diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml index 11142cf..cdd6489 100644 --- a/packages/Keyguard/res/values/styles.xml +++ b/packages/Keyguard/res/values/styles.xml @@ -19,36 +19,20 @@ <resources> <!-- Keyguard PIN pad styles --> - <style name="Widget.Button.NumPadKey" - parent="@android:style/Widget.Button"> + <style name="Widget.TextView.NumPadKey" parent="@android:style/Widget.TextView"> <item name="android:singleLine">true</item> - <item name="android:gravity">left|center_vertical</item> - <item name="android:background">?android:attr/selectableItemBackground</item> - <item name="android:textSize">34dp</item> - <item name="android:fontFamily">sans-serif</item> - <item name="android:textStyle">normal</item> - <item name="android:textColor">#ffffff</item> - <item name="android:paddingTop">6dp</item> - <item name="android:paddingBottom">8dp</item> - <item name="android:paddingLeft">20dp</item> - <item name="android:paddingRight">6dp</item> - </style> - <style name="Widget.Button.NumPadKey.Sim" > - <item name="android:paddingTop">3dp</item> - <item name="android:paddingBottom">4dp</item> + <item name="android:gravity">center_horizontal|center_vertical</item> + <item name="android:background">@null</item> + <item name="android:textSize">36sp</item> + <item name="android:fontFamily">sans-serif-light</item> + <item name="android:textColor">#ffffffff</item> + <item name="android:paddingBottom">-16dp</item> </style> - <style name="TextAppearance.NumPadKey" - parent="@android:style/TextAppearance"> - <item name="android:textSize">34dp</item> + <style name="Widget.TextView.NumPadKey.Klondike" parent="Widget.TextView.NumPadKey"> + <item name="android:textSize">12sp</item> <item name="android:fontFamily">sans-serif</item> - <item name="android:textStyle">normal</item> - <item name="android:textColor">#ffffff</item> - </style> - <style name="TextAppearance.NumPadKey.Klondike"> - <item name="android:textSize">20dp</item> - <item name="android:fontFamily">sans-serif-condensed</item> - <item name="android:textStyle">normal</item> <item name="android:textColor">#80ffffff</item> + <item name="android:paddingBottom">0dp</item> </style> <!-- Standard animations for a non-full-screen window or activity. --> diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java index aae92e8..c49c318 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java @@ -17,12 +17,9 @@ package com.android.keyguard; import android.content.Context; -import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.CountDownTimer; import android.os.SystemClock; -import android.text.Editable; -import android.text.TextWatcher; import android.util.AttributeSet; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; @@ -38,9 +35,8 @@ import com.android.internal.widget.LockPatternUtils; * Base class for PIN and password unlock screens. */ public abstract class KeyguardAbsKeyInputView extends LinearLayout - implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { + implements KeyguardSecurityView { protected KeyguardSecurityCallback mCallback; - protected TextView mPasswordEntry; protected LockPatternUtils mLockPatternUtils; protected SecurityMessageDisplay mSecurityMessageDisplay; protected View mEcaView; @@ -70,9 +66,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout public void reset() { // start fresh - mPasswordEntry.setText(""); - mPasswordEntry.requestFocus(); - + resetPasswordText(false /* animate */); // if the user is currently locked out, enforce it. long deadline = mLockPatternUtils.getLockoutAttemptDeadline(); if (shouldLockout(deadline)) { @@ -93,34 +87,6 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout @Override protected void onFinishInflate() { mLockPatternUtils = new LockPatternUtils(mContext); - - mPasswordEntry = (TextView) findViewById(getPasswordTextViewId()); - mPasswordEntry.setOnEditorActionListener(this); - mPasswordEntry.addTextChangedListener(this); - - // Set selected property on so the view can send accessibility events. - mPasswordEntry.setSelected(true); - - // Poke the wakelock any time the text is selected or modified - mPasswordEntry.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - mCallback.userActivity(0); // TODO: customize timeout for text? - } - }); - - mPasswordEntry.addTextChangedListener(new TextWatcher() { - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - public void afterTextChanged(Editable s) { - if (mCallback != null) { - mCallback.userActivity(0); - } - } - }); mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this); mEcaView = findViewById(R.id.keyguard_selector_fade_container); View bouncerFrameView = findViewById(R.id.keyguard_bouncer_frame); @@ -129,12 +95,6 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout } } - @Override - protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { - // send focus to the password field - return mPasswordEntry.requestFocus(direction, previouslyFocusedRect); - } - /* * Override this if you have a different string for "wrong password" * @@ -145,7 +105,7 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout } protected void verifyPasswordAndUnlock() { - String entry = mPasswordEntry.getText().toString(); + String entry = getPasswordText(); if (mLockPatternUtils.checkPassword(entry)) { mCallback.reportUnlockAttempt(true); mCallback.dismiss(true); @@ -162,12 +122,16 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout } mSecurityMessageDisplay.setMessage(getWrongPasswordStringId(), true); } - mPasswordEntry.setText(""); + resetPasswordText(true /* animate */); } + protected abstract void resetPasswordText(boolean animate); + protected abstract String getPasswordText(); + protected abstract void setPasswordEntryEnabled(boolean enabled); + // Prevent user from using the PIN/Password entry until scheduled deadline. protected void handleAttemptLockout(long elapsedRealtimeDeadline) { - mPasswordEntry.setEnabled(false); + setPasswordEntryEnabled(false); long elapsedRealtime = SystemClock.elapsedRealtime(); new CountDownTimer(elapsedRealtimeDeadline - elapsedRealtime, 1000) { @@ -193,17 +157,6 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout } @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - // Check if this was the result of hitting the enter key - if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE - || actionId == EditorInfo.IME_ACTION_NEXT) { - verifyPasswordAndUnlock(); - return true; - } - return false; - } - - @Override public boolean needsInput() { return false; } @@ -223,21 +176,6 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout return mCallback; } - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - if (mCallback != null) { - mCallback.userActivity(KeyguardConstants.DIGIT_PRESS_WAKE_MILLIS); - } - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - } - // Cause a VIRTUAL_KEY vibration public void doHapticKeyClick() { if (mEnableHaptics) { diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java index 1f3c176..ec5d040eb 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPINView.java @@ -28,8 +28,7 @@ import android.widget.TextView.OnEditorActionListener; /** * Displays a PIN pad for unlocking. */ -public class KeyguardPINView extends KeyguardAbsKeyInputView - implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { +public class KeyguardPINView extends KeyguardPinBasedInputView { private final AppearAnimationUtils mAppearAnimationUtils; private ViewGroup mKeyguardBouncerFrame; @@ -49,12 +48,12 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView } protected void resetState() { + super.resetState(); if (KeyguardUpdateMonitor.getInstance(mContext).getMaxBiometricUnlockAttemptsReached()) { mSecurityMessageDisplay.setMessage(R.string.faceunlock_multiple_failures, true); } else { mSecurityMessageDisplay.setMessage(R.string.kg_pin_instructions, false); } - mPasswordEntry.setEnabled(true); } @Override @@ -72,54 +71,6 @@ public class KeyguardPINView extends KeyguardAbsKeyInputView mRow2 = (ViewGroup) findViewById(R.id.row2); mRow3 = (ViewGroup) findViewById(R.id.row3); mDivider = findViewById(R.id.divider); - final View ok = findViewById(R.id.key_enter); - if (ok != null) { - ok.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - doHapticKeyClick(); - if (mPasswordEntry.isEnabled()) { - verifyPasswordAndUnlock(); - } - } - }); - ok.setOnHoverListener(new LiftToActivateListener(getContext())); - } - - // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts, - // not a separate view - View pinDelete = findViewById(R.id.delete_button); - if (pinDelete != null) { - pinDelete.setVisibility(View.VISIBLE); - pinDelete.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - // check for time-based lockouts - if (mPasswordEntry.isEnabled()) { - CharSequence str = mPasswordEntry.getText(); - if (str.length() > 0) { - mPasswordEntry.setText(str.subSequence(0, str.length()-1)); - } - } - doHapticKeyClick(); - } - }); - pinDelete.setOnLongClickListener(new View.OnLongClickListener() { - public boolean onLongClick(View v) { - // check for time-based lockouts - if (mPasswordEntry.isEnabled()) { - mPasswordEntry.setText(""); - } - doHapticKeyClick(); - return true; - } - }); - } - - mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance()); - mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER - | InputType.TYPE_NUMBER_VARIATION_PASSWORD); - - mPasswordEntry.requestFocus(); } @Override diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java index 0c385da..9f820f8 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPasswordView.java @@ -17,15 +17,19 @@ package com.android.keyguard; import android.content.Context; +import android.graphics.Rect; import android.text.Editable; import android.text.InputType; import android.text.TextWatcher; import android.text.method.TextKeyListener; import android.util.AttributeSet; +import android.view.KeyEvent; import android.view.View; +import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; +import android.widget.TextView; import android.widget.TextView.OnEditorActionListener; import java.util.List; @@ -40,6 +44,7 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView private final boolean mShowImeAtScreenOn; InputMethodManager mImm; + private TextView mPasswordEntry; public KeyguardPasswordView(Context context) { this(context, null); @@ -82,6 +87,12 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView } @Override + public void reset() { + super.reset(); + mPasswordEntry.requestFocus(); + } + + @Override protected void onFinishInflate() { super.onFinishInflate(); @@ -90,9 +101,12 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView mImm = (InputMethodManager) getContext().getSystemService( Context.INPUT_METHOD_SERVICE); + mPasswordEntry = (TextView) findViewById(getPasswordTextViewId()); mPasswordEntry.setKeyListener(TextKeyListener.getInstance()); mPasswordEntry.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); + mPasswordEntry.setOnEditorActionListener(this); + mPasswordEntry.addTextChangedListener(this); // Poke the wakelock any time the text is selected or modified mPasswordEntry.setOnClickListener(new OnClickListener() { @@ -101,6 +115,9 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView } }); + // Set selected property on so the view can send accessibility events. + mPasswordEntry.setSelected(true); + mPasswordEntry.addTextChangedListener(new TextWatcher() { public void onTextChanged(CharSequence s, int start, int before, int count) { } @@ -142,6 +159,27 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView } } + @Override + protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { + // send focus to the password field + return mPasswordEntry.requestFocus(direction, previouslyFocusedRect); + } + + @Override + protected void resetPasswordText(boolean animate) { + mPasswordEntry.setText(""); + } + + @Override + protected String getPasswordText() { + return mPasswordEntry.getText().toString(); + } + + @Override + protected void setPasswordEntryEnabled(boolean enabled) { + mPasswordEntry.setEnabled(enabled); + } + /** * Method adapted from com.android.inputmethod.latin.Utils * @@ -205,4 +243,30 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView setAlpha(0); animate().alpha(1).withLayer().setDuration(200); } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (mCallback != null) { + mCallback.userActivity(KeyguardConstants.DIGIT_PRESS_WAKE_MILLIS); + } + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + } + + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + // Check if this was the result of hitting the enter key + if (actionId == EditorInfo.IME_NULL || actionId == EditorInfo.IME_ACTION_DONE + || actionId == EditorInfo.IME_ACTION_NEXT) { + verifyPasswordAndUnlock(); + return true; + } + return false; + } } diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java new file mode 100644 index 0000000..1ef873f --- /dev/null +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPinBasedInputView.java @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2014 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.keyguard; + +import android.content.Context; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.view.KeyEvent; +import android.view.View; + +/** + * A Pin based Keyguard input view + */ +public abstract class KeyguardPinBasedInputView extends KeyguardAbsKeyInputView + implements View.OnKeyListener { + + protected PasswordTextView mPasswordEntry; + private View mOkButton; + private View mDeleteButton; + private View mButton0; + private View mButton1; + private View mButton2; + private View mButton3; + private View mButton4; + private View mButton5; + private View mButton6; + private View mButton7; + private View mButton8; + private View mButton9; + + public KeyguardPinBasedInputView(Context context) { + this(context, null); + } + + public KeyguardPinBasedInputView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public void reset() { + mPasswordEntry.requestFocus(); + super.reset(); + } + + @Override + protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) { + // send focus to the password field + return mPasswordEntry.requestFocus(direction, previouslyFocusedRect); + } + + protected void resetState() { + mPasswordEntry.setEnabled(true); + } + + @Override + protected void setPasswordEntryEnabled(boolean enabled) { + mPasswordEntry.setEnabled(enabled); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (KeyEvent.isConfirmKey(keyCode)) { + performClick(mOkButton); + return true; + } else if (keyCode == KeyEvent.KEYCODE_DEL) { + performClick(mDeleteButton); + return true; + } + if (keyCode >= KeyEvent.KEYCODE_0 && keyCode <= KeyEvent.KEYCODE_9) { + int number = keyCode - KeyEvent.KEYCODE_0 ; + performNumberClick(number); + return true; + } + return super.onKeyDown(keyCode, event); + } + + private void performClick(View view) { + view.performClick(); + } + + private void performNumberClick(int number) { + switch (number) { + case 0: + performClick(mButton0); + break; + case 1: + performClick(mButton1); + break; + case 2: + performClick(mButton2); + break; + case 3: + performClick(mButton3); + break; + case 4: + performClick(mButton4); + break; + case 5: + performClick(mButton5); + break; + case 6: + performClick(mButton6); + break; + case 7: + performClick(mButton7); + break; + case 8: + performClick(mButton8); + break; + case 9: + performClick(mButton9); + break; + } + } + + @Override + protected void resetPasswordText(boolean animate) { + mPasswordEntry.reset(animate); + } + + @Override + protected String getPasswordText() { + return mPasswordEntry.getText(); + } + + @Override + protected void onFinishInflate() { + mPasswordEntry = (PasswordTextView) findViewById(getPasswordTextViewId()); + mPasswordEntry.setOnKeyListener(this); + + // Set selected property on so the view can send accessibility events. + mPasswordEntry.setSelected(true); + + // Poke the wakelock any time the text is selected or modified + mPasswordEntry.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + mCallback.userActivity(0); // TODO: customize timeout for text? + } + }); + + mOkButton = findViewById(R.id.key_enter); + if (mOkButton != null) { + mOkButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + doHapticKeyClick(); + if (mPasswordEntry.isEnabled()) { + verifyPasswordAndUnlock(); + } + } + }); + mOkButton.setOnHoverListener(new LiftToActivateListener(getContext())); + } + + mDeleteButton = findViewById(R.id.delete_button); + if (mDeleteButton != null) { + mDeleteButton.setVisibility(View.VISIBLE); + mDeleteButton.setOnClickListener(new OnClickListener() { + public void onClick(View v) { + // check for time-based lockouts + if (mPasswordEntry.isEnabled()) { + mPasswordEntry.deleteLastChar(); + } + doHapticKeyClick(); + } + }); + mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() { + public boolean onLongClick(View v) { + // check for time-based lockouts + if (mPasswordEntry.isEnabled()) { + resetPasswordText(true /* animate */); + } + doHapticKeyClick(); + return true; + } + }); + } + mButton0 = findViewById(R.id.key0); + mButton1 = findViewById(R.id.key1); + mButton2 = findViewById(R.id.key2); + mButton3 = findViewById(R.id.key3); + mButton4 = findViewById(R.id.key4); + mButton5 = findViewById(R.id.key5); + mButton6 = findViewById(R.id.key6); + mButton7 = findViewById(R.id.key7); + mButton8 = findViewById(R.id.key8); + mButton9 = findViewById(R.id.key9); + + mPasswordEntry.requestFocus(); + super.onFinishInflate(); + } + + @Override + public boolean onKey(View v, int keyCode, KeyEvent event) { + if (event.getAction() == KeyEvent.ACTION_DOWN) { + onKeyDown(keyCode, event); + return true; + } + return false; + } +} diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java index 09c4e7c..cc90bcb 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java @@ -38,8 +38,7 @@ import android.widget.TextView.OnEditorActionListener; /** * Displays a PIN pad for unlocking. */ -public class KeyguardSimPinView extends KeyguardAbsKeyInputView - implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { +public class KeyguardSimPinView extends KeyguardPinBasedInputView { private static final String LOG_TAG = "KeyguardSimPinView"; private static final boolean DEBUG = KeyguardConstants.DEBUG; public static final String TAG = "KeyguardSimPinView"; @@ -58,8 +57,8 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView } public void resetState() { + super.resetState(); mSecurityMessageDisplay.setMessage(R.string.kg_sim_pin_instructions, true); - mPasswordEntry.setEnabled(true); } private String getPinPasswordErrorMessage(int attemptsRemaining) { @@ -94,46 +93,6 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView protected void onFinishInflate() { super.onFinishInflate(); - final View ok = findViewById(R.id.key_enter); - if (ok != null) { - ok.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - doHapticKeyClick(); - verifyPasswordAndUnlock(); - } - }); - } - - // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts, - // not a separate view - View pinDelete = findViewById(R.id.delete_button); - if (pinDelete != null) { - pinDelete.setVisibility(View.VISIBLE); - pinDelete.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - CharSequence str = mPasswordEntry.getText(); - if (str.length() > 0) { - mPasswordEntry.setText(str.subSequence(0, str.length()-1)); - } - doHapticKeyClick(); - } - }); - pinDelete.setOnLongClickListener(new View.OnLongClickListener() { - public boolean onLongClick(View v) { - mPasswordEntry.setText(""); - doHapticKeyClick(); - return true; - } - }); - } - - mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance()); - mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER - | InputType.TYPE_NUMBER_VARIATION_PASSWORD); - - mPasswordEntry.requestFocus(); - mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default if (mEcaView instanceof EmergencyCarrierArea) { ((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true); @@ -220,12 +179,12 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView @Override protected void verifyPasswordAndUnlock() { - String entry = mPasswordEntry.getText().toString(); + String entry = mPasswordEntry.getText(); if (entry.length() < 4) { // otherwise, display a message to the user, and don't submit. mSecurityMessageDisplay.setMessage(R.string.kg_invalid_sim_pin_hint, true); - mPasswordEntry.setText(""); + resetPasswordText(true); mCallback.userActivity(0); return; } @@ -233,7 +192,7 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView getSimUnlockProgressDialog().show(); if (mCheckSimPinThread == null) { - mCheckSimPinThread = new CheckSimPin(mPasswordEntry.getText().toString()) { + mCheckSimPinThread = new CheckSimPin(mPasswordEntry.getText()) { void onSimCheckResponse(final int result, final int attemptsRemaining) { post(new Runnable() { public void run() { @@ -262,7 +221,7 @@ public class KeyguardSimPinView extends KeyguardAbsKeyInputView if (DEBUG) Log.d(LOG_TAG, "verifyPasswordAndUnlock " + " CheckSimPin.onSimCheckResponse: " + result + " attemptsRemaining=" + attemptsRemaining); - mPasswordEntry.setText(""); + resetPasswordText(true /* animate */); } mCallback.userActivity(0); mCheckSimPinThread = null; diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java index 6215d34..b956e99 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java @@ -39,8 +39,7 @@ import com.android.internal.telephony.PhoneConstants; /** * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier. */ -public class KeyguardSimPukView extends KeyguardAbsKeyInputView - implements KeyguardSecurityView, OnEditorActionListener, TextWatcher { +public class KeyguardSimPukView extends KeyguardPinBasedInputView { private static final String LOG_TAG = "KeyguardSimPukView"; private static final boolean DEBUG = KeyguardConstants.DEBUG; public static final String TAG = "KeyguardSimPukView"; @@ -85,7 +84,7 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView msg = R.string.kg_invalid_confirm_pin_hint; } } - mPasswordEntry.setText(null); + resetPasswordText(true); if (msg != 0) { mSecurityMessageDisplay.setMessage(msg, true); } @@ -126,8 +125,8 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView } public void resetState() { + super.resetState(); mStateMachine.reset(); - mPasswordEntry.setEnabled(true); } @Override @@ -145,46 +144,6 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView protected void onFinishInflate() { super.onFinishInflate(); - final View ok = findViewById(R.id.key_enter); - if (ok != null) { - ok.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - doHapticKeyClick(); - verifyPasswordAndUnlock(); - } - }); - } - - // The delete button is of the PIN keyboard itself in some (e.g. tablet) layouts, - // not a separate view - View pinDelete = findViewById(R.id.delete_button); - if (pinDelete != null) { - pinDelete.setVisibility(View.VISIBLE); - pinDelete.setOnClickListener(new OnClickListener() { - public void onClick(View v) { - CharSequence str = mPasswordEntry.getText(); - if (str.length() > 0) { - mPasswordEntry.setText(str.subSequence(0, str.length()-1)); - } - doHapticKeyClick(); - } - }); - pinDelete.setOnLongClickListener(new View.OnLongClickListener() { - public boolean onLongClick(View v) { - mPasswordEntry.setText(""); - doHapticKeyClick(); - return true; - } - }); - } - - mPasswordEntry.setKeyListener(DigitsKeyListener.getInstance()); - mPasswordEntry.setInputType(InputType.TYPE_CLASS_NUMBER - | InputType.TYPE_NUMBER_VARIATION_PASSWORD); - - mPasswordEntry.requestFocus(); - mSecurityMessageDisplay.setTimeout(0); // don't show ownerinfo/charging status by default if (mEcaView instanceof EmergencyCarrierArea) { ((EmergencyCarrierArea) mEcaView).setCarrierTextVisible(true); @@ -276,7 +235,7 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView private boolean checkPuk() { // make sure the puk is at least 8 digits long. if (mPasswordEntry.getText().length() == 8) { - mPukText = mPasswordEntry.getText().toString(); + mPukText = mPasswordEntry.getText(); return true; } return false; @@ -286,14 +245,14 @@ public class KeyguardSimPukView extends KeyguardAbsKeyInputView // make sure the PIN is between 4 and 8 digits int length = mPasswordEntry.getText().length(); if (length >= 4 && length <= 8) { - mPinText = mPasswordEntry.getText().toString(); + mPinText = mPasswordEntry.getText(); return true; } return false; } public boolean confirmPin() { - return mPinText.equals(mPasswordEntry.getText().toString()); + return mPinText.equals(mPasswordEntry.getText()); } private void updateSim() { diff --git a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java index 532670f..2d20b02 100644 --- a/packages/Keyguard/src/com/android/keyguard/NumPadKey.java +++ b/packages/Keyguard/src/com/android/keyguard/NumPadKey.java @@ -18,44 +18,54 @@ package com.android.keyguard; import android.content.Context; import android.content.res.TypedArray; -import android.text.SpannableStringBuilder; -import android.text.style.TextAppearanceSpan; +import android.graphics.drawable.Drawable; +import android.os.Debug; +import android.os.PowerManager; +import android.os.SystemClock; import android.util.AttributeSet; import android.view.HapticFeedbackConstants; +import android.view.KeyEvent; +import android.view.LayoutInflater; import android.view.View; -import android.widget.Button; +import android.view.ViewGroup; +import android.view.accessibility.AccessibilityEvent; import android.widget.TextView; import com.android.internal.widget.LockPatternUtils; -public class NumPadKey extends Button { +public class NumPadKey extends ViewGroup { // list of "ABC", etc per digit, starting with '0' static String sKlondike[]; - int mDigit = -1; - int mTextViewResId; - TextView mTextView = null; - boolean mEnableHaptics; + private int mDigit = -1; + private int mTextViewResId; + private PasswordTextView mTextView; + private TextView mDigitText; + private TextView mKlondikeText; + private boolean mEnableHaptics; + private PowerManager mPM; private View.OnClickListener mListener = new View.OnClickListener() { @Override public void onClick(View thisView) { - if (mTextView == null) { - if (mTextViewResId > 0) { - final View v = NumPadKey.this.getRootView().findViewById(mTextViewResId); - if (v != null && v instanceof TextView) { - mTextView = (TextView) v; - } + if (mTextView == null && mTextViewResId > 0) { + final View v = NumPadKey.this.getRootView().findViewById(mTextViewResId); + if (v != null && v instanceof PasswordTextView) { + mTextView = (PasswordTextView) v; } } - // check for time-based lockouts if (mTextView != null && mTextView.isEnabled()) { - mTextView.append(String.valueOf(mDigit)); + mTextView.append(Character.forDigit(mDigit, 10)); } + userActivity(); doHapticKeyClick(); } }; + public void userActivity() { + mPM.userActivity(SystemClock.uptimeMillis(), false); + } + public NumPadKey(Context context) { this(context, null); } @@ -66,10 +76,16 @@ public class NumPadKey extends Button { public NumPadKey(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + setFocusable(true); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NumPadKey); - mDigit = a.getInt(R.styleable.NumPadKey_digit, mDigit); - setTextViewResId(a.getResourceId(R.styleable.NumPadKey_textView, 0)); + + try { + mDigit = a.getInt(R.styleable.NumPadKey_digit, mDigit); + mTextViewResId = a.getResourceId(R.styleable.NumPadKey_textView, 0); + } finally { + a.recycle(); + } setOnClickListener(mListener); setOnHoverListener(new LiftToActivateListener(context)); @@ -77,26 +93,32 @@ public class NumPadKey extends Button { mEnableHaptics = new LockPatternUtils(context).isTactileFeedbackEnabled(); - SpannableStringBuilder builder = new SpannableStringBuilder(); - builder.append(String.valueOf(mDigit)); + mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + inflater.inflate(R.layout.keyguard_num_pad_key, this, true); + + mDigitText = (TextView) findViewById(R.id.digit_text); + mDigitText.setText(Integer.toString(mDigit)); + mKlondikeText = (TextView) findViewById(R.id.klondike_text); + if (mDigit >= 0) { if (sKlondike == null) { - sKlondike = context.getResources().getStringArray( - R.array.lockscreen_num_pad_klondike); + sKlondike = getResources().getStringArray(R.array.lockscreen_num_pad_klondike); } if (sKlondike != null && sKlondike.length > mDigit) { - final String extra = sKlondike[mDigit]; - final int extraLen = extra.length(); - if (extraLen > 0) { - builder.append(" "); - builder.append(extra); - builder.setSpan( - new TextAppearanceSpan(context, R.style.TextAppearance_NumPadKey_Klondike), - builder.length()-extraLen, builder.length(), 0); + String klondike = sKlondike[mDigit]; + final int len = klondike.length(); + if (len > 0) { + mKlondikeText.setText(klondike); + } else { + mKlondikeText.setVisibility(View.INVISIBLE); } } } - setText(builder); + + setBackground(mContext.getDrawable(R.drawable.ripple_drawable)); + setContentDescription(mDigitText.getText().toString() + mKlondikeText.getText().toString()); } @Override @@ -107,13 +129,27 @@ public class NumPadKey extends Button { ObscureSpeechDelegate.sAnnouncedHeadset = false; } - public void setTextView(TextView tv) { - mTextView = tv; + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + measureChildren(widthMeasureSpec, heightMeasureSpec); } - public void setTextViewResId(int resId) { - mTextView = null; - mTextViewResId = resId; + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + int digitHeight = mDigitText.getMeasuredHeight(); + int klondikeHeight = mKlondikeText.getMeasuredHeight(); + int totalHeight = digitHeight + klondikeHeight; + int top = getHeight() / 2 - totalHeight / 2; + int centerX = getWidth() / 2; + int left = centerX - mDigitText.getMeasuredWidth() / 2; + int bottom = top + digitHeight; + mDigitText.layout(left, top, left + mDigitText.getMeasuredWidth(), bottom); + top = (int) (bottom - klondikeHeight * 0.35f); + bottom = top + klondikeHeight; + + left = centerX - mKlondikeText.getMeasuredWidth() / 2; + mKlondikeText.layout(left, top, left + mKlondikeText.getMeasuredWidth(), bottom); } // Cause a VIRTUAL_KEY vibration diff --git a/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java new file mode 100644 index 0000000..f3ba3a7 --- /dev/null +++ b/packages/Keyguard/src/com/android/keyguard/PasswordTextView.java @@ -0,0 +1,590 @@ +/* + * Copyright (C) 2014 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.keyguard; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.os.PowerManager; +import android.os.SystemClock; +import android.provider.Settings; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; + +import java.util.ArrayList; +import java.util.Stack; + +/** + * A View similar to a textView which contains password text and can animate when the text is + * changed + */ +public class PasswordTextView extends View { + + private static final float DOT_OVERSHOOT_FACTOR = 1.5f; + private static final long DOT_APPEAR_DURATION_OVERSHOOT = 320; + private static final long APPEAR_DURATION = 160; + private static final long DISAPPEAR_DURATION = 160; + private static final long RESET_DELAY_PER_ELEMENT = 40; + private static final long RESET_MAX_DELAY = 200; + + /** + * The overlap between the text disappearing and the dot appearing animation + */ + private static final long DOT_APPEAR_TEXT_DISAPPEAR_OVERLAP_DURATION = 130; + + /** + * The duration the text needs to stay there at least before it can morph into a dot + */ + private static final long TEXT_REST_DURATION_AFTER_APPEAR = 100; + + /** + * The duration the text should be visible, starting with the appear animation + */ + private static final long TEXT_VISIBILITY_DURATION = 1300; + + /** + * The position in time from [0,1] where the overshoot should be finished and the settle back + * animation of the dot should start + */ + private static final float OVERSHOOT_TIME_POSITION = 0.5f; + + /** + * The raw text size, will be multiplied by the scaled density when drawn + */ + private final int mTextHeightRaw; + private ArrayList<CharState> mTextChars = new ArrayList<>(); + private String mText = ""; + private Stack<CharState> mCharPool = new Stack<>(); + private int mDotSize; + private PowerManager mPM; + private int mCharPadding; + private final Paint mDrawPaint = new Paint(); + private Interpolator mAppearInterpolator; + private Interpolator mDisappearInterpolator; + private Interpolator mFastOutSlowInInterpolator; + private boolean mShowPassword; + + public PasswordTextView(Context context) { + this(context, null); + } + + public PasswordTextView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PasswordTextView(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs, defStyleAttr, 0); + } + + public PasswordTextView(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + setFocusableInTouchMode(true); + setFocusable(true); + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PasswordTextView); + try { + mTextHeightRaw = a.getInt(R.styleable.PasswordTextView_scaledTextSize, 0); + } finally { + a.recycle(); + } + mDrawPaint.setFlags(Paint.SUBPIXEL_TEXT_FLAG | Paint.ANTI_ALIAS_FLAG); + mDrawPaint.setTextAlign(Paint.Align.CENTER); + mDrawPaint.setColor(0xffffffff); + mDrawPaint.setTypeface(Typeface.create("sans-serif-light", 0)); + mDotSize = getContext().getResources().getDimensionPixelSize(R.dimen.password_dot_size); + mCharPadding = getContext().getResources().getDimensionPixelSize(R.dimen + .password_char_padding); + mShowPassword = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.TEXT_SHOW_PASSWORD, 1) == 1; + mAppearInterpolator = AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.linear_out_slow_in); + mDisappearInterpolator = AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.fast_out_linear_in); + mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(mContext, + android.R.interpolator.fast_out_slow_in); + mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + } + + @Override + protected void onDraw(Canvas canvas) { + float totalDrawingWidth = getDrawingWidth(); + float currentDrawPosition = getWidth() / 2 - totalDrawingWidth / 2; + int length = mTextChars.size(); + Rect bounds = getCharBounds(); + int charHeight = (bounds.bottom - bounds.top); + float yPosition = getHeight() / 2; + float charLength = bounds.right - bounds.left; + for (int i = 0; i < length; i++) { + CharState charState = mTextChars.get(i); + float charWidth = charState.draw(canvas, currentDrawPosition, charHeight, yPosition, + charLength); + currentDrawPosition += charWidth; + } + } + + private Rect getCharBounds() { + float textHeight = mTextHeightRaw * getResources().getDisplayMetrics().scaledDensity; + mDrawPaint.setTextSize(textHeight); + Rect bounds = new Rect(); + mDrawPaint.getTextBounds("0", 0, 1, bounds); + return bounds; + } + + private float getDrawingWidth() { + int width = 0; + int length = mTextChars.size(); + Rect bounds = getCharBounds(); + int charLength = bounds.right - bounds.left; + for (int i = 0; i < length; i++) { + CharState charState = mTextChars.get(i); + if (i != 0) { + width += mCharPadding * charState.currentWidthFactor; + } + width += charLength * charState.currentWidthFactor; + } + return width; + } + + + public void append(char c) { + int visibleChars = mTextChars.size(); + mText = mText + c; + int newLength = mText.length(); + CharState charState; + if (newLength > visibleChars) { + charState = obtainCharState(c); + mTextChars.add(charState); + } else { + charState = mTextChars.get(newLength - 1); + charState.whichChar = c; + } + charState.startAppearAnimation(); + + // ensure that the previous element is being swapped + if (newLength > 1) { + CharState previousState = mTextChars.get(newLength - 2); + if (previousState.isDotSwapPending) { + previousState.swapToDotWhenAppearFinished(); + } + } + userActivity(); + } + + private void userActivity() { + mPM.userActivity(SystemClock.uptimeMillis(), false); + } + + public void deleteLastChar() { + int length = mText.length(); + if (length > 0) { + mText = mText.substring(0, length - 1); + CharState charState = mTextChars.get(length - 1); + charState.startRemoveAnimation(0, 0); + } + userActivity(); + } + + public String getText() { + return mText; + } + + private CharState obtainCharState(char c) { + CharState charState; + if(mCharPool.isEmpty()) { + charState = new CharState(); + } else { + charState = mCharPool.pop(); + charState.reset(); + } + charState.whichChar = c; + return charState; + } + + public void reset(boolean animated) { + mText = ""; + int length = mTextChars.size(); + int middleIndex = (length - 1) / 2; + long delayPerElement = RESET_DELAY_PER_ELEMENT; + for (int i = 0; i < length; i++) { + CharState charState = mTextChars.get(i); + if (animated) { + int delayIndex; + if (i <= middleIndex) { + delayIndex = i * 2; + } else { + int distToMiddle = i - middleIndex; + delayIndex = (length - 1) - (distToMiddle - 1) * 2; + } + long startDelay = delayIndex * delayPerElement; + startDelay = Math.min(startDelay, RESET_MAX_DELAY); + long maxDelay = delayPerElement * (length - 1); + maxDelay = Math.min(maxDelay, RESET_MAX_DELAY) + DISAPPEAR_DURATION; + charState.startRemoveAnimation(startDelay, maxDelay); + charState.removeDotSwapCallbacks(); + } else { + mCharPool.push(charState); + } + } + if (!animated) { + mTextChars.clear(); + } + } + + private class CharState { + char whichChar; + ValueAnimator textAnimator; + boolean textAnimationIsGrowing; + Animator dotAnimator; + boolean dotAnimationIsGrowing; + ValueAnimator widthAnimator; + boolean widthAnimationIsGrowing; + float currentTextSizeFactor; + float currentDotSizeFactor; + float currentWidthFactor; + boolean isDotSwapPending; + float currentTextTranslationY = 1.0f; + ValueAnimator textTranslateAnimator; + + Animator.AnimatorListener removeEndListener = new AnimatorListenerAdapter() { + private boolean mCancelled; + @Override + public void onAnimationCancel(Animator animation) { + mCancelled = true; + } + + @Override + public void onAnimationEnd(Animator animation) { + if (!mCancelled) { + mTextChars.remove(CharState.this); + mCharPool.push(CharState.this); + reset(); + cancelAnimator(textTranslateAnimator); + textTranslateAnimator = null; + } + } + + @Override + public void onAnimationStart(Animator animation) { + mCancelled = false; + } + }; + + Animator.AnimatorListener dotFinishListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + dotAnimator = null; + } + }; + + Animator.AnimatorListener textFinishListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + textAnimator = null; + } + }; + + Animator.AnimatorListener textTranslateFinishListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + textTranslateAnimator = null; + } + }; + + Animator.AnimatorListener widthFinishListener = new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + widthAnimator = null; + } + }; + + private ValueAnimator.AnimatorUpdateListener dotSizeUpdater + = new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + currentDotSizeFactor = (float) animation.getAnimatedValue(); + invalidate(); + } + }; + + private ValueAnimator.AnimatorUpdateListener textSizeUpdater + = new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + currentTextSizeFactor = (float) animation.getAnimatedValue(); + invalidate(); + } + }; + + private ValueAnimator.AnimatorUpdateListener textTranslationUpdater + = new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + currentTextTranslationY = (float) animation.getAnimatedValue(); + invalidate(); + } + }; + + private ValueAnimator.AnimatorUpdateListener widthUpdater + = new ValueAnimator.AnimatorUpdateListener() { + @Override + public void onAnimationUpdate(ValueAnimator animation) { + currentWidthFactor = (float) animation.getAnimatedValue(); + invalidate(); + } + }; + + private Runnable dotSwapperRunnable = new Runnable() { + @Override + public void run() { + performSwap(); + isDotSwapPending = false; + } + }; + + void reset() { + whichChar = 0; + currentTextSizeFactor = 0.0f; + currentDotSizeFactor = 0.0f; + currentWidthFactor = 0.0f; + cancelAnimator(textAnimator); + textAnimator = null; + cancelAnimator(dotAnimator); + dotAnimator = null; + cancelAnimator(widthAnimator); + widthAnimator = null; + currentTextTranslationY = 1.0f; + removeDotSwapCallbacks(); + } + + void startRemoveAnimation(long startDelay, long widthDelay) { + boolean dotNeedsAnimation = (currentDotSizeFactor > 0.0f && dotAnimator == null) + || (dotAnimator != null && dotAnimationIsGrowing); + boolean textNeedsAnimation = (currentTextSizeFactor > 0.0f && textAnimator == null) + || (textAnimator != null && textAnimationIsGrowing); + boolean widthNeedsAnimation = (currentWidthFactor > 0.0f && widthAnimator == null) + || (widthAnimator != null && widthAnimationIsGrowing); + if (dotNeedsAnimation) { + startDotDisappearAnimation(startDelay); + } + if (textNeedsAnimation) { + startTextDisappearAnimation(startDelay); + } + if (widthNeedsAnimation) { + startWidthDisappearAnimation(widthDelay); + } + } + + void startAppearAnimation() { + boolean dotNeedsAnimation = !mShowPassword + && (dotAnimator == null || !dotAnimationIsGrowing); + boolean textNeedsAnimation = mShowPassword + && (textAnimator == null || !textAnimationIsGrowing); + boolean widthNeedsAnimation = (widthAnimator == null || !widthAnimationIsGrowing); + if (dotNeedsAnimation) { + startDotAppearAnimation(0); + } + if (textNeedsAnimation) { + startTextAppearAnimation(); + } + if (widthNeedsAnimation) { + startWidthAppearAnimation(); + } + if (mShowPassword) { + postDotSwap(TEXT_VISIBILITY_DURATION); + } + } + + /** + * Posts a runnable which ensures that the text will be replaced by a dot after {@link + * com.android.keyguard.PasswordTextView#TEXT_VISIBILITY_DURATION}. + */ + private void postDotSwap(long delay) { + removeDotSwapCallbacks(); + postDelayed(dotSwapperRunnable, delay); + isDotSwapPending = true; + } + + private void removeDotSwapCallbacks() { + removeCallbacks(dotSwapperRunnable); + isDotSwapPending = false; + } + + void swapToDotWhenAppearFinished() { + removeDotSwapCallbacks(); + if (textAnimator != null) { + long remainingDuration = textAnimator.getDuration() + - textAnimator.getCurrentPlayTime(); + postDotSwap(remainingDuration + TEXT_REST_DURATION_AFTER_APPEAR); + } else { + performSwap(); + } + } + + private void performSwap() { + startTextDisappearAnimation(0); + startDotAppearAnimation(DISAPPEAR_DURATION + - DOT_APPEAR_TEXT_DISAPPEAR_OVERLAP_DURATION); + } + + private void startWidthDisappearAnimation(long widthDelay) { + cancelAnimator(widthAnimator); + widthAnimator = ValueAnimator.ofFloat(currentWidthFactor, 0.0f); + widthAnimator.addUpdateListener(widthUpdater); + widthAnimator.addListener(widthFinishListener); + widthAnimator.addListener(removeEndListener); + widthAnimator.setDuration((long) (DISAPPEAR_DURATION * currentWidthFactor)); + widthAnimator.setStartDelay(widthDelay); + widthAnimator.start(); + widthAnimationIsGrowing = false; + } + + private void startTextDisappearAnimation(long startDelay) { + cancelAnimator(textAnimator); + textAnimator = ValueAnimator.ofFloat(currentTextSizeFactor, 0.0f); + textAnimator.addUpdateListener(textSizeUpdater); + textAnimator.addListener(textFinishListener); + textAnimator.setInterpolator(mDisappearInterpolator); + textAnimator.setDuration((long) (DISAPPEAR_DURATION * currentTextSizeFactor)); + textAnimator.setStartDelay(startDelay); + textAnimator.start(); + textAnimationIsGrowing = false; + } + + private void startDotDisappearAnimation(long startDelay) { + cancelAnimator(dotAnimator); + ValueAnimator animator = ValueAnimator.ofFloat(currentDotSizeFactor, 0.0f); + animator.addUpdateListener(dotSizeUpdater); + animator.addListener(dotFinishListener); + animator.setInterpolator(mDisappearInterpolator); + long duration = (long) (DISAPPEAR_DURATION * Math.min(currentDotSizeFactor, 1.0f)); + animator.setDuration(duration); + animator.setStartDelay(startDelay); + animator.start(); + dotAnimator = animator; + dotAnimationIsGrowing = false; + } + + private void startWidthAppearAnimation() { + cancelAnimator(widthAnimator); + widthAnimator = ValueAnimator.ofFloat(currentWidthFactor, 1.0f); + widthAnimator.addUpdateListener(widthUpdater); + widthAnimator.addListener(widthFinishListener); + widthAnimator.setDuration((long) (APPEAR_DURATION * (1f - currentWidthFactor))); + widthAnimator.start(); + widthAnimationIsGrowing = true; + } + + private void startTextAppearAnimation() { + cancelAnimator(textAnimator); + textAnimator = ValueAnimator.ofFloat(currentTextSizeFactor, 1.0f); + textAnimator.addUpdateListener(textSizeUpdater); + textAnimator.addListener(textFinishListener); + textAnimator.setInterpolator(mAppearInterpolator); + textAnimator.setDuration((long) (APPEAR_DURATION * (1f - currentTextSizeFactor))); + textAnimator.start(); + textAnimationIsGrowing = true; + + // handle translation + if (textTranslateAnimator == null) { + textTranslateAnimator = ValueAnimator.ofFloat(1.0f, 0.0f); + textTranslateAnimator.addUpdateListener(textTranslationUpdater); + textTranslateAnimator.addListener(textTranslateFinishListener); + textTranslateAnimator.setInterpolator(mAppearInterpolator); + textTranslateAnimator.setDuration(APPEAR_DURATION); + textTranslateAnimator.start(); + } + } + + private void startDotAppearAnimation(long delay) { + cancelAnimator(dotAnimator); + if (!mShowPassword) { + // We perform an overshoot animation + ValueAnimator overShootAnimator = ValueAnimator.ofFloat(currentDotSizeFactor, + DOT_OVERSHOOT_FACTOR); + overShootAnimator.addUpdateListener(dotSizeUpdater); + overShootAnimator.setInterpolator(mAppearInterpolator); + long overShootDuration = (long) (DOT_APPEAR_DURATION_OVERSHOOT + * OVERSHOOT_TIME_POSITION); + overShootAnimator.setDuration(overShootDuration); + ValueAnimator settleBackAnimator = ValueAnimator.ofFloat(DOT_OVERSHOOT_FACTOR, + 1.0f); + settleBackAnimator.addUpdateListener(dotSizeUpdater); + settleBackAnimator.setDuration(DOT_APPEAR_DURATION_OVERSHOOT - overShootDuration); + settleBackAnimator.addListener(dotFinishListener); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playSequentially(overShootAnimator, settleBackAnimator); + animatorSet.setStartDelay(delay); + animatorSet.start(); + dotAnimator = animatorSet; + } else { + ValueAnimator growAnimator = ValueAnimator.ofFloat(currentDotSizeFactor, 1.0f); + growAnimator.addUpdateListener(dotSizeUpdater); + growAnimator.setDuration((long) (APPEAR_DURATION * (1.0f - currentDotSizeFactor))); + growAnimator.addListener(dotFinishListener); + growAnimator.setStartDelay(delay); + growAnimator.start(); + dotAnimator = growAnimator; + } + dotAnimationIsGrowing = true; + } + + private void cancelAnimator(Animator animator) { + if (animator != null) { + animator.cancel(); + } + } + + /** + * Draw this char to the canvas. + * + * @return The width this character contributes, including padding. + */ + public float draw(Canvas canvas, float currentDrawPosition, int charHeight, float yPosition, + float charLength) { + boolean textVisible = currentTextSizeFactor > 0; + boolean dotVisible = currentDotSizeFactor > 0; + float charWidth = charLength * currentWidthFactor; + if (textVisible) { + float currYPosition = yPosition + charHeight / 2.0f * currentTextSizeFactor + + charHeight * currentTextTranslationY * 0.8f; + canvas.save(); + float centerX = currentDrawPosition + charWidth / 2; + canvas.translate(centerX, currYPosition); + canvas.scale(currentTextSizeFactor, currentTextSizeFactor); + canvas.drawText(Character.toString(whichChar), 0, 0, mDrawPaint); + canvas.restore(); + } + if (dotVisible) { + canvas.save(); + float centerX = currentDrawPosition + charWidth / 2; + canvas.translate(centerX, yPosition); + canvas.drawCircle(0, 0, mDotSize / 2 * currentDotSizeFactor, mDrawPaint); + canvas.restore(); + } + return charWidth + mCharPadding * currentWidthFactor; + } + } +} |