diff options
author | Yorke Lee <yorkelee@google.com> | 2014-06-20 19:27:31 +0000 |
---|---|---|
committer | Yorke Lee <yorkelee@google.com> | 2014-06-20 19:27:31 +0000 |
commit | 56444f96da37934839c788f2a74cbb5d8193c552 (patch) | |
tree | 67ce563c527882768a6a6bd8384814bdad933b77 /src/com/android | |
parent | 8e7cebc6aff9b41192dd3348fc52ef62c06236ab (diff) | |
download | android_packages_apps_ContactsCommon-56444f96da37934839c788f2a74cbb5d8193c552.tar.gz android_packages_apps_ContactsCommon-56444f96da37934839c788f2a74cbb5d8193c552.tar.bz2 android_packages_apps_ContactsCommon-56444f96da37934839c788f2a74cbb5d8193c552.zip |
Revert "Update Emergency Dialer to match Dialer (3/5)."
This reverts commit 8e7cebc6aff9b41192dd3348fc52ef62c06236ab.
Change-Id: Ifa42f45868286b80e111229bb0761798af884293
Diffstat (limited to 'src/com/android')
6 files changed, 810 insertions, 0 deletions
diff --git a/src/com/android/contacts/common/animation/AnimUtils.java b/src/com/android/contacts/common/animation/AnimUtils.java new file mode 100644 index 00000000..5f5dec9b --- /dev/null +++ b/src/com/android/contacts/common/animation/AnimUtils.java @@ -0,0 +1,108 @@ +/* + * 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.contacts.common.animation; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.view.View; +import android.view.ViewPropertyAnimator; +import android.view.animation.Interpolator; +import android.view.animation.PathInterpolator; + +public class AnimUtils { + public static final int DEFAULT_DURATION = -1; + public static final Interpolator EASE_IN = new PathInterpolator(0.0f, 0.0f, 0.2f, 1.0f); + public static final Interpolator EASE_OUT = new PathInterpolator(0.4f, 0.0f, 1.0f, 1.0f); + public static final Interpolator EASE_OUT_EASE_IN = new PathInterpolator(0.4f, 0, 0.2f, 1); + + public static class AnimationCallback { + public void onAnimationEnd() {} + public void onAnimationCancel() {} + } + + public static void crossFadeViews(View fadeIn, View fadeOut, int duration) { + fadeIn(fadeIn, duration); + fadeOut(fadeOut, duration); + } + + public static void fadeOut(View fadeOut, int duration) { + fadeOut(fadeOut, duration, null); + } + + public static void fadeOut(final View fadeOut, int duration, final AnimationCallback callback) { + fadeOut.setAlpha(1); + final ViewPropertyAnimator animator = fadeOut.animate(); + animator.cancel(); + animator.alpha(0).withLayer().setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + fadeOut.setVisibility(View.GONE); + if (callback != null) { + callback.onAnimationEnd(); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + fadeOut.setVisibility(View.GONE); + fadeOut.setAlpha(0); + if (callback != null) { + callback.onAnimationCancel(); + } + } + }); + if (duration != DEFAULT_DURATION) { + animator.setDuration(duration); + } + animator.start(); + } + + public static void fadeIn(View fadeIn, int duration) { + fadeIn(fadeIn, duration, null); + } + + public static void fadeIn(final View fadeIn, int duration, final AnimationCallback callback) { + fadeIn.setAlpha(0); + final ViewPropertyAnimator animator = fadeIn.animate(); + animator.cancel(); + animator.alpha(1).withLayer().setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + fadeIn.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationCancel(Animator animation) { + fadeIn.setAlpha(1); + if (callback != null) { + callback.onAnimationCancel(); + } + } + + @Override + public void onAnimationEnd(Animator animation) { + if (callback != null) { + callback.onAnimationEnd(); + } + } + }); + if (duration != DEFAULT_DURATION) { + animator.setDuration(duration); + } + animator.start(); + } +} diff --git a/src/com/android/contacts/common/animation/AnimationListenerAdapter.java b/src/com/android/contacts/common/animation/AnimationListenerAdapter.java new file mode 100644 index 00000000..abdfe4a9 --- /dev/null +++ b/src/com/android/contacts/common/animation/AnimationListenerAdapter.java @@ -0,0 +1,48 @@ +/* + * 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.contacts.common.animation; + +import android.view.animation.Animation; +import android.view.animation.Animation.AnimationListener; + +/** + * Provides empty implementations of the methods in {@link AnimationListener} + * for convenience reasons. + */ +public class AnimationListenerAdapter implements AnimationListener { + + /** + * {@inheritDoc} + */ + @Override + public void onAnimationStart(Animation animation) { + } + + /** + * {@inheritDoc} + */ + @Override + public void onAnimationEnd(Animation animation) { + } + + /** + * {@inheritDoc} + */ + @Override + public void onAnimationRepeat(Animation animation) { + } +} diff --git a/src/com/android/contacts/common/dialpad/DialpadKeyButton.java b/src/com/android/contacts/common/dialpad/DialpadKeyButton.java new file mode 100644 index 00000000..db62af84 --- /dev/null +++ b/src/com/android/contacts/common/dialpad/DialpadKeyButton.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.contacts.common.dialpad; + +import android.content.Context; +import android.graphics.Rect; +import android.os.Bundle; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.accessibility.AccessibilityEvent; +import android.view.accessibility.AccessibilityManager; +import android.view.accessibility.AccessibilityNodeInfo; +import android.widget.FrameLayout; + +/** + * Custom class for dialpad buttons. + * <p> + * When touch exploration mode is enabled for accessibility, this class + * implements the lift-to-type interaction model: + * <ul> + * <li>Hovering over the button will cause it to gain accessibility focus + * <li>Removing the hover pointer while inside the bounds of the button will + * perform a click action + * <li>If long-click is supported, hovering over the button for a longer period + * of time will switch to the long-click action + * <li>Moving the hover pointer outside of the bounds of the button will restore + * to the normal click action + * <ul> + */ +public class DialpadKeyButton extends FrameLayout { + /** Timeout before switching to long-click accessibility mode. */ + private static final int LONG_HOVER_TIMEOUT = ViewConfiguration.getLongPressTimeout() * 2; + + /** Accessibility manager instance used to check touch exploration state. */ + private AccessibilityManager mAccessibilityManager; + + /** Bounds used to filter HOVER_EXIT events. */ + private Rect mHoverBounds = new Rect(); + + /** Whether this view is currently in the long-hover state. */ + private boolean mLongHovered; + + /** Alternate content description for long-hover state. */ + private CharSequence mLongHoverContentDesc; + + /** Backup of standard content description. Used for accessibility. */ + private CharSequence mBackupContentDesc; + + /** Backup of clickable property. Used for accessibility. */ + private boolean mWasClickable; + + /** Backup of long-clickable property. Used for accessibility. */ + private boolean mWasLongClickable; + + /** Runnable used to trigger long-click mode for accessibility. */ + private Runnable mLongHoverRunnable; + + public interface OnPressedListener { + public void onPressed(View view, boolean pressed); + } + + private OnPressedListener mOnPressedListener; + + public void setOnPressedListener(OnPressedListener onPressedListener) { + mOnPressedListener = onPressedListener; + } + + public DialpadKeyButton(Context context, AttributeSet attrs) { + super(context, attrs); + initForAccessibility(context); + } + + public DialpadKeyButton(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initForAccessibility(context); + } + + private void initForAccessibility(Context context) { + mAccessibilityManager = (AccessibilityManager) context.getSystemService( + Context.ACCESSIBILITY_SERVICE); + } + + public void setLongHoverContentDescription(CharSequence contentDescription) { + mLongHoverContentDesc = contentDescription; + + if (mLongHovered) { + super.setContentDescription(mLongHoverContentDesc); + } + } + + @Override + public void setContentDescription(CharSequence contentDescription) { + if (mLongHovered) { + mBackupContentDesc = contentDescription; + } else { + super.setContentDescription(contentDescription); + } + } + + @Override + public void setPressed(boolean pressed) { + super.setPressed(pressed); + if (mOnPressedListener != null) { + mOnPressedListener.onPressed(this, pressed); + } + } + + @Override + public void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + mHoverBounds.left = getPaddingLeft(); + mHoverBounds.right = w - getPaddingRight(); + mHoverBounds.top = getPaddingTop(); + mHoverBounds.bottom = h - getPaddingBottom(); + } + + @Override + public boolean performAccessibilityAction(int action, Bundle arguments) { + if (action == AccessibilityNodeInfo.ACTION_CLICK) { + simulateClickForAccessibility(); + return true; + } + + return super.performAccessibilityAction(action, arguments); + } + + @Override + public boolean onHoverEvent(MotionEvent event) { + // When touch exploration is turned on, lifting a finger while inside + // the button's hover target bounds should perform a click action. + if (mAccessibilityManager.isEnabled() + && mAccessibilityManager.isTouchExplorationEnabled()) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_HOVER_ENTER: + // Lift-to-type temporarily disables double-tap activation. + mWasClickable = isClickable(); + mWasLongClickable = isLongClickable(); + if (mWasLongClickable && mLongHoverContentDesc != null) { + if (mLongHoverRunnable == null) { + mLongHoverRunnable = new Runnable() { + @Override + public void run() { + setLongHovered(true); + announceForAccessibility(mLongHoverContentDesc); + } + }; + } + postDelayed(mLongHoverRunnable, LONG_HOVER_TIMEOUT); + } + + setClickable(false); + setLongClickable(false); + break; + case MotionEvent.ACTION_HOVER_EXIT: + if (mHoverBounds.contains((int) event.getX(), (int) event.getY())) { + if (mLongHovered) { + performLongClick(); + } else { + simulateClickForAccessibility(); + } + } + + cancelLongHover(); + setClickable(mWasClickable); + setLongClickable(mWasLongClickable); + break; + } + } + + return super.onHoverEvent(event); + } + + /** + * When accessibility is on, simulate press and release to preserve the + * semantic meaning of performClick(). Required for Braille support. + */ + private void simulateClickForAccessibility() { + // Checking the press state prevents double activation. + if (isPressed()) { + return; + } + + setPressed(true); + + // Stay consistent with performClick() by sending the event after + // setting the pressed state but before performing the action. + sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); + + setPressed(false); + } + + private void setLongHovered(boolean enabled) { + if (mLongHovered != enabled) { + mLongHovered = enabled; + + // Switch between normal and alternate description, if available. + if (enabled) { + mBackupContentDesc = getContentDescription(); + super.setContentDescription(mLongHoverContentDesc); + } else { + super.setContentDescription(mBackupContentDesc); + } + } + } + + private void cancelLongHover() { + if (mLongHoverRunnable != null) { + removeCallbacks(mLongHoverRunnable); + } + setLongHovered(false); + } +} diff --git a/src/com/android/contacts/common/dialpad/DialpadTextView.java b/src/com/android/contacts/common/dialpad/DialpadTextView.java new file mode 100644 index 00000000..0a65329c --- /dev/null +++ b/src/com/android/contacts/common/dialpad/DialpadTextView.java @@ -0,0 +1,72 @@ +/* + * 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.contacts.common.dialpad; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.widget.TextView; + +/** + * This is a custom text view intended only for rendering the numerals (and star and pound) on the + * dialpad. TextView has built in top/bottom padding to help account for ascenders/descenders. + * + * Since vertical space is at a premium on the dialpad, particularly if the font size is scaled to + * a larger default, for the dialpad we use this class to more precisely render characters according + * to the precise amount of space they need. + */ +public class DialpadTextView extends TextView { + private Rect mTextBounds = new Rect(); + private String mTextStr; + + public DialpadTextView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + /** + * Draw the text to fit within the height/width which have been specified during measurement. + */ + @Override + public void draw(Canvas canvas) { + Paint paint = getPaint(); + + // Without this, the draw does not respect the style's specified text color. + paint.setColor(getCurrentTextColor()); + + // The text bounds values are relative and can be negative,, so rather than specifying a + // standard origin such as 0, 0, we need to use negative of the left/top bounds. + // For example, the bounds may be: Left: 11, Right: 37, Top: -77, Bottom: 0 + canvas.drawText(mTextStr, -mTextBounds.left, -mTextBounds.top, paint); + } + + /** + * Calculate the pixel-accurate bounds of the text when rendered, and use that to specify the + * height and width. + */ + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + mTextStr = getText().toString(); + getPaint().getTextBounds(mTextStr, 0, mTextStr.length(), mTextBounds); + + int width = resolveSize(mTextBounds.width(), widthMeasureSpec); + int height = resolveSize(mTextBounds.height(), heightMeasureSpec); + setMeasuredDimension(width, height); + } +}
\ No newline at end of file diff --git a/src/com/android/contacts/common/dialpad/DialpadView.java b/src/com/android/contacts/common/dialpad/DialpadView.java new file mode 100644 index 00000000..dccaab30 --- /dev/null +++ b/src/com/android/contacts/common/dialpad/DialpadView.java @@ -0,0 +1,259 @@ +/* + * 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.contacts.common.dialpad; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.PorterDuff; +import android.graphics.drawable.RippleDrawable; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.LinearLayout; +import android.widget.TextView; + +import com.android.contacts.common.R; +import com.android.contacts.common.animation.AnimUtils; + +/** + * View that displays a twelve-key phone dialpad. + */ +public class DialpadView extends LinearLayout { + private static final String TAG = DialpadView.class.getSimpleName(); + + private static final double DELAY_MULTIPLIER = 0.66; + private static final double DURATION_MULTIPLIER = 0.8; + + private EditText mDigits; + private ImageButton mDelete; + private View mOverflowMenuButton; + private ColorStateList mRippleColor; + + private boolean mCanDigitsBeEdited; + + private final int[] mButtonIds = new int[] {R.id.zero, R.id.one, R.id.two, R.id.three, + R.id.four, R.id.five, R.id.six, R.id.seven, R.id.eight, R.id.nine, R.id.star, + R.id.pound}; + + // For animation. + private static final int KEY_FRAME_DURATION = 33; + + private int mTranslateDistance; + + public DialpadView(Context context) { + this(context, null); + } + + public DialpadView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DialpadView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Dialpad); + mRippleColor = a.getColorStateList(R.styleable.Dialpad_dialpad_key_button_touch_tint); + a.recycle(); + + mTranslateDistance = getResources().getDimensionPixelSize( + R.dimen.dialpad_key_button_translate_y); + } + + @Override + protected void onFinishInflate() { + setupKeypad(); + mDigits = (EditText) findViewById(R.id.digits); + mDelete = (ImageButton) findViewById(R.id.deleteButton); + mOverflowMenuButton = findViewById(R.id.dialpad_overflow); + } + + private void setupKeypad() { + final int[] numberIds = new int[] {R.string.dialpad_0_number, R.string.dialpad_1_number, + R.string.dialpad_2_number, R.string.dialpad_3_number, R.string.dialpad_4_number, + R.string.dialpad_5_number, R.string.dialpad_6_number, R.string.dialpad_7_number, + R.string.dialpad_8_number, R.string.dialpad_9_number, R.string.dialpad_star_number, + R.string.dialpad_pound_number}; + + final int[] letterIds = new int[] {R.string.dialpad_0_letters, R.string.dialpad_1_letters, + R.string.dialpad_2_letters, R.string.dialpad_3_letters, R.string.dialpad_4_letters, + R.string.dialpad_5_letters, R.string.dialpad_6_letters, R.string.dialpad_7_letters, + R.string.dialpad_8_letters, R.string.dialpad_9_letters, + R.string.dialpad_star_letters, R.string.dialpad_pound_letters}; + + final Resources resources = getContext().getResources(); + + DialpadKeyButton dialpadKey; + TextView numberView; + TextView lettersView; + + for (int i = 0; i < mButtonIds.length; i++) { + dialpadKey = (DialpadKeyButton) findViewById(mButtonIds[i]); + numberView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_number); + lettersView = (TextView) dialpadKey.findViewById(R.id.dialpad_key_letters); + final String numberString = resources.getString(numberIds[i]); + final RippleDrawable rippleBackground = + (RippleDrawable) resources.getDrawable(R.drawable.btn_dialpad_key); + if (mRippleColor != null) { + rippleBackground.setColor(mRippleColor); + } + + numberView.setText(numberString); + numberView.setElegantTextHeight(false); + dialpadKey.setContentDescription(numberString); + dialpadKey.setBackground(rippleBackground); + + if (lettersView != null) { + lettersView.setText(resources.getString(letterIds[i])); + } + } + + final DialpadKeyButton one = (DialpadKeyButton) findViewById(R.id.one); + one.setLongHoverContentDescription( + resources.getText(R.string.description_voicemail_button)); + + final DialpadKeyButton zero = (DialpadKeyButton) findViewById(R.id.zero); + zero.setLongHoverContentDescription( + resources.getText(R.string.description_image_button_plus)); + + } + + public void setShowVoicemailButton(boolean show) { + View view = findViewById(R.id.dialpad_key_voicemail); + if (view != null) { + view.setVisibility(show ? View.VISIBLE : View.INVISIBLE); + } + } + + /** + * Whether or not the digits above the dialer can be edited. + * + * @param canBeEdited If true, the backspace button will be shown and the digits EditText + * will be configured to allow text manipulation. + */ + public void setCanDigitsBeEdited(boolean canBeEdited) { + View deleteButton = findViewById(R.id.deleteButton); + deleteButton.setVisibility(canBeEdited ? View.VISIBLE : View.GONE); + View overflowMenuButton = findViewById(R.id.dialpad_overflow); + overflowMenuButton.setVisibility(canBeEdited ? View.VISIBLE : View.GONE); + + EditText digits = (EditText) findViewById(R.id.digits); + digits.setClickable(canBeEdited); + digits.setLongClickable(canBeEdited); + digits.setFocusableInTouchMode(canBeEdited); + digits.setCursorVisible(false); + + mCanDigitsBeEdited = canBeEdited; + } + + public boolean canDigitsBeEdited() { + return mCanDigitsBeEdited; + } + + /** + * Always returns true for onHoverEvent callbacks, to fix problems with accessibility due to + * the dialpad overlaying other fragments. + */ + @Override + public boolean onHoverEvent(MotionEvent event) { + return true; + } + + public void animateShow() { + // This is a hack; without this, the setTranslationY is delayed in being applied, and the + // numbers appear at their original position (0) momentarily before animating. + final AnimatorListenerAdapter showListener = new AnimatorListenerAdapter() {}; + + for (int i = 0; i < mButtonIds.length; i++) { + int delay = (int)(getKeyButtonAnimationDelay(mButtonIds[i]) * DELAY_MULTIPLIER); + int duration = + (int)(getKeyButtonAnimationDuration(mButtonIds[i]) * DURATION_MULTIPLIER); + final DialpadKeyButton dialpadKey = (DialpadKeyButton) findViewById(mButtonIds[i]); + + dialpadKey.setTranslationY(mTranslateDistance); + dialpadKey.animate() + .translationY(0) + .setInterpolator(AnimUtils.EASE_OUT_EASE_IN) + .setStartDelay(delay) + .setDuration(duration) + .setListener(showListener) + .start(); + } + } + + public EditText getDigits() { + return mDigits; + } + + public ImageButton getDeleteButton() { + return mDelete; + } + + public View getOverflowMenuButton() { + return mOverflowMenuButton; + } + + private int getKeyButtonAnimationDelay(int buttonId) { + switch(buttonId) { + case R.id.one: return KEY_FRAME_DURATION * 1; + case R.id.two: return KEY_FRAME_DURATION * 2; + case R.id.three: return KEY_FRAME_DURATION * 3; + case R.id.four: return KEY_FRAME_DURATION * 4; + case R.id.five: return KEY_FRAME_DURATION * 5; + case R.id.six: return KEY_FRAME_DURATION * 6; + case R.id.seven: return KEY_FRAME_DURATION * 7; + case R.id.eight: return KEY_FRAME_DURATION * 8; + case R.id.nine: return KEY_FRAME_DURATION * 9; + case R.id.star: return KEY_FRAME_DURATION * 10; + case R.id.zero: + case R.id.pound: + return KEY_FRAME_DURATION * 11; + } + + Log.wtf(TAG, "Attempted to get animation delay for invalid key button id."); + return 0; + } + + private int getKeyButtonAnimationDuration(int buttonId) { + switch(buttonId) { + case R.id.one: + case R.id.two: + case R.id.three: + case R.id.four: + case R.id.five: + case R.id.six: + return KEY_FRAME_DURATION * 10; + case R.id.seven: + case R.id.eight: + case R.id.nine: + return KEY_FRAME_DURATION * 9; + case R.id.star: + case R.id.zero: + case R.id.pound: + return KEY_FRAME_DURATION * 8; + } + + Log.wtf(TAG, "Attempted to get animation duration for invalid key button id."); + return 0; + } +} diff --git a/src/com/android/contacts/common/dialpad/DigitsEditText.java b/src/com/android/contacts/common/dialpad/DigitsEditText.java new file mode 100644 index 00000000..bc8fca39 --- /dev/null +++ b/src/com/android/contacts/common/dialpad/DigitsEditText.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2011 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.contacts.common.dialpad; + +import android.content.Context; +import android.graphics.Paint; +import android.graphics.Rect; +import android.text.InputType; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.MotionEvent; +import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.EditText; + +import com.android.contacts.common.R; + +/** + * EditText which suppresses IME show up. + */ +public class DigitsEditText extends EditText { + // Only scale the text down to 66% smaller at most. + private static final float MIN_TEXT_RESIZE_RATIO = 0.66f; + private final float mOriginalTextSize; + + public DigitsEditText(Context context, AttributeSet attrs) { + super(context, attrs); + mOriginalTextSize = getTextSize(); + setInputType(getInputType() | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS); + setShowSoftInputOnFocus(false); + } + + @Override + protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) { + super.onFocusChanged(focused, direction, previouslyFocusedRect); + final InputMethodManager imm = ((InputMethodManager) getContext() + .getSystemService(Context.INPUT_METHOD_SERVICE)); + if (imm != null && imm.isActive(this)) { + imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + final boolean ret = super.onTouchEvent(event); + // Must be done after super.onTouchEvent() + final InputMethodManager imm = ((InputMethodManager) getContext() + .getSystemService(Context.INPUT_METHOD_SERVICE)); + if (imm != null && imm.isActive(this)) { + imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0); + } + return ret; + } + + @Override + protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) { + super.onTextChanged(text, start, lengthBefore, lengthAfter); + resizeText(getWidth()); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + resizeText(w); + } + + private void resizeText(int width) { + if (width == 0) { + return; + } + final Paint paint = getPaint(); + setTextSize(TypedValue.COMPLEX_UNIT_PX, mOriginalTextSize); + + float ratio = width / paint.measureText(getText().toString()); + if (ratio <= 1.0f) { + setTextSize(TypedValue.COMPLEX_UNIT_PX, + mOriginalTextSize * Math.max(MIN_TEXT_RESIZE_RATIO, ratio)); + } + } +} |