blob: 2ae2aca947b1ab2caa783f12912ed8000f60b7b3 [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;
wangqi70189d82018-05-29 18:08:16 -070024import android.view.ContextThemeWrapper;
Eric Erfanianccca3152017-02-22 16:32:36 -080025import android.view.KeyEvent;
26import android.view.LayoutInflater;
27import android.view.View;
28import android.view.View.OnClickListener;
29import android.view.View.OnKeyListener;
30import android.view.ViewGroup;
31import android.widget.EditText;
32import android.widget.LinearLayout;
33import android.widget.TextView;
maxwelb5e22e802017-11-27 17:01:07 -080034import com.android.dialer.common.LogUtil;
Eric Erfanianccca3152017-02-22 16:32:36 -080035import com.android.dialer.dialpadview.DialpadKeyButton;
36import com.android.dialer.dialpadview.DialpadKeyButton.OnPressedListener;
37import com.android.dialer.dialpadview.DialpadView;
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -070038import com.android.dialer.logging.DialerImpression;
39import com.android.dialer.logging.Logger;
Eric Erfanianccca3152017-02-22 16:32:36 -080040import com.android.incallui.DialpadPresenter.DialpadUi;
41import com.android.incallui.baseui.BaseFragment;
42import java.util.Map;
43
44/** Fragment for call control buttons */
45public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
46 implements DialpadUi, OnKeyListener, OnClickListener, OnPressedListener {
47
48 /** Hash Map to map a view id to a character */
linyuh183cb712017-12-27 17:02:37 -080049 private static final Map<Integer, Character> displayMap = new ArrayMap<>();
Eric Erfanianccca3152017-02-22 16:32:36 -080050
51 /** Set up the static maps */
52 static {
53 // Map the buttons to the display characters
linyuh183cb712017-12-27 17:02:37 -080054 displayMap.put(R.id.one, '1');
55 displayMap.put(R.id.two, '2');
56 displayMap.put(R.id.three, '3');
57 displayMap.put(R.id.four, '4');
58 displayMap.put(R.id.five, '5');
59 displayMap.put(R.id.six, '6');
60 displayMap.put(R.id.seven, '7');
61 displayMap.put(R.id.eight, '8');
62 displayMap.put(R.id.nine, '9');
63 displayMap.put(R.id.zero, '0');
64 displayMap.put(R.id.pound, '#');
65 displayMap.put(R.id.star, '*');
Eric Erfanianccca3152017-02-22 16:32:36 -080066 }
67
linyuh183cb712017-12-27 17:02:37 -080068 private final int[] buttonIds =
Eric Erfanianccca3152017-02-22 16:32:36 -080069 new int[] {
70 R.id.zero,
71 R.id.one,
72 R.id.two,
73 R.id.three,
74 R.id.four,
75 R.id.five,
76 R.id.six,
77 R.id.seven,
78 R.id.eight,
79 R.id.nine,
80 R.id.star,
81 R.id.pound
82 };
linyuh183cb712017-12-27 17:02:37 -080083 private EditText dtmfDialerField;
Eric Erfanianccca3152017-02-22 16:32:36 -080084 // KeyListener used with the "dialpad digits" EditText widget.
linyuh183cb712017-12-27 17:02:37 -080085 private DtmfKeyListener dtmfKeyListener;
86 private DialpadView dialpadView;
87 private int currentTextColor;
wangqifd4c9f72018-03-08 18:21:50 -080088 private View endCallSpace;
89 private boolean shouldShowEndCallSpace = true;
Eric Erfanianccca3152017-02-22 16:32:36 -080090
91 @Override
92 public void onClick(View v) {
93 if (v.getId() == R.id.dialpad_back) {
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -070094 Logger.get(getContext())
95 .logImpression(DialerImpression.Type.IN_CALL_DIALPAD_CLOSE_BUTTON_PRESSED);
Eric Erfanianccca3152017-02-22 16:32:36 -080096 getActivity().onBackPressed();
97 }
98 }
99
100 @Override
101 public boolean onKey(View v, int keyCode, KeyEvent event) {
102 Log.d(this, "onKey: keyCode " + keyCode + ", view " + v);
103
104 if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
105 int viewId = v.getId();
linyuh183cb712017-12-27 17:02:37 -0800106 if (displayMap.containsKey(viewId)) {
Eric Erfanianccca3152017-02-22 16:32:36 -0800107 switch (event.getAction()) {
108 case KeyEvent.ACTION_DOWN:
109 if (event.getRepeatCount() == 0) {
linyuh183cb712017-12-27 17:02:37 -0800110 getPresenter().processDtmf(displayMap.get(viewId));
Eric Erfanianccca3152017-02-22 16:32:36 -0800111 }
112 break;
113 case KeyEvent.ACTION_UP:
114 getPresenter().stopDtmf();
115 break;
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -0700116 default: // fall out
Eric Erfanianccca3152017-02-22 16:32:36 -0800117 }
118 // do not return true [handled] here, since we want the
119 // press / click animation to be handled by the framework.
120 }
121 }
122 return false;
123 }
124
125 @Override
126 public DialpadPresenter createPresenter() {
127 return new DialpadPresenter();
128 }
129
130 @Override
131 public DialpadPresenter.DialpadUi getUi() {
132 return this;
133 }
134
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -0700135 // TODO(klp) Adds hardware keyboard listener
Eric Erfanianccca3152017-02-22 16:32:36 -0800136
137 @Override
138 public View onCreateView(
139 LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
wangqi70189d82018-05-29 18:08:16 -0700140 Context contextThemeWrapper = new ContextThemeWrapper(getActivity(), R.style.Dialer_ThemeBase);
141 LayoutInflater layoutInflater = inflater.cloneInContext(contextThemeWrapper);
142 final View parent = layoutInflater.inflate(R.layout.incall_dialpad_fragment, container, false);
linyuh183cb712017-12-27 17:02:37 -0800143 dialpadView = (DialpadView) parent.findViewById(R.id.dialpad_view);
144 dialpadView.setCanDigitsBeEdited(false);
145 dialpadView.setBackgroundResource(R.color.incall_dialpad_background);
146 dtmfDialerField = (EditText) parent.findViewById(R.id.digits);
147 if (dtmfDialerField != null) {
maxwelb5e22e802017-11-27 17:01:07 -0800148 LogUtil.i("DialpadFragment.onCreateView", "creating dtmfKeyListener");
linyuh183cb712017-12-27 17:02:37 -0800149 dtmfKeyListener = new DtmfKeyListener(getPresenter());
150 dtmfDialerField.setKeyListener(dtmfKeyListener);
Eric Erfanianccca3152017-02-22 16:32:36 -0800151 // remove the long-press context menus that support
152 // the edit (copy / paste / select) functions.
linyuh183cb712017-12-27 17:02:37 -0800153 dtmfDialerField.setLongClickable(false);
154 dtmfDialerField.setElegantTextHeight(false);
Eric Erfanianccca3152017-02-22 16:32:36 -0800155 configureKeypadListeners();
156 }
linyuh183cb712017-12-27 17:02:37 -0800157 View backButton = dialpadView.findViewById(R.id.dialpad_back);
Eric Erfanianccca3152017-02-22 16:32:36 -0800158 backButton.setVisibility(View.VISIBLE);
159 backButton.setOnClickListener(this);
wangqifd4c9f72018-03-08 18:21:50 -0800160 endCallSpace = dialpadView.findViewById(R.id.end_call_space);
Eric Erfanianccca3152017-02-22 16:32:36 -0800161
162 return parent;
163 }
164
165 @Override
166 public void onResume() {
167 super.onResume();
168 updateColors();
wangqifd4c9f72018-03-08 18:21:50 -0800169 endCallSpace.setVisibility(shouldShowEndCallSpace ? View.VISIBLE : View.GONE);
Eric Erfanianccca3152017-02-22 16:32:36 -0800170 }
171
172 public void updateColors() {
173 int textColor = InCallPresenter.getInstance().getThemeColorManager().getPrimaryColor();
174
linyuh183cb712017-12-27 17:02:37 -0800175 if (currentTextColor == textColor) {
Eric Erfanianccca3152017-02-22 16:32:36 -0800176 return;
177 }
178
179 DialpadKeyButton dialpadKey;
linyuh183cb712017-12-27 17:02:37 -0800180 for (int i = 0; i < buttonIds.length; i++) {
181 dialpadKey = (DialpadKeyButton) dialpadView.findViewById(buttonIds[i]);
Eric Erfanianccca3152017-02-22 16:32:36 -0800182 ((TextView) dialpadKey.findViewById(R.id.dialpad_key_number)).setTextColor(textColor);
183 }
184
linyuh183cb712017-12-27 17:02:37 -0800185 currentTextColor = textColor;
Eric Erfanianccca3152017-02-22 16:32:36 -0800186 }
187
188 @Override
189 public void onDestroyView() {
linyuh183cb712017-12-27 17:02:37 -0800190 dtmfKeyListener = null;
Eric Erfanianccca3152017-02-22 16:32:36 -0800191 super.onDestroyView();
192 }
193
194 /**
195 * Getter for Dialpad text.
196 *
197 * @return String containing current Dialpad EditText text.
198 */
199 public String getDtmfText() {
linyuh183cb712017-12-27 17:02:37 -0800200 return dtmfDialerField.getText().toString();
Eric Erfanianccca3152017-02-22 16:32:36 -0800201 }
202
203 /**
204 * Sets the Dialpad text field with some text.
205 *
206 * @param text Text to set Dialpad EditText to.
207 */
208 public void setDtmfText(String text) {
linyuhb06d0092018-03-01 15:05:36 -0800209 dtmfDialerField.setText(PhoneNumberUtils.createTtsSpannable(text));
Eric Erfanianccca3152017-02-22 16:32:36 -0800210 }
211
Eric Erfanianccca3152017-02-22 16:32:36 -0800212 /** Starts the slide up animation for the Dialpad keys when the Dialpad is revealed. */
213 public void animateShowDialpad() {
214 final DialpadView dialpadView = (DialpadView) getView().findViewById(R.id.dialpad_view);
215 dialpadView.animateShow();
216 }
217
218 @Override
219 public void appendDigitsToField(char digit) {
linyuh183cb712017-12-27 17:02:37 -0800220 if (dtmfDialerField != null) {
Eric Erfanianccca3152017-02-22 16:32:36 -0800221 // TODO: maybe *don't* manually append this digit if
222 // mDialpadDigits is focused and this key came from the HW
223 // keyboard, since in that case the EditText field will
224 // get the key event directly and automatically appends
225 // whetever the user types.
226 // (Or, a cleaner fix would be to just make mDialpadDigits
227 // *not* handle HW key presses. That seems to be more
228 // complicated than just setting focusable="false" on it,
229 // though.)
linyuh183cb712017-12-27 17:02:37 -0800230 dtmfDialerField.getText().append(digit);
Eric Erfanianccca3152017-02-22 16:32:36 -0800231 }
232 }
233
234 /** Called externally (from InCallScreen) to play a DTMF Tone. */
235 /* package */ boolean onDialerKeyDown(KeyEvent event) {
236 Log.d(this, "Notifying dtmf key down.");
linyuh183cb712017-12-27 17:02:37 -0800237 if (dtmfKeyListener != null) {
238 return dtmfKeyListener.onKeyDown(event);
Eric Erfanianccca3152017-02-22 16:32:36 -0800239 } else {
240 return false;
241 }
242 }
243
244 /** Called externally (from InCallScreen) to cancel the last DTMF Tone played. */
245 public boolean onDialerKeyUp(KeyEvent event) {
246 Log.d(this, "Notifying dtmf key up.");
linyuh183cb712017-12-27 17:02:37 -0800247 if (dtmfKeyListener != null) {
248 return dtmfKeyListener.onKeyUp(event);
Eric Erfanianccca3152017-02-22 16:32:36 -0800249 } else {
250 return false;
251 }
252 }
253
254 private void configureKeypadListeners() {
255 DialpadKeyButton dialpadKey;
linyuh183cb712017-12-27 17:02:37 -0800256 for (int i = 0; i < buttonIds.length; i++) {
257 dialpadKey = (DialpadKeyButton) dialpadView.findViewById(buttonIds[i]);
Eric Erfanianccca3152017-02-22 16:32:36 -0800258 dialpadKey.setOnKeyListener(this);
259 dialpadKey.setOnClickListener(this);
260 dialpadKey.setOnPressedListener(this);
261 }
262 }
263
264 @Override
265 public void onPressed(View view, boolean pressed) {
linyuh183cb712017-12-27 17:02:37 -0800266 if (pressed && displayMap.containsKey(view.getId())) {
Eric Erfanianfc0eb8c2017-08-31 06:57:16 -0700267 Logger.get(getContext())
268 .logImpression(DialerImpression.Type.IN_CALL_DIALPAD_NUMBER_BUTTON_PRESSED);
linyuh183cb712017-12-27 17:02:37 -0800269 Log.d(this, "onPressed: " + pressed + " " + displayMap.get(view.getId()));
270 getPresenter().processDtmf(displayMap.get(view.getId()));
Eric Erfanianccca3152017-02-22 16:32:36 -0800271 }
272 if (!pressed) {
273 Log.d(this, "onPressed: " + pressed);
274 getPresenter().stopDtmf();
275 }
276 }
277
wangqifd4c9f72018-03-08 18:21:50 -0800278 public void setShouldShowEndCallSpace(boolean show) {
279 shouldShowEndCallSpace = show;
280 }
281
Eric Erfanianccca3152017-02-22 16:32:36 -0800282 /**
283 * LinearLayout with getter and setter methods for the translationY property using floats, for
284 * animation purposes.
285 */
286 public static class DialpadSlidingLinearLayout extends LinearLayout {
287
288 public DialpadSlidingLinearLayout(Context context) {
289 super(context);
290 }
291
292 public DialpadSlidingLinearLayout(Context context, AttributeSet attrs) {
293 super(context, attrs);
294 }
295
296 public DialpadSlidingLinearLayout(Context context, AttributeSet attrs, int defStyle) {
297 super(context, attrs, defStyle);
298 }
299
300 public float getYFraction() {
301 final int height = getHeight();
302 if (height == 0) {
303 return 0;
304 }
305 return getTranslationY() / height;
306 }
307
308 public void setYFraction(float yFraction) {
309 setTranslationY(yFraction * getHeight());
310 }
311 }
Eric Erfanianccca3152017-02-22 16:32:36 -0800312}