• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.incallui;
18 
19 import android.content.Context;
20 import android.os.Bundle;
21 import android.telephony.PhoneNumberUtils;
22 import android.util.ArrayMap;
23 import android.util.AttributeSet;
24 import android.view.KeyEvent;
25 import android.view.LayoutInflater;
26 import android.view.View;
27 import android.view.View.OnClickListener;
28 import android.view.View.OnKeyListener;
29 import android.view.ViewGroup;
30 import android.widget.EditText;
31 import android.widget.LinearLayout;
32 import android.widget.TextView;
33 import com.android.dialer.common.LogUtil;
34 import com.android.dialer.dialpadview.DialpadKeyButton;
35 import com.android.dialer.dialpadview.DialpadKeyButton.OnPressedListener;
36 import com.android.dialer.dialpadview.DialpadView;
37 import com.android.dialer.logging.DialerImpression;
38 import com.android.dialer.logging.Logger;
39 import com.android.incallui.DialpadPresenter.DialpadUi;
40 import com.android.incallui.baseui.BaseFragment;
41 import java.util.Map;
42 
43 /** Fragment for call control buttons */
44 public class DialpadFragment extends BaseFragment<DialpadPresenter, DialpadUi>
45     implements DialpadUi, OnKeyListener, OnClickListener, OnPressedListener {
46 
47   /** Hash Map to map a view id to a character */
48   private static final Map<Integer, Character> displayMap = new ArrayMap<>();
49 
50   /** Set up the static maps */
51   static {
52     // Map the buttons to the display characters
displayMap.put(R.id.one, '1')53     displayMap.put(R.id.one, '1');
displayMap.put(R.id.two, '2')54     displayMap.put(R.id.two, '2');
displayMap.put(R.id.three, '3')55     displayMap.put(R.id.three, '3');
displayMap.put(R.id.four, '4')56     displayMap.put(R.id.four, '4');
displayMap.put(R.id.five, '5')57     displayMap.put(R.id.five, '5');
displayMap.put(R.id.six, '6')58     displayMap.put(R.id.six, '6');
displayMap.put(R.id.seven, '7')59     displayMap.put(R.id.seven, '7');
displayMap.put(R.id.eight, '8')60     displayMap.put(R.id.eight, '8');
displayMap.put(R.id.nine, '9')61     displayMap.put(R.id.nine, '9');
displayMap.put(R.id.zero, '0')62     displayMap.put(R.id.zero, '0');
displayMap.put(R.id.pound, '#')63     displayMap.put(R.id.pound, '#');
displayMap.put(R.id.star, '*')64     displayMap.put(R.id.star, '*');
65   }
66 
67   private final int[] buttonIds =
68       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       };
82   private EditText dtmfDialerField;
83   // KeyListener used with the "dialpad digits" EditText widget.
84   private DtmfKeyListener dtmfKeyListener;
85   private DialpadView dialpadView;
86   private int currentTextColor;
87 
88   @Override
onClick(View v)89   public void onClick(View v) {
90     if (v.getId() == R.id.dialpad_back) {
91       Logger.get(getContext())
92           .logImpression(DialerImpression.Type.IN_CALL_DIALPAD_CLOSE_BUTTON_PRESSED);
93       getActivity().onBackPressed();
94     }
95   }
96 
97   @Override
onKey(View v, int keyCode, KeyEvent event)98   public boolean onKey(View v, int keyCode, KeyEvent event) {
99     Log.d(this, "onKey:  keyCode " + keyCode + ", view " + v);
100 
101     if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_ENTER) {
102       int viewId = v.getId();
103       if (displayMap.containsKey(viewId)) {
104         switch (event.getAction()) {
105           case KeyEvent.ACTION_DOWN:
106             if (event.getRepeatCount() == 0) {
107               getPresenter().processDtmf(displayMap.get(viewId));
108             }
109             break;
110           case KeyEvent.ACTION_UP:
111             getPresenter().stopDtmf();
112             break;
113           default: // fall out
114         }
115         // do not return true [handled] here, since we want the
116         // press / click animation to be handled by the framework.
117       }
118     }
119     return false;
120   }
121 
122   @Override
createPresenter()123   public DialpadPresenter createPresenter() {
124     return new DialpadPresenter();
125   }
126 
127   @Override
getUi()128   public DialpadPresenter.DialpadUi getUi() {
129     return this;
130   }
131 
132   // TODO(klp) Adds hardware keyboard listener
133 
134   @Override
onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)135   public View onCreateView(
136       LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
137     final View parent = inflater.inflate(R.layout.incall_dialpad_fragment, container, false);
138     dialpadView = (DialpadView) parent.findViewById(R.id.dialpad_view);
139     dialpadView.setCanDigitsBeEdited(false);
140     dialpadView.setBackgroundResource(R.color.incall_dialpad_background);
141     dtmfDialerField = (EditText) parent.findViewById(R.id.digits);
142     if (dtmfDialerField != null) {
143       LogUtil.i("DialpadFragment.onCreateView", "creating dtmfKeyListener");
144       dtmfKeyListener = new DtmfKeyListener(getPresenter());
145       dtmfDialerField.setKeyListener(dtmfKeyListener);
146       // remove the long-press context menus that support
147       // the edit (copy / paste / select) functions.
148       dtmfDialerField.setLongClickable(false);
149       dtmfDialerField.setElegantTextHeight(false);
150       configureKeypadListeners();
151     }
152     View backButton = dialpadView.findViewById(R.id.dialpad_back);
153     backButton.setVisibility(View.VISIBLE);
154     backButton.setOnClickListener(this);
155 
156     return parent;
157   }
158 
159   @Override
onResume()160   public void onResume() {
161     super.onResume();
162     updateColors();
163   }
164 
updateColors()165   public void updateColors() {
166     int textColor = InCallPresenter.getInstance().getThemeColorManager().getPrimaryColor();
167 
168     if (currentTextColor == textColor) {
169       return;
170     }
171 
172     DialpadKeyButton dialpadKey;
173     for (int i = 0; i < buttonIds.length; i++) {
174       dialpadKey = (DialpadKeyButton) dialpadView.findViewById(buttonIds[i]);
175       ((TextView) dialpadKey.findViewById(R.id.dialpad_key_number)).setTextColor(textColor);
176     }
177 
178     currentTextColor = textColor;
179   }
180 
181   @Override
onDestroyView()182   public void onDestroyView() {
183     dtmfKeyListener = null;
184     super.onDestroyView();
185   }
186 
187   /**
188    * Getter for Dialpad text.
189    *
190    * @return String containing current Dialpad EditText text.
191    */
getDtmfText()192   public String getDtmfText() {
193     return dtmfDialerField.getText().toString();
194   }
195 
196   /**
197    * Sets the Dialpad text field with some text.
198    *
199    * @param text Text to set Dialpad EditText to.
200    */
setDtmfText(String text)201   public void setDtmfText(String text) {
202     dtmfDialerField.setText(PhoneNumberUtils.createTtsSpannable(text));
203   }
204 
205   /** Starts the slide up animation for the Dialpad keys when the Dialpad is revealed. */
animateShowDialpad()206   public void animateShowDialpad() {
207     final DialpadView dialpadView = (DialpadView) getView().findViewById(R.id.dialpad_view);
208     dialpadView.animateShow();
209   }
210 
211   @Override
appendDigitsToField(char digit)212   public void appendDigitsToField(char digit) {
213     if (dtmfDialerField != null) {
214       // TODO: maybe *don't* manually append this digit if
215       // mDialpadDigits is focused and this key came from the HW
216       // keyboard, since in that case the EditText field will
217       // get the key event directly and automatically appends
218       // whetever the user types.
219       // (Or, a cleaner fix would be to just make mDialpadDigits
220       // *not* handle HW key presses.  That seems to be more
221       // complicated than just setting focusable="false" on it,
222       // though.)
223       dtmfDialerField.getText().append(digit);
224     }
225   }
226 
227   /** Called externally (from InCallScreen) to play a DTMF Tone. */
onDialerKeyDown(KeyEvent event)228   /* package */ boolean onDialerKeyDown(KeyEvent event) {
229     Log.d(this, "Notifying dtmf key down.");
230     if (dtmfKeyListener != null) {
231       return dtmfKeyListener.onKeyDown(event);
232     } else {
233       return false;
234     }
235   }
236 
237   /** Called externally (from InCallScreen) to cancel the last DTMF Tone played. */
onDialerKeyUp(KeyEvent event)238   public boolean onDialerKeyUp(KeyEvent event) {
239     Log.d(this, "Notifying dtmf key up.");
240     if (dtmfKeyListener != null) {
241       return dtmfKeyListener.onKeyUp(event);
242     } else {
243       return false;
244     }
245   }
246 
configureKeypadListeners()247   private void configureKeypadListeners() {
248     DialpadKeyButton dialpadKey;
249     for (int i = 0; i < buttonIds.length; i++) {
250       dialpadKey = (DialpadKeyButton) dialpadView.findViewById(buttonIds[i]);
251       dialpadKey.setOnKeyListener(this);
252       dialpadKey.setOnClickListener(this);
253       dialpadKey.setOnPressedListener(this);
254     }
255   }
256 
257   @Override
onPressed(View view, boolean pressed)258   public void onPressed(View view, boolean pressed) {
259     if (pressed && displayMap.containsKey(view.getId())) {
260       Logger.get(getContext())
261           .logImpression(DialerImpression.Type.IN_CALL_DIALPAD_NUMBER_BUTTON_PRESSED);
262       Log.d(this, "onPressed: " + pressed + " " + displayMap.get(view.getId()));
263       getPresenter().processDtmf(displayMap.get(view.getId()));
264     }
265     if (!pressed) {
266       Log.d(this, "onPressed: " + pressed);
267       getPresenter().stopDtmf();
268     }
269   }
270 
271   /**
272    * LinearLayout with getter and setter methods for the translationY property using floats, for
273    * animation purposes.
274    */
275   public static class DialpadSlidingLinearLayout extends LinearLayout {
276 
DialpadSlidingLinearLayout(Context context)277     public DialpadSlidingLinearLayout(Context context) {
278       super(context);
279     }
280 
DialpadSlidingLinearLayout(Context context, AttributeSet attrs)281     public DialpadSlidingLinearLayout(Context context, AttributeSet attrs) {
282       super(context, attrs);
283     }
284 
DialpadSlidingLinearLayout(Context context, AttributeSet attrs, int defStyle)285     public DialpadSlidingLinearLayout(Context context, AttributeSet attrs, int defStyle) {
286       super(context, attrs, defStyle);
287     }
288 
getYFraction()289     public float getYFraction() {
290       final int height = getHeight();
291       if (height == 0) {
292         return 0;
293       }
294       return getTranslationY() / height;
295     }
296 
setYFraction(float yFraction)297     public void setYFraction(float yFraction) {
298       setTranslationY(yFraction * getHeight());
299     }
300   }
301 }
302