아래 소스에서 view group에서 상속받은 (class InCallMenuView extends ViewGroup)를 아래와 같이 표시하니까 폰이 죽어버리는데요.
어떻게 화면에 표시할 수 있을까요?
=======================================
setContentView(mInCallMenuView);
======================================
package com.callingmenu;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class CallingMenu extends Activity {
InCallMenuItemView mManageConference;
InCallMenuItemView mShowDialpad;
InCallMenuItemView mEndCall;
InCallMenuItemView mAddCall;
InCallMenuItemView mSwapCalls;
InCallMenuItemView mMergeCalls;
InCallMenuItemView mBluetooth;
InCallMenuItemView mSpeaker;
InCallMenuItemView mMute;
InCallMenuItemView mHold;
InCallMenuItemView mAnswerAndHold;
InCallMenuItemView mAnswerAndEnd;
InCallMenuItemView mAnswer;
InCallMenuItemView mIgnore;
private InCallMenuView mInCallMenuView;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Context wrappedContext = new ContextThemeWrapper(
this,
com.android.internal.R.style.Theme_IconMenu);
mManageConference = new InCallMenuItemView(wrappedContext);
mManageConference.setId(R.id.menuManageConference);
// mManageConference.setOnClickListener(mInCallScreen);
mManageConference.setText(R.string.menu_manageConference);
mManageConference.setIconResource(com.android.internal.R.drawable.ic_menu_allfriends);
mShowDialpad = new InCallMenuItemView(wrappedContext);
mShowDialpad.setId(R.id.menuShowDialpad);
// mShowDialpad.setOnClickListener(mInCallScreen);
mShowDialpad.setText(R.string.menu_showDialpad); // or "Hide dialpad" if it's open
mShowDialpad.setIconResource(R.drawable.ic_menu_dial_pad);
mEndCall = new InCallMenuItemView(wrappedContext);
mEndCall.setId(R.id.menuEndCall);
// mEndCall.setOnClickListener(mInCallScreen);
mEndCall.setText(R.string.menu_endCall);
mEndCall.setIconResource(R.drawable.ic_menu_end_call);
mAddCall = new InCallMenuItemView(wrappedContext);
mAddCall.setId(R.id.menuAddCall);
// mAddCall.setOnClickListener(mInCallScreen);
mAddCall.setText(R.string.menu_addCall);
mAddCall.setIconResource(android.R.drawable.ic_menu_add);
mSwapCalls = new InCallMenuItemView(wrappedContext);
mSwapCalls.setId(R.id.menuSwapCalls);
// mSwapCalls.setOnClickListener(mInCallScreen);
mSwapCalls.setText(R.string.menu_swapCalls);
mSwapCalls.setIconResource(R.drawable.ic_menu_swap_calls);
mMergeCalls = new InCallMenuItemView(wrappedContext);
mMergeCalls.setId(R.id.menuMergeCalls);
// mMergeCalls.setOnClickListener(mInCallScreen);
mMergeCalls.setText(R.string.menu_mergeCalls);
mMergeCalls.setIconResource(R.drawable.ic_menu_merge_calls);
// TODO: Icons for menu items we don't have yet:
// R.drawable.ic_menu_answer_call
// R.drawable.ic_menu_silence_ringer
mBluetooth = new InCallMenuItemView(wrappedContext);
mBluetooth.setId(R.id.menuBluetooth);
// mBluetooth.setOnClickListener(mInCallScreen);
mBluetooth.setText(R.string.menu_bluetooth);
mBluetooth.setIndicatorVisible(true);
mSpeaker = new InCallMenuItemView(wrappedContext);
mSpeaker.setId(R.id.menuSpeaker);
// mSpeaker.setOnClickListener(mInCallScreen);
mSpeaker.setText(R.string.menu_speaker);
mSpeaker.setIndicatorVisible(true);
mMute = new InCallMenuItemView(wrappedContext);
mMute.setId(R.id.menuMute);
// mMute.setOnClickListener(mInCallScreen);
mMute.setText(R.string.menu_mute);
mMute.setIndicatorVisible(true);
mHold = new InCallMenuItemView(wrappedContext);
mHold.setId(R.id.menuHold);
// mHold.setOnClickListener(mInCallScreen);
mHold.setText(R.string.menu_hold);
mHold.setIndicatorVisible(true);
mAnswerAndHold = new InCallMenuItemView(wrappedContext);
mAnswerAndHold.setId(R.id.menuAnswerAndHold);
// mAnswerAndHold.setOnClickListener(mInCallScreen);
mAnswerAndHold.setText(R.string.menu_answerAndHold);
mAnswerAndEnd = new InCallMenuItemView(wrappedContext);
mAnswerAndEnd.setId(R.id.menuAnswerAndEnd);
// mAnswerAndEnd.setOnClickListener(mInCallScreen);
mAnswerAndEnd.setText(R.string.menu_answerAndEnd);
mAnswer = new InCallMenuItemView(wrappedContext);
mAnswer.setId(R.id.menuAnswer);
// mAnswer.setOnClickListener(mInCallScreen);
mAnswer.setText(R.string.menu_answer);
mIgnore = new InCallMenuItemView(wrappedContext);
mIgnore.setId(R.id.menuIgnore);
// mIgnore.setOnClickListener(mInCallScreen);
mIgnore.setText(R.string.menu_ignore);
mInCallMenuView = new InCallMenuView(wrappedContext, this);
mInCallMenuView.updateVisibility();
// mInCallMenuView.addItemView(mSwapCalls, 0);
// mInCallMenuView.addItemView(mShowDialpad, 0);
setContentView(mInCallMenuView);
}
class InCallMenuItemView extends TextView {
private static final String LOG_TAG = "PHONE/InCallMenuItemView";
private static final boolean DBG = false;
private boolean mIndicatorVisible;
private boolean mIndicatorState;
private Drawable mIndicatorDrawable;
private Drawable mIcon;
public InCallMenuItemView(Context context) {
super(context);
if (DBG) log("InCallMenuView constructor...");
setGravity(Gravity.CENTER);
TypedArray a =
context.obtainStyledAttributes(com.android.internal.R.styleable.MenuView);
int textAppearance = a.getResourceId(com.android.internal.R.styleable.
MenuView_itemTextAppearance, -1);
// TODO: any other styleable attrs we need from the standard menu item style?
a.recycle();
setClickable(true);
setFocusable(true);
setTextAppearance(context, textAppearance);
// Set the padding like the regular menu items do
setPadding(3, getPaddingTop(), 3, getPaddingBottom());
}
//
// Visibility: we only ever use the VISIBLE and GONE states.
//
public void setVisible(boolean isVisible) {
setVisibility(isVisible ? VISIBLE : GONE);
}
public boolean isVisible() {
return (getVisibility() == VISIBLE);
}
/**
* Sets whether or not this item's "green LED" state indicator
* should be visible.
*/
public void setIndicatorVisible(boolean isVisible) {
if (DBG) log("setIndicatorVisible(" + isVisible + ")...");
mIndicatorVisible = isVisible;
updateIndicator();
updateCompoundDrawables();
}
/**
* Turns this item's "green LED" state indicator on or off.
*/
public void setIndicatorState(boolean onoff) {
if (DBG) log("setIndicatorState(" + onoff + ")...");
mIndicatorState = onoff;
updateIndicator();
updateCompoundDrawables();
}
/**
* Sets this item's icon, to be drawn above the text label.
*/
public void setIcon(Drawable icon) {
if (DBG) log("setIcon(" + icon + ")...");
mIcon = icon;
updateCompoundDrawables();
// If there's an icon, we'll only have enough room for one line of text.
if (icon != null) setSingleLineMarquee();
}
/**
* Sets this item's icon, to be drawn above the text label.
*/
public void setIconResource(int resId) {
if (DBG) log("setIconResource(" + resId + ")...");
Drawable iconDrawable = getResources().getDrawable(resId);
setIcon(iconDrawable);
}
/**
* Updates mIndicatorDrawable based on mIndicatorVisible and mIndicatorState.
*/
private void updateIndicator() {
if (mIndicatorVisible) {
int resId = mIndicatorState ? android.R.drawable.button_onoff_indicator_on
: android.R.drawable.button_onoff_indicator_off;
mIndicatorDrawable = getResources().getDrawable(resId);
} else {
mIndicatorDrawable = null;
}
}
/**
* Installs mIcon and mIndicatorDrawable as our TextView "compound drawables",
* and does any necessary layout tweaking depending on the presence or
* absence of the icon or indicator.
*/
private void updateCompoundDrawables() {
// TODO: There are several hand-tweaked layout constants hardcoded here.
// If we ever move this widget into the framework (and make it
// usable from XML), be sure to move these constants to XML too.
// If the icon is visible, add a bit of negative padding to scoot
// it down closer to the text.
if (mIcon != null) {
setCompoundDrawablePadding(-10);
}
// Add some top/bottom padding when the indicator and/or icon are
// visible (to add a little vertical space between the indicator
// and the bottom of the item, or the icon and the top of the
// item.)
int topPadding = (mIcon != null) ? 5 : 0;
int bottomPadding = (mIndicatorDrawable != null) ? 5 : 0;
setPadding(0, topPadding, 0, bottomPadding);
// TODO: topPadding seems to have no effect here.
// Regardless of the value I use, the icon image
// ends up right up against the top edge of the button...
// (Maybe we're just out of room?)
// if (DBG) log("updateCompoundDrawables: padding: top " + topPadding
// + ", bottom " + bottomPadding);
setCompoundDrawablesWithIntrinsicBounds(null, mIcon, null, mIndicatorDrawable);
}
/**
* Forces this menu item into "single line" mode, with marqueeing enabled.
* This is only necessary when an icon is present, since otherwise
* there's enough room for long labels to wrap onto two lines.
*/
private void setSingleLineMarquee() {
setEllipsize(TruncateAt.MARQUEE);
setHorizontalFadingEdgeEnabled(true);
setSingleLine(true);
}
@Override
public String toString() {
return "'" + getText() + "' (" + super.toString() + ")";
}
private void log(String msg) {
Log.d(LOG_TAG, msg);
}
}
class InCallMenuView extends ViewGroup {
private static final String LOG_TAG = "PHONE/InCallMenuView";
private static final boolean DBG = false;
private int mRowHeight;
/** Divider that is drawn between all rows */
private Drawable mHorizontalDivider;
/** Height of the horizontal divider */
private int mHorizontalDividerHeight;
/** Set of horizontal divider positions where the horizontal divider will be drawn */
private ArrayList<Rect> mHorizontalDividerRects;
/** Divider that is drawn between all columns */
private Drawable mVerticalDivider;
/** Width of the vertical divider */
private int mVerticalDividerWidth;
/** Set of vertical divider positions where the vertical divider will be drawn */
private ArrayList<Rect> mVerticalDividerRects;
/** Background of each item (should contain the selected and focused states) */
private Drawable mItemBackground;
/**
* The actual layout of items in the menu, organized into 3 rows.
*
* Row 0 is the topmost row onscreen, item 0 is the leftmost item in a row.
*
* Individual items may be disabled or hidden, but never move between
* rows or change their order within a row.
*/
private static final int NUM_ROWS = 3;
private static final int MAX_ITEMS_PER_ROW = 10;
private InCallMenuItemView[][] mItems = new InCallMenuItemView[NUM_ROWS][MAX_ITEMS_PER_ROW];
private int mNumItemsForRow[] = new int[NUM_ROWS];
/**
* Number of visible items per row, given the current state of all the
* menu items.
* A row with zero visible items isn't drawn at all.
*/
private int mNumVisibleItemsForRow[] = new int[NUM_ROWS];
private int mNumVisibleRows;
/**
* Reference to the InCallScreen activity that owns us. This will be
* null if we haven't been initialized yet *or* after the InCallScreen
* activity has been destroyed.
*/
private CallingMenu mInCallScreen;
InCallMenuView(Context context, CallingMenu inCallScreen) {
super(context);
if (DBG) log("InCallMenuView constructor...");
mInCallScreen = inCallScreen;
// Look up a few styled attrs from IconMenuView and/or MenuView
// (to keep our look and feel at least *somewhat* consistent with
// menus in other apps.)
TypedArray a =
mContext.obtainStyledAttributes(com.android.internal.R.styleable.IconMenuView);
if (DBG) log("- IconMenuView styled attrs: " + a);
mRowHeight = a.getDimensionPixelSize(
com.android.internal.R.styleable.IconMenuView_rowHeight, 64);
if (DBG) log(" - mRowHeight: " + mRowHeight);
a.recycle();
a = mContext.obtainStyledAttributes(com.android.internal.R.styleable.MenuView);
if (DBG) log("- MenuView styled attrs: " + a);
mItemBackground = a.getDrawable(com.android.internal.R.styleable.MenuView_itemBackground);
if (DBG) log(" - mItemBackground: " + mItemBackground);
mHorizontalDivider = a.getDrawable(com.android.internal.R.styleable.MenuView_horizontalDivider);
if (DBG) log(" - mHorizontalDivider: " + mHorizontalDivider);
//paul mHorizontalDividerRects = new ArrayList<Rect>();
mVerticalDivider = a.getDrawable(com.android.internal.R.styleable.MenuView_verticalDivider);
if (DBG) log(" - mVerticalDivider: " + mVerticalDivider);
//paul mVerticalDividerRects = new ArrayList<Rect>();
a.recycle();
if (mHorizontalDivider != null) {
mHorizontalDividerHeight = mHorizontalDivider.getIntrinsicHeight();
// Make sure to have some height for the divider
if (mHorizontalDividerHeight == -1) mHorizontalDividerHeight = 1;
}
if (mVerticalDivider != null) {
mVerticalDividerWidth = mVerticalDivider.getIntrinsicWidth();
// Make sure to have some width for the divider
if (mVerticalDividerWidth == -1) mVerticalDividerWidth = 1;
}
// This view will be drawing the dividers.
setWillNotDraw(false);
// Arrange to get key events even when there's no focused item in
// the in-call menu (i.e. when in touch mode).
// (We *always* want key events whenever we're visible, so that we
// can forward them to the InCallScreen activity; see dispatchKeyEvent().)
setFocusableInTouchMode(true);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
// The default ViewGroup.LayoutParams width and height are
// WRAP_CONTENT. (This applies to us right now since we
// initially have no LayoutParams at all.)
// But in the Menu framework, when returning a view from
// onCreatePanelView(), a layout width of WRAP_CONTENT indicates
// that you want the smaller-sized "More" menu frame. We want the
// full-screen-width menu frame instead, though, so we need to
// give ourselves a LayoutParams with width==FILL_PARENT.
ViewGroup.LayoutParams lp =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
setLayoutParams(lp);
}
/**
* Null out our reference to the InCallScreen activity.
* This indicates that the InCallScreen activity has been destroyed.
*/
void clearInCallScreenReference() {
mInCallScreen = null;
}
/**
* Adds an InCallMenuItemView to the specified row.
*/
/* package */ void addItemView(InCallMenuItemView itemView, int row) {
if (DBG) log("addItemView(" + itemView + ", row " + row + ")...");
if (row >= NUM_ROWS) {
throw new IllegalStateException("Row index " + row + " > NUM_ROWS");
}
int indexInRow = mNumItemsForRow[row];
if (indexInRow >= MAX_ITEMS_PER_ROW) {
throw new IllegalStateException("Too many items (" + indexInRow + ") in row " + row);
}
mNumItemsForRow[row]++;
mItems[row][indexInRow] = itemView;
//
// Finally, add this item as a child.
//
ViewGroup.LayoutParams lp = itemView.getLayoutParams();
if (lp == null) {
// Default layout parameters
lp = new LayoutParams(android.view.ViewGroup.LayoutParams.FILL_PARENT, android.view.ViewGroup.LayoutParams.FILL_PARENT);
}
// Apply the background to the item view
itemView.setBackgroundDrawable(mItemBackground.getConstantState().newDrawable());
addView(itemView, lp);
}
/**
* Precomputes the number of visible items per row, and the total
* number of visible rows. (A row with zero visible items isn't
* drawn at all.)
*/
/* package */ void updateVisibility() {
if (DBG) log("updateVisibility()...");
mNumVisibleRows = 0;
for (int row = 0; row < NUM_ROWS; row++) {
InCallMenuItemView[] thisRow = mItems[row];
int numItemsThisRow = mNumItemsForRow[row];
int numVisibleThisRow = 0;
for (int itemIndex = 0; itemIndex < numItemsThisRow; itemIndex++) {
// if (DBG) log(" - Checking item: " + mItems[row][itemIndex]);
if (mItems[row][itemIndex].isVisible()) numVisibleThisRow++;
}
if (DBG) log("==> Num visible for row " + row + ": " + numVisibleThisRow);
mNumVisibleItemsForRow[row] = numVisibleThisRow;
if (numVisibleThisRow > 0) mNumVisibleRows++;
}
if (DBG) log("==> Num visible rows: " + mNumVisibleRows);
}
/* package */ void dumpState() {
if (DBG) log("============ dumpState() ============");
if (DBG) log("- mItems LENGTH: " + mItems.length);
for (int row = 0; row < NUM_ROWS; row++) {
if (DBG) log("- Row " + row + ": length " + mItems[row].length
+ ", num items " + mNumItemsForRow[row]
+ ", num visible " + mNumVisibleItemsForRow[row]);
}
}
/**
* The positioning algorithm that gets called from onMeasure. It just
* computes positions for each child, and then stores them in the
* child's layout params.
*
* At this point the visibility of each item in mItems[][] is correct,
* and mNumVisibleRows and mNumVisibleItemsForRow[] have already been
* precomputed.
*
* @param menuWidth The width of this menu to assume for positioning
* @param menuHeight The height of this menu to assume for positioning
*
* TODO: This is a near-exact duplicate of IconMenuView.positionChildren().
* Consider abstracting this out into a more general-purpose "grid layout
* with dividers" container that both classes could use...
*/
private void positionChildren(int menuWidth, int menuHeight) {
if (DBG) log("positionChildren(" + menuWidth + " x " + menuHeight + ")...");
// Clear the containers for the positions where the dividers should be drawn
if (mHorizontalDivider != null) mHorizontalDividerRects.clear();
if (mVerticalDivider != null) mVerticalDividerRects.clear();
InCallMenuItemView child;
InCallMenuView.LayoutParams childLayoutParams = null;
// Use float for this to get precise positions (uniform item widths
// instead of last one taking any slack), and then convert to ints at last opportunity
float itemLeft;
float itemTop = 0;
// Since each row can have a different number of items, this will be computed per row
float itemWidth;
// Subtract the space needed for the horizontal dividers
final float itemHeight = (menuHeight - mHorizontalDividerHeight * (mNumVisibleRows - 1))
/ (float) mNumVisibleRows;
// We add horizontal dividers between each visible row, so there should
// be a total of mNumVisibleRows-1 of them.
int numHorizDividersRemainingToDraw = mNumVisibleRows - 1;
for (int row = 0; row < NUM_ROWS; row++) {
int numItemsThisRow = mNumItemsForRow[row];
int numVisibleThisRow = mNumVisibleItemsForRow[row];
if (DBG) log(" - num visible for row " + row + ": " + numVisibleThisRow);
if (numVisibleThisRow == 0) {
continue;
}
InCallMenuItemView[] thisRow = mItems[row];
// Start at the left
itemLeft = 0;
// Subtract the space needed for the vertical dividers, and
// divide by the number of items.
itemWidth = (menuWidth - mVerticalDividerWidth * (numVisibleThisRow - 1))
/ (float) numVisibleThisRow;
for (int itemIndex = 0; itemIndex < numItemsThisRow; itemIndex++) {
child = mItems[row][itemIndex];
if (!child.isVisible()) continue;
if (DBG) log("==> child [" + row + "][" + itemIndex + "]: " + child);
// Tell the child to be exactly this size
child.measure(MeasureSpec.makeMeasureSpec((int) itemWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec((int) itemHeight, MeasureSpec.EXACTLY));
// Remember the child's position for layout
childLayoutParams = (InCallMenuView.LayoutParams) child.getLayoutParams();
childLayoutParams.height = (int) itemLeft;
childLayoutParams.width = (int) (itemLeft + itemWidth);
childLayoutParams.height = (int) itemTop;
childLayoutParams.width = (int) (itemTop + itemHeight);
// Increment by item width
itemLeft += itemWidth;
// Add a vertical divider to draw
if (mVerticalDivider != null) {
mVerticalDividerRects.add(new Rect((int) itemLeft,
(int) itemTop, (int) (itemLeft + mVerticalDividerWidth),
(int) (itemTop + itemHeight)));
}
// Increment by divider width (even if we're not computing
// dividers, since we need to leave room for them when
// calculating item positions)
itemLeft += mVerticalDividerWidth;
}
// Last child on each row should extend to very right edge
if (childLayoutParams != null) {
childLayoutParams.height = menuWidth;
}
itemTop += itemHeight;
// Add a horizontal divider (if we need one under this row)
if ((mHorizontalDivider != null) && (numHorizDividersRemainingToDraw-- > 0)) {
mHorizontalDividerRects.add(new Rect(0, (int) itemTop, menuWidth,
(int) (itemTop + mHorizontalDividerHeight)));
itemTop += mHorizontalDividerHeight;
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if (DBG) log("onMeasure(" + widthMeasureSpec + " x " + heightMeasureSpec + ")...");
// Get the desired height of the icon menu view (last row of items does
// not have a divider below)
final int desiredHeight = (mRowHeight + mHorizontalDividerHeight) * mNumVisibleRows
- mHorizontalDividerHeight;
// Maximum possible width and desired height
setMeasuredDimension(resolveSize(Integer.MAX_VALUE, widthMeasureSpec),
resolveSize(desiredHeight, heightMeasureSpec));
// Position the children
positionChildren(mMeasuredWidth, mMeasuredHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (DBG) log("onLayout(changed " + changed
+ ", l " + l + " t " + t + " r " + r + " b " + b + ")...");
View child;
InCallMenuView.LayoutParams childLayoutParams;
for (int i = getChildCount() - 1; i >= 0; i--) {
child = getChildAt(i);
childLayoutParams = (InCallMenuView.LayoutParams) child.getLayoutParams();
// Layout children according to positions set during the measure
child.layout(childLayoutParams.height, childLayoutParams.FILL_PARENT,
childLayoutParams.width, childLayoutParams.WRAP_CONTENT);
}
}
@Override
protected void onDraw(Canvas canvas) {
if (DBG) log("onDraw()...");
if (mHorizontalDivider != null) {
// If we have a horizontal divider to draw, draw it at the remembered positions
for (int i = mHorizontalDividerRects.size() - 1; i >= 0; i--) {
mHorizontalDivider.setBounds(mHorizontalDividerRects.get(i));
mHorizontalDivider.draw(canvas);
}
}
if (mVerticalDivider != null) {
// If we have a vertical divider to draw, draw it at the remembered positions
for (int i = mVerticalDividerRects.size() - 1; i >= 0; i--) {
mVerticalDivider.setBounds(mVerticalDividerRects.get(i));
mVerticalDivider.draw(canvas);
}
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (DBG) log("dispatchKeyEvent(" + event + ")...");
// In most other apps, when a menu is up, the menu itself handles
// keypresses. And keys that aren't handled by the menu do NOT
// get dispatched to the current Activity.
//
// But in the in-call UI, we don't have any menu shortcuts, *and*
// it's important for buttons like CALL to work normally even
// while the menu is up. So we handle ALL key events (with some
// exceptions -- see below) by simply forwarding them to the
// InCallScreen.
int keyCode = event.getKeyCode();
if (event.isDown()) {
switch (keyCode) {
// The BACK key dismisses the menu.
case KeyEvent.KEYCODE_BACK:
if (DBG) log("==> BACK key! handling it ourselves...");
// We don't need to do anything here (since BACK
// is magically handled by the framework); we just
// need to *not* forward it to the InCallScreen.
break;
// Don't send KEYCODE_DPAD_CENTER/KEYCODE_ENTER to the
// InCallScreen either, since the framework needs those to
// activate the focused item when using the trackball.
case KeyEvent.KEYCODE_DPAD_CENTER:
case KeyEvent.KEYCODE_ENTER:
break;
// Anything else gets forwarded to the InCallScreen.
default:
if (DBG) log("==> dispatchKeyEvent: forwarding event to the InCallScreen");
if (mInCallScreen != null) {
return mInCallScreen.onKeyDown(keyCode, event);
}
break;
}
} {}
return super.dispatchKeyEvent(event);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new InCallMenuView.LayoutParams(getContext(), attrs);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
// Override to allow type-checking of LayoutParams.
return p instanceof InCallMenuView.LayoutParams;
}
/**
* Layout parameters specific to InCallMenuView (stores the left, top,
* right, bottom from the measure pass).
*/
private void log(String msg) {
Log.d(LOG_TAG, msg);
}
}
}