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
This commit is contained in:
Selim Cinek
2014-06-20 16:37:04 -07:00
parent 5f834774c7
commit 4e8b9ed30b
32 changed files with 1627 additions and 971 deletions

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 786 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -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>

View File

@@ -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>

View File

@@ -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"

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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"

View File

@@ -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 -->

View File

@@ -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>

View File

@@ -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>

View File

@@ -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: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="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>
<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>
</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>
<item name="android:paddingBottom">0dp</item>
</style>
<!-- Standard animations for a non-full-screen window or activity. -->

View File

@@ -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) {
@@ -192,17 +156,6 @@ public abstract class KeyguardAbsKeyInputView extends LinearLayout
return false;
}
@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) {

View File

@@ -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

View File

@@ -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);
@@ -81,6 +86,12 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView
mImm.hideSoftInputFromWindow(getWindowToken(), 0);
}
@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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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() {

View File

@@ -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

View File

@@ -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;
}
}
}