From f023f97370cfbe775a1fab04da3699e0f82c066b Mon Sep 17 00:00:00 2001 From: Kamaljeet Maini Date: Fri, 22 Apr 2016 14:43:25 -0700 Subject: Add new options for call waiting response in InCallUI When an incoming call is received while there is already an active call, the user will be given four choices for the response: 1) Left button: hold the current call and answer incoming call 2) Bottom button: end the current call and answer the incoming call 3) Right button: decline the incoming call 4) Top button: Send a text message to the incoming caller if texting is enabled The changes in this component include updated icon graphics, display of text hints, and new APIs for additonal flag. Change-Id: Ic97e0fde12ae98afa0124f4bb5326e874a146e91 --- res/drawable-hdpi/ic_call_end_16dp.png | Bin 0 -> 316 bytes res/drawable-hdpi/ic_pause_16dp.png | Bin 0 -> 159 bytes res/drawable-mdpi/ic_call_end_16dp.png | Bin 0 -> 243 bytes res/drawable-mdpi/ic_pause_16dp.png | Bin 0 -> 178 bytes res/drawable-xhdpi/ic_call_end_16dp.png | Bin 0 -> 351 bytes res/drawable-xhdpi/ic_pause_16dp.png | Bin 0 -> 159 bytes res/drawable-xxhdpi/ic_call_end_16dp.png | Bin 0 -> 455 bytes res/drawable-xxhdpi/ic_pause_16dp.png | Bin 0 -> 161 bytes res/drawable-xxxhdpi/ic_call_end_16dp.png | Bin 0 -> 584 bytes res/drawable-xxxhdpi/ic_pause_16dp.png | Bin 0 -> 163 bytes .../ic_lockscreen_answer_activated_layer.xml | 15 ++-- res/drawable/ic_lockscreen_answer_end_current.xml | 27 +++++++ ...ckscreen_answer_end_current_activated_layer.xml | 28 +++++++ ..._lockscreen_answer_end_current_normal_layer.xml | 37 +++++++++ res/drawable/ic_lockscreen_answer_hold_current.xml | 27 +++++++ ...kscreen_answer_hold_current_activated_layer.xml | 28 +++++++ ...lockscreen_answer_hold_current_normal_layer.xml | 37 +++++++++ res/drawable/ic_lockscreen_answer_normal_layer.xml | 16 ++-- .../ic_lockscreen_block_activated_layer.xml | 13 +-- res/drawable/ic_lockscreen_block_normal_layer.xml | 20 +++-- .../ic_lockscreen_decline_activated_layer.xml | 13 +-- .../ic_lockscreen_decline_normal_layer.xml | 17 ++-- res/drawable/ic_lockscreen_decline_small_layer.xml | 36 +++++++++ res/drawable/ic_lockscreen_hold_small_layer.xml | 36 +++++++++ .../ic_lockscreen_text_activated_layer.xml | 19 ++--- res/drawable/ic_lockscreen_text_normal_layer.xml | 14 ++-- res/layout/answer_fragment.xml | 1 + res/values/array.xml | 90 +++++++++++++++++++++ res/values/attrs.xml | 3 + res/values/cm_colors.xml | 10 +++ res/values/cm_dimens.xml | 13 +++ res/values/cm_strings.xml | 15 ++++ src/com/android/incallui/AnswerFragment.java | 51 +++++++++++- src/com/android/incallui/AnswerPresenter.java | 33 +++++--- src/com/android/incallui/GlowPadWrapper.java | 12 +++ src/com/android/incallui/TelecomAdapter.java | 9 +++ .../incallui/widget/multiwaveview/GlowPadView.java | 81 ++++++++++++++++++- 37 files changed, 630 insertions(+), 71 deletions(-) create mode 100644 res/drawable-hdpi/ic_call_end_16dp.png create mode 100644 res/drawable-hdpi/ic_pause_16dp.png create mode 100644 res/drawable-mdpi/ic_call_end_16dp.png create mode 100644 res/drawable-mdpi/ic_pause_16dp.png create mode 100644 res/drawable-xhdpi/ic_call_end_16dp.png create mode 100644 res/drawable-xhdpi/ic_pause_16dp.png create mode 100644 res/drawable-xxhdpi/ic_call_end_16dp.png create mode 100644 res/drawable-xxhdpi/ic_pause_16dp.png create mode 100644 res/drawable-xxxhdpi/ic_call_end_16dp.png create mode 100644 res/drawable-xxxhdpi/ic_pause_16dp.png create mode 100644 res/drawable/ic_lockscreen_answer_end_current.xml create mode 100644 res/drawable/ic_lockscreen_answer_end_current_activated_layer.xml create mode 100644 res/drawable/ic_lockscreen_answer_end_current_normal_layer.xml create mode 100644 res/drawable/ic_lockscreen_answer_hold_current.xml create mode 100644 res/drawable/ic_lockscreen_answer_hold_current_activated_layer.xml create mode 100644 res/drawable/ic_lockscreen_answer_hold_current_normal_layer.xml create mode 100644 res/drawable/ic_lockscreen_decline_small_layer.xml create mode 100644 res/drawable/ic_lockscreen_hold_small_layer.xml diff --git a/res/drawable-hdpi/ic_call_end_16dp.png b/res/drawable-hdpi/ic_call_end_16dp.png new file mode 100644 index 00000000..f049c3ab Binary files /dev/null and b/res/drawable-hdpi/ic_call_end_16dp.png differ diff --git a/res/drawable-hdpi/ic_pause_16dp.png b/res/drawable-hdpi/ic_pause_16dp.png new file mode 100644 index 00000000..bda48634 Binary files /dev/null and b/res/drawable-hdpi/ic_pause_16dp.png differ diff --git a/res/drawable-mdpi/ic_call_end_16dp.png b/res/drawable-mdpi/ic_call_end_16dp.png new file mode 100644 index 00000000..0ccf67a9 Binary files /dev/null and b/res/drawable-mdpi/ic_call_end_16dp.png differ diff --git a/res/drawable-mdpi/ic_pause_16dp.png b/res/drawable-mdpi/ic_pause_16dp.png new file mode 100644 index 00000000..3d58e3b7 Binary files /dev/null and b/res/drawable-mdpi/ic_pause_16dp.png differ diff --git a/res/drawable-xhdpi/ic_call_end_16dp.png b/res/drawable-xhdpi/ic_call_end_16dp.png new file mode 100644 index 00000000..aad29a86 Binary files /dev/null and b/res/drawable-xhdpi/ic_call_end_16dp.png differ diff --git a/res/drawable-xhdpi/ic_pause_16dp.png b/res/drawable-xhdpi/ic_pause_16dp.png new file mode 100644 index 00000000..ae2617f3 Binary files /dev/null and b/res/drawable-xhdpi/ic_pause_16dp.png differ diff --git a/res/drawable-xxhdpi/ic_call_end_16dp.png b/res/drawable-xxhdpi/ic_call_end_16dp.png new file mode 100644 index 00000000..0d0f3130 Binary files /dev/null and b/res/drawable-xxhdpi/ic_call_end_16dp.png differ diff --git a/res/drawable-xxhdpi/ic_pause_16dp.png b/res/drawable-xxhdpi/ic_pause_16dp.png new file mode 100644 index 00000000..1d6eaf50 Binary files /dev/null and b/res/drawable-xxhdpi/ic_pause_16dp.png differ diff --git a/res/drawable-xxxhdpi/ic_call_end_16dp.png b/res/drawable-xxxhdpi/ic_call_end_16dp.png new file mode 100644 index 00000000..3ed18ece Binary files /dev/null and b/res/drawable-xxxhdpi/ic_call_end_16dp.png differ diff --git a/res/drawable-xxxhdpi/ic_pause_16dp.png b/res/drawable-xxxhdpi/ic_pause_16dp.png new file mode 100644 index 00000000..f27c7be6 Binary files /dev/null and b/res/drawable-xxxhdpi/ic_pause_16dp.png differ diff --git a/res/drawable/ic_lockscreen_answer_activated_layer.xml b/res/drawable/ic_lockscreen_answer_activated_layer.xml index c615295e..e06fdb69 100644 --- a/res/drawable/ic_lockscreen_answer_activated_layer.xml +++ b/res/drawable/ic_lockscreen_answer_activated_layer.xml @@ -14,12 +14,15 @@ limitations under the License. --> - + - + + + + diff --git a/res/drawable/ic_lockscreen_answer_end_current.xml b/res/drawable/ic_lockscreen_answer_end_current.xml new file mode 100644 index 00000000..e00afb52 --- /dev/null +++ b/res/drawable/ic_lockscreen_answer_end_current.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/res/drawable/ic_lockscreen_answer_end_current_activated_layer.xml b/res/drawable/ic_lockscreen_answer_end_current_activated_layer.xml new file mode 100644 index 00000000..9469a37c --- /dev/null +++ b/res/drawable/ic_lockscreen_answer_end_current_activated_layer.xml @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/res/drawable/ic_lockscreen_answer_end_current_normal_layer.xml b/res/drawable/ic_lockscreen_answer_end_current_normal_layer.xml new file mode 100644 index 00000000..4c53b3aa --- /dev/null +++ b/res/drawable/ic_lockscreen_answer_end_current_normal_layer.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/res/drawable/ic_lockscreen_answer_hold_current.xml b/res/drawable/ic_lockscreen_answer_hold_current.xml new file mode 100644 index 00000000..b96936c2 --- /dev/null +++ b/res/drawable/ic_lockscreen_answer_hold_current.xml @@ -0,0 +1,27 @@ + + + + + + + diff --git a/res/drawable/ic_lockscreen_answer_hold_current_activated_layer.xml b/res/drawable/ic_lockscreen_answer_hold_current_activated_layer.xml new file mode 100644 index 00000000..7ea65294 --- /dev/null +++ b/res/drawable/ic_lockscreen_answer_hold_current_activated_layer.xml @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/res/drawable/ic_lockscreen_answer_hold_current_normal_layer.xml b/res/drawable/ic_lockscreen_answer_hold_current_normal_layer.xml new file mode 100644 index 00000000..662f0d97 --- /dev/null +++ b/res/drawable/ic_lockscreen_answer_hold_current_normal_layer.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + diff --git a/res/drawable/ic_lockscreen_answer_normal_layer.xml b/res/drawable/ic_lockscreen_answer_normal_layer.xml index 31b884f9..1bd7cfdd 100644 --- a/res/drawable/ic_lockscreen_answer_normal_layer.xml +++ b/res/drawable/ic_lockscreen_answer_normal_layer.xml @@ -14,20 +14,20 @@ limitations under the License. --> - - - - + + diff --git a/res/drawable/ic_lockscreen_block_activated_layer.xml b/res/drawable/ic_lockscreen_block_activated_layer.xml index 12d12c48..64029aa5 100644 --- a/res/drawable/ic_lockscreen_block_activated_layer.xml +++ b/res/drawable/ic_lockscreen_block_activated_layer.xml @@ -14,11 +14,14 @@ limitations under the License. --> - - + + + + diff --git a/res/drawable/ic_lockscreen_block_normal_layer.xml b/res/drawable/ic_lockscreen_block_normal_layer.xml index c42ea64c..0606286a 100644 --- a/res/drawable/ic_lockscreen_block_normal_layer.xml +++ b/res/drawable/ic_lockscreen_block_normal_layer.xml @@ -13,21 +13,25 @@ See the License for the specific language governing permissions and limitations under the License. --> + - - - - + + + android:tint="@color/incoming_call_widget_bitmap" + android:autoMirrored="true" /> + diff --git a/res/drawable/ic_lockscreen_decline_activated_layer.xml b/res/drawable/ic_lockscreen_decline_activated_layer.xml index 096c32b4..19fa49f9 100644 --- a/res/drawable/ic_lockscreen_decline_activated_layer.xml +++ b/res/drawable/ic_lockscreen_decline_activated_layer.xml @@ -14,11 +14,14 @@ limitations under the License. --> - - + + + + diff --git a/res/drawable/ic_lockscreen_decline_normal_layer.xml b/res/drawable/ic_lockscreen_decline_normal_layer.xml index 4da5f8d6..8bbfb93b 100644 --- a/res/drawable/ic_lockscreen_decline_normal_layer.xml +++ b/res/drawable/ic_lockscreen_decline_normal_layer.xml @@ -14,19 +14,20 @@ limitations under the License. --> - - - - + + + android:src="@drawable/ic_call_end_white_24dp" + android:tint="@color/incoming_call_widget_bitmap" + android:autoMirrored="true" /> diff --git a/res/drawable/ic_lockscreen_decline_small_layer.xml b/res/drawable/ic_lockscreen_decline_small_layer.xml new file mode 100644 index 00000000..9b51e432 --- /dev/null +++ b/res/drawable/ic_lockscreen_decline_small_layer.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + diff --git a/res/drawable/ic_lockscreen_hold_small_layer.xml b/res/drawable/ic_lockscreen_hold_small_layer.xml new file mode 100644 index 00000000..d8da4d0b --- /dev/null +++ b/res/drawable/ic_lockscreen_hold_small_layer.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + diff --git a/res/drawable/ic_lockscreen_text_activated_layer.xml b/res/drawable/ic_lockscreen_text_activated_layer.xml index a74e36b3..73b6c7de 100644 --- a/res/drawable/ic_lockscreen_text_activated_layer.xml +++ b/res/drawable/ic_lockscreen_text_activated_layer.xml @@ -15,18 +15,13 @@ --> - - - + + - - - + diff --git a/res/drawable/ic_lockscreen_text_normal_layer.xml b/res/drawable/ic_lockscreen_text_normal_layer.xml index be32d0ba..888aeb40 100644 --- a/res/drawable/ic_lockscreen_text_normal_layer.xml +++ b/res/drawable/ic_lockscreen_text_normal_layer.xml @@ -14,20 +14,20 @@ limitations under the License. --> - - - - + + diff --git a/res/layout/answer_fragment.xml b/res/layout/answer_fragment.xml index 03357482..bd9083c7 100644 --- a/res/layout/answer_fragment.xml +++ b/res/layout/answer_fragment.xml @@ -30,6 +30,7 @@ dc:targetDrawables="@array/incoming_call_widget_audio_with_sms_without_block_targets" dc:targetDescriptions="@array/incoming_call_widget_audio_with_sms_without_block_target_descriptions" dc:directionDescriptions="@array/incoming_call_widget_audio_with_sms_without_block_direction_descriptions" + dc:targetDisplayText="@array/incoming_call_widget_audio_with_sms_without_block_display_text" dc:handleDrawable="@drawable/ic_incall_audio_handle" dc:outerRingDrawable="@drawable/ic_lockscreen_outerring" dc:outerRadius="@dimen/glowpadview_target_placement_radius" diff --git a/res/values/array.xml b/res/values/array.xml index 9e6c007e..42f7d16c 100644 --- a/res/values/array.xml +++ b/res/values/array.xml @@ -210,4 +210,94 @@ @null + + + @drawable/ic_lockscreen_answer_hold_current + @null + @drawable/ic_lockscreen_decline + @drawable/ic_lockscreen_answer_end_current" + + + @string/description_target_answer_hold_active + @null + @string/description_target_decline + @string/description_target_answer_end_active" + + + @string/description_direction_right + @null + @string/description_direction_left + @string/description_direction_down + + + @string/display_text_target_answer_and_hold_active + @null + @string/display_text_target_dismiss + @string/display_text_target_answer_and_end_active" + + + + + @drawable/ic_lockscreen_answer_hold_current + @drawable/ic_lockscreen_text + @drawable/ic_lockscreen_decline + @drawable/ic_lockscreen_answer_end_current + + + @string/description_target_answer_hold_active + @string/description_target_send_sms + @string/description_target_decline + @string/description_target_answer_end_active" + + + @string/description_direction_right + @string/description_direction_up + @string/description_direction_left + @string/description_direction_down + + + @string/display_text_target_answer_and_hold_active + @string/display_text_target_sms + @string/display_text_target_dismiss + @string/display_text_target_answer_and_end_active + + + + + @string/empty_string + @string/empty_string + @string/empty_string + @string/empty_string + + + @string/display_text_target_answer + @string/display_text_target_sms + @string/display_text_target_dismiss + @null + + + @string/display_text_target_answer + @null + @string/display_text_target_dismiss + @null + + + @string/display_text_target_answer + @string/display_text_target_sms + @string/display_text_target_dismiss + @string/display_text_target_block + + + @string/display_text_target_answer + @null + @string/display_text_target_dismiss + @string/display_text_target_block + diff --git a/res/values/attrs.xml b/res/values/attrs.xml index e135fb72..f9471bb4 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -28,6 +28,9 @@ + + + diff --git a/res/values/cm_colors.xml b/res/values/cm_colors.xml index adee95e2..4b3f214d 100644 --- a/res/values/cm_colors.xml +++ b/res/values/cm_colors.xml @@ -23,4 +23,14 @@ #ff402c #ffffff + + #b2ffffff + #00c853 + #ff2844 + #ff2844 + #ffffff + #ffffff + #607d8b + #b2ffffff + #0288d1 \ No newline at end of file diff --git a/res/values/cm_dimens.xml b/res/values/cm_dimens.xml index e69ebfc2..b73349cf 100644 --- a/res/values/cm_dimens.xml +++ b/res/values/cm_dimens.xml @@ -36,4 +36,17 @@ 25dp 12dp + + + 14sp + 22dp + 2dp + 27dp + 30dp + 11dp + 20dp + 20dp + 30dp + 30dp + diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml index 77b40f21..18d3a773 100644 --- a/res/values/cm_strings.xml +++ b/res/values/cm_strings.xml @@ -70,5 +70,20 @@ Take note Unknown + + Hold current call and answer + + End current call and answer + + + + DISMISS + BLOCK + ANSWER + QUICK MESSAGE + HOLD CURRENT CALL AND ANSWER + END CURRENT CALL AND ANSWER diff --git a/src/com/android/incallui/AnswerFragment.java b/src/com/android/incallui/AnswerFragment.java index 6ed5e558..2dfba187 100644 --- a/src/com/android/incallui/AnswerFragment.java +++ b/src/com/android/incallui/AnswerFragment.java @@ -21,6 +21,7 @@ import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; +import android.telecom.TelecomManager; import android.telecom.VideoProfile; import android.text.Editable; import android.text.TextWatcher; @@ -57,6 +58,9 @@ public class AnswerFragment extends BaseFragment InCallPresenter.getInstance().acceptUpgradeRequest(videoState, context); } else { Log.d(this, "onAnswer (answerCall) mCallId=" + mCallId + " videoState=" + videoState); - TelecomAdapter.getInstance().answerCall(mCall[phoneId].getId(), videoState); + TelecomAdapter.getInstance().answerCall(mCall[phoneId].getId(), videoState, + callWaitingResponseType); } } @@ -554,6 +555,9 @@ public class AnswerPresenter extends Presenter && mHasTextMessages; boolean withBlock = isBlockingEnabled(); + Call activeCall = CallList.getInstance().getActiveCall(); + boolean isCallWaiting = activeCall != null && activeCall != call; + // Only present the user with the option to answer as a video call if the incoming call is // a bi-directional video call. if (call.isVideoCall(getUi().getContext())) { @@ -575,14 +579,25 @@ public class AnswerPresenter extends Presenter } } else { if (withSms) { - getUi().showTargets(withBlock - ? AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS_AND_BLOCK - : AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS_WITHOUT_BLOCK); - getUi().configureMessageDialog(textMsgs); + if (isCallWaiting) { + getUi().showTargets(AnswerFragment + .TARGET_SET_FOR_AUDIO_WITH_SMS_AND_CALL_WAITING); + getUi().configureMessageDialog(textMsgs); + } else { + getUi().showTargets(withBlock + ? AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS_AND_BLOCK + : AnswerFragment.TARGET_SET_FOR_AUDIO_WITH_SMS_WITHOUT_BLOCK); + getUi().configureMessageDialog(textMsgs); + } } else { - getUi().showTargets(withBlock - ? AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS_WITH_BLOCK - : AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS_AND_BLOCK); + if (isCallWaiting) { + getUi().showTargets(AnswerFragment + .TARGET_SET_FOR_AUDIO_WITHOUT_SMS_WITH_CALL_WAITING); + } else { + getUi().showTargets(withBlock + ? AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS_WITH_BLOCK + : AnswerFragment.TARGET_SET_FOR_AUDIO_WITHOUT_SMS_AND_BLOCK); + } } } } diff --git a/src/com/android/incallui/GlowPadWrapper.java b/src/com/android/incallui/GlowPadWrapper.java index eff43a1c..369bfe20 100644 --- a/src/com/android/incallui/GlowPadWrapper.java +++ b/src/com/android/incallui/GlowPadWrapper.java @@ -20,6 +20,7 @@ import android.content.Context; import android.os.Handler; import android.os.Message; import android.telecom.VideoProfile; +import android.telecom.TelecomManager; import android.util.AttributeSet; import android.view.View; @@ -149,6 +150,16 @@ public class GlowPadWrapper extends GlowPadView implements GlowPadView.OnTrigger mAnswerListener.onDeflect(getContext()); mTargetTriggered = true; break; + case R.drawable.ic_lockscreen_answer_hold_current: + mAnswerListener.onAnswer(VideoProfile.STATE_AUDIO_ONLY, getContext(), + TelecomManager.CALL_WAITING_RESPONSE_NO_POPUP_HOLD_CALL); + mTargetTriggered = true; + break; + case R.drawable.ic_lockscreen_answer_end_current: + mAnswerListener.onAnswer(VideoProfile.STATE_AUDIO_ONLY, getContext(), + TelecomManager.CALL_WAITING_RESPONSE_NO_POPUP_END_CALL); + mTargetTriggered = true; + break; default: // Code should never reach here. Log.e(this, "Trigger detected on unhandled resource. Skipping."); @@ -180,6 +191,7 @@ public class GlowPadWrapper extends GlowPadView implements GlowPadView.OnTrigger public interface AnswerListener { void onAnswer(int videoState, Context context); + void onAnswer(int videoState, Context context, int callWaitingResponseType); void onDecline(Context context); void onDeclineUpgradeRequest(Context context); void onText(); diff --git a/src/com/android/incallui/TelecomAdapter.java b/src/com/android/incallui/TelecomAdapter.java index 5de28f5f..ce5f75b6 100644 --- a/src/com/android/incallui/TelecomAdapter.java +++ b/src/com/android/incallui/TelecomAdapter.java @@ -68,6 +68,15 @@ final class TelecomAdapter implements InCallServiceListener { } } + void answerCall(String callId, int videoState, int callWaitingResponseType) { + android.telecom.Call call = getTelecommCallById(callId); + if (call != null) { + call.answer(videoState, callWaitingResponseType); + } else { + Log.e(this, "error answerCall, call not in call list: " + callId); + } + } + void rejectCall(String callId, boolean rejectWithMessage, String message) { android.telecom.Call call = getTelecommCallById(callId); if (call != null) { diff --git a/src/com/android/incallui/widget/multiwaveview/GlowPadView.java b/src/com/android/incallui/widget/multiwaveview/GlowPadView.java index 23200279..acbcdba6 100644 --- a/src/com/android/incallui/widget/multiwaveview/GlowPadView.java +++ b/src/com/android/incallui/widget/multiwaveview/GlowPadView.java @@ -29,6 +29,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; +import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -37,6 +38,10 @@ import android.support.v4.view.ViewCompat; import android.support.v4.view.accessibility.AccessibilityEventCompat; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; import android.support.v4.widget.ExploreByTouchHelper; +import android.text.DynamicLayout; +import android.text.Layout.Alignment; +import android.text.SpannableStringBuilder; +import android.text.TextPaint; import android.text.TextUtils; import android.util.AttributeSet; import android.util.Log; @@ -137,6 +142,14 @@ public class GlowPadView extends View { private AccessibilityNodeProvider mAccessibilityNodeProvider; private GlowpadExploreByTouchHelper mExploreByTouchHelper; + private ArrayList mTargetDisplayText; + private boolean mShowHintText = false; + private int mTargetDisplayTextResourceId; + private TextPaint mTextPaint; + private DynamicLayout mTextLayout; + private SpannableStringBuilder mDisplayText; + private int mDisplayTextWidth; + private class AnimationBundle extends ArrayList { private static final long serialVersionUID = 0xA84D78726F127468L; private boolean mSuspended; @@ -274,12 +287,36 @@ public class GlowPadView extends View { setDirectionDescriptionsResourceId(resourceId); } + // Read array of display text + if (a.getValue(R.styleable.GlowPadView_targetDisplayText, outValue)) { + final int resourceId = outValue.resourceId; + if (resourceId == 0) { + throw new IllegalStateException("Must specify display text"); + } + setTargetDisplayTextResourceId(resourceId); + } + + mTextPaint = new TextPaint(); + mTextPaint.setColor(getResources().getColor(R.color.incoming_call_display_text)); + + // This SpannableStringBuilder is used as first parameter when creating DynamicLayout. + // DynamicLayout creates instance of internal static class DynamicLayout.ChangeWatcher + // and attaches it to SpannableStringBuilder. As a result, whenever + // SpannableStringBuilder is updated, DynamicLayout receives change notification + mDisplayText = new SpannableStringBuilder(""); + + mDisplayTextWidth = (int) (getRingWidth() - mMaxTargetWidth - getResources() + .getDimensionPixelSize(R.dimen.incoming_call_widget_display_text_side_offset)); + mTextPaint.setTextSize(getResources().getDimensionPixelSize(R.dimen + .incoming_call_display_text_size)); + mTextLayout = new DynamicLayout(mDisplayText, mTextPaint, mDisplayTextWidth, + android.text.Layout.Alignment.ALIGN_CENTER, 1.0f, 0.0f, false); + // Use gravity attribute from LinearLayout //a = context.obtainStyledAttributes(attrs, R.styleable.LinearLayout); mGravity = a.getInt(R.styleable.GlowPadView_android_gravity, Gravity.TOP); a.recycle(); - setVibrateEnabled(mVibrationDuration > 0); assignDefaultsIfNeeded(); @@ -677,6 +714,18 @@ public class GlowPadView extends View { } } + /** + * Sets the resource id specifying the target display text + * + * @param resourceId The resource id. + */ + public void setTargetDisplayTextResourceId(int resourceId) { + mTargetDisplayTextResourceId = resourceId; + if (mTargetDisplayText != null) { + mTargetDisplayText.clear(); + } + } + /** * Gets the resource id specifying the target descriptions for accessibility. * @@ -943,9 +992,11 @@ public class GlowPadView extends View { if (activeTarget != -1) { switchToState(STATE_SNAP, x,y); updateGlowPosition(x, y); + mShowHintText = true; } else { switchToState(STATE_TRACKING, x, y); updateGlowPosition(x, y); + mShowHintText = false; } if (mActiveTarget != activeTarget) { @@ -1196,6 +1247,18 @@ public class GlowPadView extends View { target.draw(canvas); } } + if (mShowHintText && mActiveTarget >= 0) { + String displayText = getTargetDisplayText(mActiveTarget); + + if (displayText != null && !TextUtils.equals(displayText, mDisplayText.toString())) { + mDisplayText.replace(0, mDisplayText.length(), displayText); + } + int textHeight = mTextLayout.getHeight(); + canvas.save(); + canvas.translate(mWaveCenterX-mDisplayTextWidth/2, mWaveCenterY-textHeight/2); + mTextLayout.draw(canvas); + canvas.restore(); + } mHandleDrawable.draw(canvas); } @@ -1253,6 +1316,22 @@ public class GlowPadView extends View { return mTargetDescriptions.get(index); } + private String getTargetDisplayText(int index) { + if (mTargetDisplayText == null || mTargetDisplayText.isEmpty()) { + mTargetDisplayText = loadDescriptions(mTargetDisplayTextResourceId); + if (mTargetDrawables.size() > mTargetDisplayText.size()) { + Log.w(TAG, "The number of target drawables must be" + + " less than or equal to the number of target display text."); + return null; + } + } + if (index < mTargetDisplayText.size()) { + return mTargetDisplayText.get(index); + } else { + return null; + } + } + private String getDirectionDescription(int index) { if (mDirectionDescriptions == null || mDirectionDescriptions.isEmpty()) { mDirectionDescriptions = loadDescriptions(mDirectionDescriptionsResourceId); -- cgit v1.2.3