blob: 343cb34fd334e2d94294708f4db673aad9b5567a [file] [log] [blame]
Eric Erfanianccca3152017-02-22 16:32:36 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.incallui;
18
19import android.content.Context;
20import android.os.Bundle;
linyuhb06d0092018-03-01 15:05:36 -080021import android.telephony.PhoneNumberUtils;
Eric Erfanianccca3152017-02-22 16:32:36 -080022import android.util.ArrayMap;
23import android.util.AttributeSet;
24import android.view.KeyEvent;
25import android.view.LayoutInflater;
26import android.view.View;
27import android.view.View.OnClickListener;
28import android.view.View.OnKeyListener;
29import android.view.ViewGroup;
30import android.widget.EditText;
31import android.widget.LinearLayout;
32import android.widget.TextView;
maxwelb5e22e802017-11-27 17:01:07 -080033import com.android.dialer.common.LogUtil;
Eric Erfanianccca3152017-02-22 16:32:36 -080034import com.android.dialer.dialpadview.DialpadKeyButton;
35import com.android.dialer.dialpadview.DialpadKeyButton.OnPressedListener;
36import com.android.dialer.dialpadview.DialpadView;
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -070037import com.android.dialer.logging.DialerImpression;
38import com.android.dialer.logging.Logger;
Eric Erfanianccca3152017-02-22 16:32:36 -080039import com.android.incallui.DialpadPresenter.DialpadUi;
40import com.android.incallui.baseui.BaseFragment;
41import java.util.Map;
42
43/** Fragment for call control buttons */
44public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
45 implements DialpadUi, OnKeyListener, OnClickListener, OnPressedListener {
46
47 /** Hash Map to map a view id to a character */
linyuh183cb712017-12-27 17:02:37 -080048 private static final Map<Integer, Character> displayMap = new ArrayMap<>();
Eric Erfanianccca3152017-02-22 16:32:36 -080049
50 /** Set up the static maps */
51 static {
52 // Map the buttons to the display characters
linyuh183cb712017-12-27 17:02:37 -080053 displayMap.put(R.id.one, '1');
54 displayMap.put(R.id.two, '2');
55 displayMap.put(R.id.three, '3');
56 displayMap.put(R.id.four, '4');
57 displayMap.put(R.id.five, '5');
58 displayMap.put(R.id.six, '6');
59 displayMap.put(R.id.seven, '7');
60 displayMap.put(R.id.eight, '8');
61 displayMap.put(R.id.nine, '9');
62 displayMap.put(R.id.zero, '0');
63 displayMap.put(R.id.pound, '#');
64 displayMap.put(R.id.star, '*');
Eric Erfanianccca3152017-02-22 16:32:36 -080065 }
66
linyuh183cb712017-12-27 17:02:37 -080067 private final int[] buttonIds =
Eric Erfanianccca3152017-02-22 16:32:36 -080068 new int[] {
69 R.id.zero,
70 R.id.one,
71 R.id.two,
72 R.id.three,
73 R.id.four,
74 R.id.five,
75 R.id.six,
76 R.id.seven,
77 R.id.eight,
78 R.id.nine,
79 R.id.star,
80 R.id.pound
81 };
linyuh183cb712017-12-27 17:02:37 -080082 private EditText dtmfDialerField;
Eric Erfanianccca3152017-02-22 16:32:36 -080083 // KeyListener used with the "dialpad digits" EditText widget.
linyuh183cb712017-12-27 17:02:37 -080084 private DtmfKeyListener dtmfKeyListener;
85 private DialpadView dialpadView;
86 private int currentTextColor;
wangqifd4c9f72018-03-08 18:21:50 -080087 private View endCallSpace;
88 private boolean shouldShowEndCallSpace = true;
Eric Erfanianccca3152017-02-22 16:32:36 -080089
90 @Override
91 public void onClick(View v) {
92 if (v.getId() == R.id.dialpad_back) {
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -070093 Logger.get(getContext())
94 .logImpression(DialerImpression.Type.IN_CALL_DIALPAD_CLOSE_BUTTON_PRESSED);
Eric Erfanianccca3152017-02-22 16:32:36 -080095 getActivity().onBackPressed();
96 }
97 }
98
99 @Override
100 public boolean onKey(View v, int keyCode, KeyEvent event) {
101 Log.d(this, "onKey: keyCode " + keyCode + ", view " + v);
102
103 if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
104 int viewId = v.getId();
linyuh183cb712017-12-27 17:02:37 -0800105 if (displayMap.containsKey(viewId)) {
Eric Erfanianccca3152017-02-22 16:32:36 -0800106 switch (event.getAction()) {
107 case KeyEvent.ACTION_DOWN:
108 if (event.getRepeatCount() == 0) {
linyuh183cb712017-12-27 17:02:37 -0800109 getPresenter().processDtmf(displayMap.get(viewId));
Eric Erfanianccca3152017-02-22 16:32:36 -0800110 }
111 break;
112 case KeyEvent.ACTION_UP:
113 getPresenter().stopDtmf();
114 break;
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -0700115 default: // fall out
Eric Erfanianccca3152017-02-22 16:32:36 -0800116 }
117 // do not return true [handled] here, since we want the
118 // press / click animation to be handled by the framework.
119 }
120 }
121 return false;
122 }
123
124 @Override
125 public DialpadPresenter createPresenter() {
126 return new DialpadPresenter();
127 }
128
129 @Override
130 public DialpadPresenter.DialpadUi getUi() {
131 return this;
132 }
133
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -0700134 // TODO(klp) Adds hardware keyboard listener
Eric Erfanianccca3152017-02-22 16:32:36 -0800135
136 @Override
137 public View onCreateView(
138 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
139 final View parent = inflater.inflate(R.layout.incall_dialpad_fragment, container, false);
linyuh183cb712017-12-27 17:02:37 -0800140 dialpadView = (DialpadView) parent.findViewById(R.id.dialpad_view);
141 dialpadView.setCanDigitsBeEdited(false);
142 dialpadView.setBackgroundResource(R.color.incall_dialpad_background);
143 dtmfDialerField = (EditText) parent.findViewById(R.id.digits);
144 if (dtmfDialerField != null) {
maxwelb5e22e802017-11-27 17:01:07 -0800145 LogUtil.i("DialpadFragment.onCreateView", "creating dtmfKeyListener");
linyuh183cb712017-12-27 17:02:37 -0800146 dtmfKeyListener = new DtmfKeyListener(getPresenter());
147 dtmfDialerField.setKeyListener(dtmfKeyListener);
Eric Erfanianccca3152017-02-22 16:32:36 -0800148 // remove the long-press context menus that support
149 // the edit (copy / paste / select) functions.
linyuh183cb712017-12-27 17:02:37 -0800150 dtmfDialerField.setLongClickable(false);
151 dtmfDialerField.setElegantTextHeight(false);
Eric Erfanianccca3152017-02-22 16:32:36 -0800152 configureKeypadListeners();
153 }
linyuh183cb712017-12-27 17:02:37 -0800154 View backButton = dialpadView.findViewById(R.id.dialpad_back);
Eric Erfanianccca3152017-02-22 16:32:36 -0800155 backButton.setVisibility(View.VISIBLE);
156 backButton.setOnClickListener(this);
wangqifd4c9f72018-03-08 18:21:50 -0800157 endCallSpace = dialpadView.findViewById(R.id.end_call_space);
Eric Erfanianccca3152017-02-22 16:32:36 -0800158
159 return parent;
160 }
161
162 @Override
163 public void onResume() {
164 super.onResume();
165 updateColors();
wangqifd4c9f72018-03-08 18:21:50 -0800166 endCallSpace.setVisibility(shouldShowEndCallSpace ? View.VISIBLE : View.GONE);
Eric Erfanianccca3152017-02-22 16:32:36 -0800167 }
168
169 public void updateColors() {
170 int textColor = InCallPresenter.getInstance().getThemeColorManager().getPrimaryColor();
171
linyuh183cb712017-12-27 17:02:37 -0800172 if (currentTextColor == textColor) {
Eric Erfanianccca3152017-02-22 16:32:36 -0800173 return;
174 }
175
176 DialpadKeyButton dialpadKey;
linyuh183cb712017-12-27 17:02:37 -0800177 for (int i = 0; i < buttonIds.length; i++) {
178 dialpadKey = (DialpadKeyButton) dialpadView.findViewById(buttonIds[i]);
Eric Erfanianccca3152017-02-22 16:32:36 -0800179 ((TextView) dialpadKey.findViewById(R.id.dialpad_key_number)).setTextColor(textColor);
180 }
181
linyuh183cb712017-12-27 17:02:37 -0800182 currentTextColor = textColor;
Eric Erfanianccca3152017-02-22 16:32:36 -0800183 }
184
185 @Override
186 public void onDestroyView() {
linyuh183cb712017-12-27 17:02:37 -0800187 dtmfKeyListener = null;
Eric Erfanianccca3152017-02-22 16:32:36 -0800188 super.onDestroyView();
189 }
190
191 /**
192 * Getter for Dialpad text.
193 *
194 * @return String containing current Dialpad EditText text.
195 */
196 public String getDtmfText() {
linyuh183cb712017-12-27 17:02:37 -0800197 return dtmfDialerField.getText().toString();
Eric Erfanianccca3152017-02-22 16:32:36 -0800198 }
199
200 /**
201 * Sets the Dialpad text field with some text.
202 *
203 * @param text Text to set Dialpad EditText to.
204 */
205 public void setDtmfText(String text) {
linyuhb06d0092018-03-01 15:05:36 -0800206 dtmfDialerField.setText(PhoneNumberUtils.createTtsSpannable(text));
Eric Erfanianccca3152017-02-22 16:32:36 -0800207 }
208
Eric Erfanianccca3152017-02-22 16:32:36 -0800209 /** Starts the slide up animation for the Dialpad keys when the Dialpad is revealed. */
210 public void animateShowDialpad() {
211 final DialpadView dialpadView = (DialpadView) getView().findViewById(R.id.dialpad_view);
212 dialpadView.animateShow();
213 }
214
215 @Override
216 public void appendDigitsToField(char digit) {
linyuh183cb712017-12-27 17:02:37 -0800217 if (dtmfDialerField != null) {
Eric Erfanianccca3152017-02-22 16:32:36 -0800218 // TODO: maybe *don't* manually append this digit if
219 // mDialpadDigits is focused and this key came from the HW
220 // keyboard, since in that case the EditText field will
221 // get the key event directly and automatically appends
222 // whetever the user types.
223 // (Or, a cleaner fix would be to just make mDialpadDigits
224 // *not* handle HW key presses. That seems to be more
225 // complicated than just setting focusable="false" on it,
226 // though.)
linyuh183cb712017-12-27 17:02:37 -0800227 dtmfDialerField.getText().append(digit);
Eric Erfanianccca3152017-02-22 16:32:36 -0800228 }
229 }
230
231 /** Called externally (from InCallScreen) to play a DTMF Tone. */
232 /* package */ boolean onDialerKeyDown(KeyEvent event) {
233 Log.d(this, "Notifying dtmf key down.");
linyuh183cb712017-12-27 17:02:37 -0800234 if (dtmfKeyListener != null) {
235 return dtmfKeyListener.onKeyDown(event);
Eric Erfanianccca3152017-02-22 16:32:36 -0800236 } else {
237 return false;
238 }
239 }
240
241 /** Called externally (from InCallScreen) to cancel the last DTMF Tone played. */
242 public boolean onDialerKeyUp(KeyEvent event) {
243 Log.d(this, "Notifying dtmf key up.");
linyuh183cb712017-12-27 17:02:37 -0800244 if (dtmfKeyListener != null) {
245 return dtmfKeyListener.onKeyUp(event);
Eric Erfanianccca3152017-02-22 16:32:36 -0800246 } else {
247 return false;
248 }
249 }
250
251 private void configureKeypadListeners() {
252 DialpadKeyButton dialpadKey;
linyuh183cb712017-12-27 17:02:37 -0800253 for (int i = 0; i < buttonIds.length; i++) {
254 dialpadKey = (DialpadKeyButton) dialpadView.findViewById(buttonIds[i]);
Eric Erfanianccca3152017-02-22 16:32:36 -0800255 dialpadKey.setOnKeyListener(this);
256 dialpadKey.setOnClickListener(this);
257 dialpadKey.setOnPressedListener(this);
258 }
259 }
260
261 @Override
262 public void onPressed(View view, boolean pressed) {
linyuh183cb712017-12-27 17:02:37 -0800263 if (pressed && displayMap.containsKey(view.getId())) {
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -0700264 Logger.get(getContext())
265 .logImpression(DialerImpression.Type.IN_CALL_DIALPAD_NUMBER_BUTTON_PRESSED);
linyuh183cb712017-12-27 17:02:37 -0800266 Log.d(this, "onPressed: " + pressed + " " + displayMap.get(view.getId()));
267 getPresenter().processDtmf(displayMap.get(view.getId()));
Eric Erfanianccca3152017-02-22 16:32:36 -0800268 }
269 if (!pressed) {
270 Log.d(this, "onPressed: " + pressed);
271 getPresenter().stopDtmf();
272 }
273 }
274
wangqifd4c9f72018-03-08 18:21:50 -0800275 public void setShouldShowEndCallSpace(boolean show) {
276 shouldShowEndCallSpace = show;
277 }
278
Eric Erfanianccca3152017-02-22 16:32:36 -0800279 /**
280 * LinearLayout with getter and setter methods for the translationY property using floats, for
281 * animation purposes.
282 */
283 public static class DialpadSlidingLinearLayout extends LinearLayout {
284
285 public DialpadSlidingLinearLayout(Context context) {
286 super(context);
287 }
288
289 public DialpadSlidingLinearLayout(Context context, AttributeSet attrs) {
290 super(context, attrs);
291 }
292
293 public DialpadSlidingLinearLayout(Context context, AttributeSet attrs, int defStyle) {
294 super(context, attrs, defStyle);
295 }
296
297 public float getYFraction() {
298 final int height = getHeight();
299 if (height == 0) {
300 return 0;
301 }
302 return getTranslationY() / height;
303 }
304
305 public void setYFraction(float yFraction) {
306 setTranslationY(yFraction * getHeight());
307 }
308 }
Eric Erfanianccca3152017-02-22 16:32:36 -0800309}