blob: 6be923cfb2b0789c77243d8f84a8782f6d72b365 [file] [log] [blame]
/*
* 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);
}
}
}