android:id="@+id/dialpad"
android:paddingLeft="7dp"
android:paddingRight="7dp"
- android:layout_width="fill_parent"
+ android:paddingTop="6dp"
+ android:paddingBottom="6dp"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
>
<ImageButton android:id="@+id/one"
android:layout_width="88dp"
<!-- TODO: Use a textAppearance to control the display of the number -->
<EditText android:id="@+id/digits"
android:layout_width="fill_parent"
- android:layout_height="66dip"
+ android:layout_height="67dip"
android:layout_marginBottom="6dip"
- android:layout_marginTop="1dip"
android:gravity="center"
android:maxLines="1"
android:scrollHorizontally="true"
<include layout="@layout/dialpad" />
<!-- Horizontal row of buttons (Voicemail + DialButton + Delete.) -->
- <LinearLayout android:id="@+id/voicemailAndDialAndDelete"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="6dip"
- android:orientation="horizontal">
-
- <!-- Onscreen "Voicemail" button -->
- <ImageButton android:id="@+id/voicemailButton"
- android:layout_width="90dip"
- android:layout_height="52dip"
- android:layout_gravity="center_vertical"
- android:state_enabled="false"
- android:background="@drawable/btn_dial_voicemail"
- android:src="@drawable/ic_dial_action_voice_mail" />
-
- <!-- Onscreen "Dial" button, used on all platforms by
- default. Its usage can be disabled using resources (see
- config.xml.) -->
- <ImageButton android:id="@+id/dialButton"
- android:layout_width="116dip"
- android:layout_height="52dip"
- android:layout_gravity="center_vertical"
- android:state_enabled="false"
- android:background="@drawable/btn_dial_action"
- android:src="@drawable/ic_dial_action_call" />
-
- <!-- Onscreen "Backspace/Delete" button -->
- <ImageButton android:id="@+id/deleteButton"
- android:layout_width="90dip"
- android:layout_height="52dip"
- android:layout_gravity="center_vertical"
- android:state_enabled="false"
- android:background="@drawable/btn_dial_delete"
- android:src="@drawable/ic_dial_action_delete" />
- </LinearLayout>
+ <include layout="@layout/voicemail_dial_delete" />
<!-- "Dialpad chooser" UI, shown only when the user brings up the
Dialer while a call is already in progress.
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Horizontal row of buttons (Voicemail + DialButton + Delete.) -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/voicemailAndDialAndDelete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="6dip"
+ android:orientation="horizontal">
+
+ <!-- Onscreen "Voicemail" button.
+ The width is 75 (from the mocks) + 12 of padding from the
+ 9patch, total is 87.
+ -->
+ <ImageButton android:id="@+id/voicemailButton"
+ android:layout_width="87dip"
+ android:layout_height="50dip"
+ android:layout_gravity="center_vertical"
+ android:state_enabled="false"
+ android:background="@drawable/btn_dial_voicemail"
+ android:src="@drawable/ic_dial_action_voice_mail" />
+
+ <!-- Onscreen "Dial" button, used on all platforms by
+ default. Its usage can be disabled using resources (see
+ config.xml.) -->
+ <ImageButton android:id="@+id/dialButton"
+ android:layout_width="116dip"
+ android:layout_height="50dip"
+ android:layout_gravity="center_vertical"
+ android:state_enabled="false"
+ android:background="@drawable/btn_dial_action"
+ android:src="@drawable/ic_dial_action_call" />
+
+ <!-- Onscreen "Backspace/Delete" button
+ The width is 75 (from the mocks) + 12 of padding from the
+ 9patch, total is 87.
+ -->
+ <ImageButton android:id="@+id/deleteButton"
+ android:layout_width="87dip"
+ android:layout_height="50dip"
+ android:layout_gravity="center_vertical"
+ android:state_enabled="false"
+ android:background="@drawable/btn_dial_delete"
+ android:src="@drawable/ic_dial_action_delete" />
+</LinearLayout>
+
<EditText android:id="@+id/digits"
android:layout_width="fill_parent"
android:layout_height="66dip"
- android:layout_marginBottom="6dip"
+ android:layout_marginBottom="50dip"
android:layout_marginTop="1dip"
android:gravity="center"
android:maxLines="1"
/>
<!-- Horizontal row of buttons (Voicemail + DialButton + Delete.) -->
- <LinearLayout android:id="@+id/voicemailAndDialAndDelete"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- android:layout_gravity="center_horizontal"
- android:layout_marginBottom="6dip"
- android:orientation="horizontal">
-
- <!-- Onscreen "Voicemail" button -->
- <ImageButton android:id="@+id/voicemailButton"
- android:layout_width="90dip"
- android:layout_height="52dip"
- android:layout_gravity="center_vertical"
- android:state_enabled="false"
- android:background="@drawable/btn_dial_voicemail"
- android:src="@drawable/ic_dial_action_voice_mail" />
-
- <!-- Onscreen "Dial" button, used on all platforms by
- default. Its usage can be disabled using resources (see
- config.xml.) -->
- <ImageButton android:id="@+id/dialButton"
- android:layout_width="116dip"
- android:layout_height="52dip"
- android:layout_gravity="center_vertical"
- android:state_enabled="false"
- android:background="@drawable/btn_dial_action"
- android:src="@drawable/ic_dial_action_call" />
-
- <!-- Onscreen "Backspace/Delete" button -->
- <ImageButton android:id="@+id/deleteButton"
- android:layout_width="90dip"
- android:layout_height="52dip"
- android:layout_gravity="center_vertical"
- android:state_enabled="false"
- android:background="@drawable/btn_dial_delete"
- android:src="@drawable/ic_dial_action_delete" />
- </LinearLayout>
+ <include layout="@layout/voicemail_dial_delete" />
<!-- "Dialpad chooser" UI, shown only when the user brings up the
Dialer while a call is already in progress.
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Dialpad in the Contact app.
+ Tall screen version with taller buttons.
+ -->
+
+<com.android.contacts.ButtonGridLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/dialpad"
+ android:paddingLeft="7dp"
+ android:paddingRight="7dp"
+ android:paddingTop="6dp"
+ android:paddingBottom="6dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+
+>
+ <ImageButton android:id="@+id/one"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_1_no_vm"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_one"
+ />
+
+ <ImageButton android:id="@+id/two"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_2"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_two"
+ />
+
+ <ImageButton android:id="@+id/three"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_3"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_three"
+ />
+
+ <ImageButton android:id="@+id/four"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_4"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_four"
+ />
+
+ <ImageButton android:id="@+id/five"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_5"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_five"
+ />
+
+ <ImageButton android:id="@+id/six"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_6"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_six"
+ />
+
+ <ImageButton android:id="@+id/seven"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_7"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_seven"
+ />
+
+ <ImageButton android:id="@+id/eight"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_8"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_eight"
+ />
+
+ <ImageButton android:id="@+id/nine"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_9"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_nine"
+ />
+
+ <ImageButton android:id="@+id/star"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_star"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_star"
+ />
+
+ <ImageButton android:id="@+id/zero"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_0"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_zero"
+ />
+
+ <ImageButton android:id="@+id/pound"
+ android:layout_width="88dp"
+ android:layout_height="58dp"
+ android:src="@drawable/dial_num_pound"
+ android:background="@drawable/btn_dial"
+ android:soundEffectsEnabled="false"
+ android:contentDescription="@string/description_image_button_pound"
+ />
+</com.android.contacts.ButtonGridLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/top"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+>
+
+ <!-- Text field above the keypad where the digits are displayed -->
+ <!-- TODO: Use a textAppearance to control the display of the number -->
+ <EditText android:id="@+id/digits"
+ android:layout_width="fill_parent"
+ android:layout_height="74dip"
+ android:layout_marginBottom="20dip"
+ android:gravity="center"
+ android:maxLines="1"
+ android:scrollHorizontally="true"
+ android:textSize="34sp"
+ android:freezesText="true"
+ android:background="@drawable/btn_dial_textfield"
+ android:textColor="@color/dialer_button_text"
+ android:focusableInTouchMode="false"
+ />
+
+ <!-- Keypad section -->
+ <include layout="@layout/dialpad" />
+
+ <!-- Horizontal row of buttons (Voicemail + DialButton + Delete.) -->
+ <include layout="@layout/voicemail_dial_delete" />
+
+ <!-- "Dialpad chooser" UI, shown only when the user brings up the
+ Dialer while a call is already in progress.
+ When this UI is visible, the other Dialer elements
+ (the textfield/button and the dialpad) are hidden. -->
+ <ListView android:id="@+id/dialpadChooser"
+ android:layout_width="fill_parent"
+ android:layout_height="1dip"
+ android:layout_weight="1"
+ />
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<!-- Horizontal row of buttons (Voicemail + DialButton + Delete.)
+ Tall screen version with taller buttons.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/voicemailAndDialAndDelete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="24dip"
+ android:orientation="horizontal">
+
+ <!-- Onscreen "Voicemail" button -->
+ <ImageButton android:id="@+id/voicemailButton"
+ android:layout_width="87dip"
+ android:layout_height="58dip"
+ android:layout_gravity="center_vertical"
+ android:state_enabled="false"
+ android:background="@drawable/btn_dial_voicemail"
+ android:src="@drawable/ic_dial_action_voice_mail" />
+
+ <!-- Onscreen "Dial" button, used on all platforms by
+ default. Its usage can be disabled using resources (see
+ config.xml.) -->
+ <ImageButton android:id="@+id/dialButton"
+ android:layout_width="116dip"
+ android:layout_height="58dip"
+ android:layout_gravity="center_vertical"
+ android:state_enabled="false"
+ android:background="@drawable/btn_dial_action"
+ android:src="@drawable/ic_dial_action_call" />
+
+ <!-- Onscreen "Backspace/Delete" button -->
+ <ImageButton android:id="@+id/deleteButton"
+ android:layout_width="87dip"
+ android:layout_height="58dip"
+ android:layout_gravity="center_vertical"
+ android:state_enabled="false"
+ android:background="@drawable/btn_dial_delete"
+ android:src="@drawable/ic_dial_action_delete" />
+</LinearLayout>
+
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/top"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+>
+
+ <!-- Text field above the keypad where the digits are displayed -->
+ <!-- TODO: Use a textAppearance to control the display of the number -->
+ <EditText android:id="@+id/digits"
+ android:layout_width="fill_parent"
+ android:layout_height="74dip"
+ android:layout_marginBottom="30dip"
+ android:layout_marginTop="1dip"
+ android:gravity="center"
+ android:maxLines="1"
+ android:scrollHorizontally="true"
+ android:textSize="34sp"
+ android:freezesText="true"
+ android:background="@drawable/btn_dial_textfield"
+ android:textColor="@color/dialer_button_text"
+ android:hint="@string/dialerKeyboardHintText"
+ />
+
+ <!-- Horizontal row of buttons (Voicemail + DialButton + Delete.) -->
+ <include layout="@layout/voicemail_dial_delete" />
+
+ <!-- "Dialpad chooser" UI, shown only when the user brings up the
+ Dialer while a call is already in progress.
+ When this UI is visible, the other Dialer elements
+ (the textfield and button) are hidden. -->
+ <ListView android:id="@+id/dialpadChooser"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:footerDividersEnabled="true"
+ />
+
+</LinearLayout>
import android.content.Context;
import android.util.AttributeSet;
+import android.view.View.MeasureSpec;
import android.view.View;
import android.view.ViewGroup;
-import android.view.View.MeasureSpec;
+/**
+ * Create a 4x3 grid of dial buttons.
+ *
+ * It was easier and more efficient to do it this way than use
+ * standard layouts. It's perfectly fine (and actually encouraged) to
+ * use custom layouts rather than piling up standard layouts.
+ *
+ * The horizontal and vertical spacings between buttons are controlled
+ * by the amount of padding (attributes on the ButtonGridLayout element):
+ * - horizontal = left + right padding and
+ * - vertical = top + bottom padding.
+ *
+ * This class assumes that all the buttons have the same size.
+ *
+ * Invocation: onMeasure is called first by the framework to know our
+ * size. Then onLayout is invoked to layout the buttons.
+ */
+// TODO: Blindly layout the buttons w/o checking if we overrun the
+// bottom-right corner.
public class ButtonGridLayout extends ViewGroup {
+ private final int COLUMNS = 3;
+ private final int ROWS = 4;
+
+ // Width and height of a button
+ private int mButtonWidth;
+ private int mButtonHeight;
- private final int mColumns = 3;
+ // Width and height of a button + padding.
+ private int mWidthInc;
+ private int mHeightInc;
public ButtonGridLayout(Context context) {
super(context);
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ int i = 0;
int y = mPaddingTop;
- final int rows = getRows();
- final View child0 = getChildAt(0);
- final int yInc = (getHeight() - mPaddingTop - mPaddingBottom) / rows;
- final int xInc = (getWidth() - mPaddingLeft - mPaddingRight) / mColumns;
- final int childWidth = child0.getMeasuredWidth();
- final int childHeight = child0.getMeasuredHeight();
- final int xOffset = (xInc - childWidth) / 2;
- final int yOffset = (yInc - childHeight) / 2;
-
- for (int row = 0; row < rows; row++) {
+ for (int row = 0; row < ROWS; row++) {
int x = mPaddingLeft;
- for (int col = 0; col < mColumns; col++) {
- int cell = row * mColumns + col;
- if (cell >= getChildCount()) {
- break;
- }
- View child = getChildAt(cell);
- child.layout(x + xOffset, y + yOffset,
- x + xOffset + childWidth,
- y + yOffset + childHeight);
- x += xInc;
+ for (int col = 0; col < COLUMNS; col++) {
+ View child = getChildAt(i);
+
+ child.layout(x, y, x + mButtonWidth, y + mButtonHeight);
+
+ x += mWidthInc;
+ i++;
}
- y += yInc;
+ y += mHeightInc;
}
- }
-
- private int getRows() {
- return (getChildCount() + mColumns - 1) / mColumns;
- }
+ }
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int width = mPaddingLeft + mPaddingRight;
- int height = mPaddingTop + mPaddingBottom;
-
- // Measure the first child and get it's size
+ // Measure the first child and get it's size
View child = getChildAt(0);
child.measure(MeasureSpec.UNSPECIFIED , MeasureSpec.UNSPECIFIED);
- int childWidth = child.getMeasuredWidth();
- int childHeight = child.getMeasuredHeight();
+
// Make sure the other children are measured as well, to initialize
for (int i = 1; i < getChildCount(); i++) {
getChildAt(i).measure(MeasureSpec.UNSPECIFIED , MeasureSpec.UNSPECIFIED);
}
- // All cells are going to be the size of the first child
- width += mColumns * childWidth;
- final int finalWidth = resolveSize(width, widthMeasureSpec);
- // The vertical padding between button must be the same as the
- // horizontal one. The cumulative horizontal padding is the
- // difference between 'width' and 'finalWidth'.
- final int padding = (finalWidth - width) / mColumns;
+ // Store these to be reused in onLayout.
+ mButtonWidth = child.getMeasuredWidth();
+ mButtonHeight = child.getMeasuredHeight();
+ mWidthInc = mButtonWidth + mPaddingLeft + mPaddingRight;
+ mHeightInc = mButtonHeight + mPaddingTop + mPaddingBottom;
- height += getRows() * (childHeight + padding);
+ final int width = resolveSize(COLUMNS * mWidthInc, widthMeasureSpec);
+ final int height = resolveSize(ROWS * mHeightInc, heightMeasureSpec);
- final int finalHeight = resolveSize(height, heightMeasureSpec);
- setMeasuredDimension(finalWidth, finalHeight);
+ setMeasuredDimension(width, height);
}
}