| /* |
| * Copyright (C) 2013 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.incallui; |
| |
| import android.content.Context; |
| import android.os.Bundle; |
| import android.view.KeyEvent; |
| import android.view.LayoutInflater; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.accessibility.AccessibilityManager; |
| import android.widget.EditText; |
| |
| import java.util.HashMap; |
| |
| /** |
| * Fragment for call control buttons |
| */ |
| public class DialpadFragment extends BaseFragment<DialpadPresenter> |
| implements DialpadPresenter.DialpadUi, View.OnTouchListener, View.OnKeyListener, |
| View.OnHoverListener, View.OnClickListener { |
| |
| private EditText mDtmfDialerField; |
| |
| /** Hash Map to map a view id to a character*/ |
| private static final HashMap<Integer, Character> mDisplayMap = |
| new HashMap<Integer, Character>(); |
| |
| /** Set up the static maps*/ |
| static { |
| // Map the buttons to the display characters |
| mDisplayMap.put(R.id.one, '1'); |
| mDisplayMap.put(R.id.two, '2'); |
| mDisplayMap.put(R.id.three, '3'); |
| mDisplayMap.put(R.id.four, '4'); |
| mDisplayMap.put(R.id.five, '5'); |
| mDisplayMap.put(R.id.six, '6'); |
| mDisplayMap.put(R.id.seven, '7'); |
| mDisplayMap.put(R.id.eight, '8'); |
| mDisplayMap.put(R.id.nine, '9'); |
| mDisplayMap.put(R.id.zero, '0'); |
| mDisplayMap.put(R.id.pound, '#'); |
| mDisplayMap.put(R.id.star, '*'); |
| } |
| |
| @Override |
| public void onClick(View v) { |
| Logger.d(this, "onClick"); |
| final AccessibilityManager accessibilityManager = (AccessibilityManager) |
| getActivity().getSystemService(Context.ACCESSIBILITY_SERVICE); |
| // When accessibility is on, simulate press and release to preserve the |
| // semantic meaning of performClick(). Required for Braille support. |
| if (accessibilityManager.isEnabled()) { |
| final int id = v.getId(); |
| // Checking the press state prevents double activation. |
| if (!v.isPressed() && mDisplayMap.containsKey(id)) { |
| getPresenter().processDtmf(mDisplayMap.get(id), true /* timedShortTone */); |
| } |
| } |
| } |
| |
| @Override |
| public boolean onHover(View v, MotionEvent event) { |
| // When touch exploration is turned on, lifting a finger while inside |
| // the button's hover target bounds should perform a click action. |
| final AccessibilityManager accessibilityManager = (AccessibilityManager) |
| getActivity().getSystemService(Context.ACCESSIBILITY_SERVICE); |
| |
| if (accessibilityManager.isEnabled() |
| && accessibilityManager.isTouchExplorationEnabled()) { |
| final int left = v.getPaddingLeft(); |
| final int right = (v.getWidth() - v.getPaddingRight()); |
| final int top = v.getPaddingTop(); |
| final int bottom = (v.getHeight() - v.getPaddingBottom()); |
| |
| switch (event.getActionMasked()) { |
| case MotionEvent.ACTION_HOVER_ENTER: |
| // Lift-to-type temporarily disables double-tap activation. |
| v.setClickable(false); |
| break; |
| case MotionEvent.ACTION_HOVER_EXIT: |
| final int x = (int) event.getX(); |
| final int y = (int) event.getY(); |
| if ((x > left) && (x < right) && (y > top) && (y < bottom)) { |
| v.performClick(); |
| } |
| v.setClickable(true); |
| break; |
| } |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public boolean onKey(View v, int keyCode, KeyEvent event) { |
| Logger.d(this, "onKey: keyCode " + keyCode + ", view " + v); |
| |
| if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) { |
| int viewId = v.getId(); |
| if (mDisplayMap.containsKey(viewId)) { |
| switch (event.getAction()) { |
| case KeyEvent.ACTION_DOWN: |
| if (event.getRepeatCount() == 0) { |
| getPresenter().processDtmf(mDisplayMap.get(viewId)); |
| } |
| break; |
| case KeyEvent.ACTION_UP: |
| getPresenter().stopTone(); |
| break; |
| } |
| // do not return true [handled] here, since we want the |
| // press / click animation to be handled by the framework. |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean onTouch(View v, MotionEvent event) { |
| Logger.d(this, "onTouch"); |
| int viewId = v.getId(); |
| |
| // if the button is recognized |
| if (mDisplayMap.containsKey(viewId)) { |
| switch (event.getAction()) { |
| case MotionEvent.ACTION_DOWN: |
| // Append the character mapped to this button, to the display. |
| // start the tone |
| getPresenter().processDtmf(mDisplayMap.get(viewId)); |
| break; |
| case MotionEvent.ACTION_UP: |
| case MotionEvent.ACTION_CANCEL: |
| // stop the tone on ANY other event, except for MOVE. |
| getPresenter().stopTone(); |
| break; |
| } |
| // do not return true [handled] here, since we want the |
| // press / click animation to be handled by the framework. |
| } |
| return false; |
| } |
| |
| // TODO(klp) Adds hardware keyboard listener |
| |
| @Override |
| DialpadPresenter createPresenter() { |
| return new DialpadPresenter(); |
| } |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| } |
| |
| @Override |
| public View onCreateView(LayoutInflater inflater, ViewGroup container, |
| Bundle savedInstanceState) { |
| final View parent = inflater.inflate( |
| com.android.incallui.R.layout.dtmf_twelve_key_dialer_view, container, false); |
| mDtmfDialerField = (EditText) parent.findViewById(R.id.dtmfDialerField); |
| if (mDtmfDialerField != null) { |
| // remove the long-press context menus that support |
| // the edit (copy / paste / select) functions. |
| mDtmfDialerField.setLongClickable(false); |
| |
| setupKeypad(parent); |
| } |
| getPresenter().onUiReady(this); |
| return parent; |
| } |
| |
| @Override |
| public void setVisible(boolean on) { |
| if (on) { |
| getView().setVisibility(View.VISIBLE); |
| } else { |
| getView().setVisibility(View.INVISIBLE); |
| } |
| } |
| |
| @Override |
| public void appendDigitsToField(char digit) { |
| if (mDtmfDialerField != null) { |
| // TODO: maybe *don't* manually append this digit if |
| // mDialpadDigits is focused and this key came from the HW |
| // keyboard, since in that case the EditText field will |
| // get the key event directly and automatically appends |
| // whetever the user types. |
| // (Or, a cleaner fix would be to just make mDialpadDigits |
| // *not* handle HW key presses. That seems to be more |
| // complicated than just setting focusable="false" on it, |
| // though.) |
| mDtmfDialerField.getText().append(digit); |
| } |
| } |
| |
| /** |
| * setup the keys on the dialer activity, using the keymaps. |
| */ |
| private void setupKeypad(View parent) { |
| // for each view id listed in the displaymap |
| View button; |
| for (int viewId : mDisplayMap.keySet()) { |
| // locate the view |
| button = parent.findViewById(viewId); |
| // Setup the listeners for the buttons |
| button.setOnTouchListener(this); |
| button.setClickable(true); |
| button.setOnKeyListener(this); |
| button.setOnHoverListener(this); |
| button.setOnClickListener(this); |
| } |
| } |
| } |