Merge "Add shadow between favorites and frequent lists on tablet"
diff --git a/res/layout/call_detail.xml b/res/layout/call_detail.xml
index 987a787..714bbd8 100644
--- a/res/layout/call_detail.xml
+++ b/res/layout/call_detail.xml
@@ -16,114 +16,194 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
+ android:id="@+id/call_detail"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="horizontal"
- android:gravity="top"
+ android:visibility="gone"
>
- <FrameLayout
- android:id="@+id/voicemail_status"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:visibility="gone"
- >
- <include layout="@layout/call_log_voicemail_status"/>
- </FrameLayout>
-
- <view
- class="com.android.contacts.widget.ProportionalLayout"
- android:id="@+id/contact_background_sizer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_below="@id/voicemail_status"
- ex:ratio="0.5"
- ex:direction="widthToHeight"
- >
- <ImageView
- android:id="@+id/contact_background"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:adjustViewBounds="true"
- android:scaleType="centerCrop"
- android:background="@drawable/ic_contact_picture"
- />
- </view>
- <LinearLayout
- android:id="@+id/blue_separator"
- android:layout_width="match_parent"
- android:layout_height="1dip"
- android:background="@android:color/holo_blue_light"
- android:layout_below="@+id/contact_background_sizer"
- />
- <LinearLayout
- android:id="@+id/voicemail_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/blue_separator"
- >
- <!-- The voicemail fragment will be put here. -->
- </LinearLayout>
- <View
- android:id="@+id/photo_text_bar"
- android:layout_width="match_parent"
- android:layout_height="42dip"
- android:background="#7F000000"
- android:layout_alignParentLeft="true"
- android:layout_alignBottom="@id/contact_background_sizer"
- />
- <ImageView
- android:id="@+id/main_action"
- android:layout_width="wrap_content"
- android:layout_height="0dip"
- android:scaleType="center"
- android:layout_alignRight="@id/photo_text_bar"
- android:layout_alignBottom="@id/photo_text_bar"
- android:layout_alignTop="@id/photo_text_bar"
- android:layout_marginRight="@dimen/call_log_outer_margin"
- />
- <TextView
- android:id="@+id/header_text"
- android:layout_width="wrap_content"
- android:layout_height="0dip"
- android:layout_alignLeft="@id/photo_text_bar"
- android:layout_toLeftOf="@id/main_action"
- android:layout_alignTop="@id/photo_text_bar"
- android:layout_alignBottom="@id/photo_text_bar"
- android:layout_marginRight="@dimen/call_log_inner_margin"
- android:layout_marginLeft="@dimen/call_detail_contact_name_margin"
- android:gravity="center_vertical"
- android:textColor="?attr/call_log_primary_text_color"
- android:textSize="18sp"
- android:singleLine="true"
- />
- <ImageButton
- android:id="@+id/main_action_push_layer"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignLeft="@id/contact_background_sizer"
- android:layout_alignTop="@id/contact_background_sizer"
- android:layout_alignRight="@id/contact_background_sizer"
- android:layout_alignBottom="@id/contact_background_sizer"
- android:background="?android:attr/selectableItemBackground"
- />
- <ListView
- android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/voicemail_container"
- android:layout_marginTop="@dimen/call_log_icon_margin"
- android:background="?attr/call_log_primary_background_color"
- />
+ <!--
+ The list view is under everything.
+ It contains a first header element which is hidden under the controls UI.
+ When scrolling, the controls move up until the name bar hits the top.
+ -->
<ListView
android:id="@+id/history"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/call_log_icon_margin"
android:layout_alignParentLeft="true"
- android:layout_below="@android:id/list"
+ android:layout_alignParentTop="true"
android:background="@android:color/black"
/>
+
+ <!-- All the controls which are part of the pinned header are in this layout. -->
+ <RelativeLayout
+ android:id="@+id/controls"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ >
+ <FrameLayout
+ android:id="@+id/voicemail_status"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:visibility="gone"
+ >
+ <include layout="@layout/call_log_voicemail_status"/>
+ </FrameLayout>
+
+ <view
+ class="com.android.contacts.widget.ProportionalLayout"
+ android:id="@+id/contact_background_sizer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@id/voicemail_status"
+ ex:ratio="0.5"
+ ex:direction="widthToHeight"
+ >
+ <ImageView
+ android:id="@+id/contact_background"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:adjustViewBounds="true"
+ android:scaleType="centerCrop"
+ />
+ </view>
+ <LinearLayout
+ android:id="@+id/blue_separator"
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="@android:color/holo_blue_light"
+ android:layout_below="@+id/contact_background_sizer"
+ />
+ <LinearLayout
+ android:id="@+id/voicemail_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/blue_separator"
+ android:background="@android:color/black"
+ >
+ <!-- The voicemail fragment will be put here. -->
+ </LinearLayout>
+ <View
+ android:id="@+id/photo_text_bar"
+ android:layout_width="match_parent"
+ android:layout_height="42dip"
+ android:background="#7F000000"
+ android:layout_alignParentLeft="true"
+ android:layout_alignBottom="@id/contact_background_sizer"
+ />
+ <ImageView
+ android:id="@+id/main_action"
+ android:layout_width="wrap_content"
+ android:layout_height="0dip"
+ android:scaleType="center"
+ android:layout_alignRight="@id/photo_text_bar"
+ android:layout_alignBottom="@id/photo_text_bar"
+ android:layout_alignTop="@id/photo_text_bar"
+ android:layout_marginRight="@dimen/call_log_outer_margin"
+ />
+ <TextView
+ android:id="@+id/header_text"
+ android:layout_width="wrap_content"
+ android:layout_height="0dip"
+ android:layout_alignLeft="@id/photo_text_bar"
+ android:layout_toLeftOf="@id/main_action"
+ android:layout_alignTop="@id/photo_text_bar"
+ android:layout_alignBottom="@id/photo_text_bar"
+ android:layout_marginRight="@dimen/call_log_inner_margin"
+ android:layout_marginLeft="@dimen/call_detail_contact_name_margin"
+ android:gravity="center_vertical"
+ android:textColor="?attr/call_log_primary_text_color"
+ android:textSize="18sp"
+ android:singleLine="true"
+ />
+ <ImageButton
+ android:id="@+id/main_action_push_layer"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_alignLeft="@id/contact_background_sizer"
+ android:layout_alignTop="@id/contact_background_sizer"
+ android:layout_alignRight="@id/contact_background_sizer"
+ android:layout_alignBottom="@id/contact_background_sizer"
+ android:background="?android:attr/selectableItemBackground"
+ />
+ <FrameLayout android:id="@+id/call_and_sms_container"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/voicemail_container"
+ android:background="@android:color/black"
+ >
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/call_and_sms"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/call_log_list_item_height"
+ android:orientation="horizontal"
+ android:layout_marginTop="@dimen/call_log_icon_margin"
+ android:gravity="center_vertical"
+ android:background="@drawable/dialpad_background"
+ >
+
+ <LinearLayout android:id="@+id/call_and_sms_main_action"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:paddingLeft="@dimen/call_log_indent_margin"
+ android:orientation="vertical"
+ android:gravity="center_vertical"
+ android:focusable="true"
+ android:background="@drawable/btn_dial"
+ >
+
+ <TextView android:id="@+id/call_and_sms_text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ />
+
+ <LinearLayout android:id="@+id/call_and_sms_line2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ >
+ <TextView android:id="@+id/call_and_sms_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="5dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textStyle="bold"
+ />
+
+ <TextView android:id="@+id/call_and_sms_number"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ />
+ </LinearLayout>
+
+ </LinearLayout>
+
+ <View android:id="@+id/call_and_sms_divider"
+ android:layout_width="1px"
+ android:layout_height="32dip"
+ android:background="@drawable/ic_divider_dashed_holo_dark"
+ android:layout_gravity="center_vertical"
+ />
+
+ <ImageView android:id="@+id/call_and_sms_icon"
+ android:layout_width="@color/call_log_voicemail_highlight_color"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/call_log_inner_margin"
+ android:paddingRight="@dimen/call_log_outer_margin"
+ android:gravity="center"
+ android:scaleType="centerInside"
+ android:focusable="true"
+ android:background="@drawable/btn_dial"
+ />
+ </LinearLayout>
+ </FrameLayout>
+ </RelativeLayout>
</RelativeLayout>
diff --git a/res/layout/call_detail_history_header.xml b/res/layout/call_detail_history_header.xml
new file mode 100644
index 0000000..7fd7556
--- /dev/null
+++ b/res/layout/call_detail_history_header.xml
@@ -0,0 +1,61 @@
+<?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.
+-->
+
+<!-- This layout is supposed to match the content of the controls in call_detail.xml -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <!-- Contact photo. -->
+ <view
+ class="com.android.contacts.widget.ProportionalLayout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@id/voicemail_status"
+ ex:ratio="0.5"
+ ex:direction="widthToHeight"
+ >
+ <!-- Proportional layout requires a view in it. -->
+ <View
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ />
+ </view>
+ <!-- Separator line -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ />
+ <!-- Voicemail controls -->
+ <!-- TODO: Make the height be based on a constant. -->
+ <View
+ android:id="@+id/header_voicemail_container"
+ android:layout_width="match_parent"
+ android:layout_height="142dip"
+ android:layout_marginBottom="@dimen/call_log_icon_margin"
+ />
+ <!-- Call and SMS -->
+ <View
+ android:id="@+id/header_call_and_sms_container"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/call_log_list_item_height"
+ />
+
+</LinearLayout>
diff --git a/res/layout/call_detail_list_item.xml b/res/layout/call_detail_list_item.xml
deleted file mode 100644
index e2bf83c..0000000
--- a/res/layout/call_detail_list_item.xml
+++ /dev/null
@@ -1,84 +0,0 @@
-<?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:layout_width="match_parent"
- android:layout_height="@dimen/call_log_list_item_height"
- android:orientation="horizontal"
- android:layout_marginTop="@dimen/call_log_icon_margin"
- android:gravity="center_vertical"
- android:background="@drawable/dialpad_background"
->
-
- <LinearLayout android:id="@+id/main_action"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:paddingLeft="@dimen/call_log_indent_margin"
- android:orientation="vertical"
- android:gravity="center_vertical"
- android:focusable="true"
- android:background="@drawable/btn_dial"
- >
-
- <TextView android:id="@android:id/text1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceLarge"
- />
-
-
- <LinearLayout android:id="@+id/line2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- >
- <TextView android:id="@+id/label"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="5dip"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textStyle="bold"
- />
-
- <TextView android:id="@+id/number"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- />
- </LinearLayout>
-
- </LinearLayout>
-
- <View android:id="@+id/divider"
- android:layout_width="1px"
- android:layout_height="32dip"
- android:background="@drawable/ic_divider_dashed_holo_dark"
- android:layout_gravity="center_vertical"
- />
-
- <ImageView android:id="@+id/icon"
- android:layout_width="@color/call_log_voicemail_highlight_color"
- android:layout_height="match_parent"
- android:paddingLeft="@dimen/call_log_inner_margin"
- android:paddingRight="@dimen/call_log_outer_margin"
- android:gravity="center"
- android:scaleType="centerInside"
- android:focusable="true"
- android:background="@drawable/btn_dial"
- />
-
-</LinearLayout>
diff --git a/res/layout/dialpad.xml b/res/layout/dialpad.xml
index e9a95ee..1f74c26 100644
--- a/res/layout/dialpad.xml
+++ b/res/layout/dialpad.xml
@@ -19,13 +19,18 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialpad"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="0px"
+ android:layout_weight="0.650"
android:layout_gravity="center_horizontal"
- android:layout_marginTop="4dip"
- android:background="@drawable/dialpad_background"
- android:layout_weight="1">
+ android:layout_marginTop="@dimen/dialpad_vertical_margin"
+ android:paddingLeft="5dip"
+ android:paddingRight="5dip"
+ android:paddingBottom="10dip"
+ android:background="@drawable/dialpad_background">
- <TableRow>
+ <TableRow
+ android:layout_height="0px"
+ android:layout_weight="1">
<ImageButton android:id="@+id/one" style="@style/DialtactsDialpadButtonStyle"
android:src="@drawable/dial_num_1"
android:contentDescription="@string/description_image_button_one" />
@@ -37,7 +42,9 @@
android:contentDescription="@string/description_image_button_three" />
</TableRow>
- <TableRow>
+ <TableRow
+ android:layout_height="0px"
+ android:layout_weight="1">
<ImageButton android:id="@+id/four" style="@style/DialtactsDialpadButtonStyle"
android:src="@drawable/dial_num_4"
android:contentDescription="@string/description_image_button_four" />
@@ -49,7 +56,9 @@
android:contentDescription="@string/description_image_button_six" />
</TableRow>
- <TableRow>
+ <TableRow
+ android:layout_height="0px"
+ android:layout_weight="1">
<ImageButton android:id="@+id/seven" style="@style/DialtactsDialpadButtonStyle"
android:src="@drawable/dial_num_7"
android:contentDescription="@string/description_image_button_seven" />
@@ -61,7 +70,9 @@
android:contentDescription="@string/description_image_button_nine" />
</TableRow>
- <TableRow>
+ <TableRow
+ android:layout_height="0px"
+ android:layout_weight="1">
<ImageButton android:id="@+id/star" style="@style/DialtactsDialpadButtonStyle"
android:src="@drawable/dial_num_star"
android:contentDescription="@string/description_image_button_star" />
@@ -71,6 +82,5 @@
<ImageButton android:id="@+id/pound" style="@style/DialtactsDialpadButtonStyle"
android:src="@drawable/dial_num_pound"
android:contentDescription="@string/description_image_button_pound" />
-
</TableRow>
</TableLayout>
diff --git a/res/layout/dialpad_additional_buttons.xml b/res/layout/dialpad_additional_buttons.xml
index 47a578e..a5e247b 100644
--- a/res/layout/dialpad_additional_buttons.xml
+++ b/res/layout/dialpad_additional_buttons.xml
@@ -18,11 +18,10 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/dialpadAdditionalButtons"
android:layout_width="match_parent"
- android:layout_height="@dimen/dialpad_additional_buttons_height"
+ android:layout_height="0px"
+ android:layout_weight="0.150"
android:layout_gravity="center_horizontal"
- android:layout_marginTop="4dip"
- android:layout_marginBottom="4dip"
- android:layout_weight="0.25"
+ android:layout_marginTop="@dimen/dialpad_vertical_margin"
android:background="@drawable/dialpad_background"
android:orientation="horizontal">
diff --git a/res/layout/dialpad_fragment.xml b/res/layout/dialpad_fragment.xml
index 864dcc7..90d2593 100644
--- a/res/layout/dialpad_fragment.xml
+++ b/res/layout/dialpad_fragment.xml
@@ -19,15 +19,16 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:paddingLeft="4dip"
- android:paddingRight="4dip">
+ android:paddingLeft="@dimen/dialpad_horizontal_margin"
+ android:paddingRight="@dimen/dialpad_horizontal_margin">
<!-- Text field and possibly soft menu button above the keypad where
the digits are displayed. -->
<RelativeLayout
android:layout_width="match_parent"
- android:layout_height="@dimen/dialpad_digits_height"
- android:layout_marginTop="4dip"
+ android:layout_height="0px"
+ android:layout_weight="0.200"
+ android:layout_marginTop="@dimen/dialpad_vertical_margin"
android:gravity="center" >
<!-- Type of this EditText is set to NULL (to disable the IME keyboard)
@@ -45,10 +46,11 @@
android:textColor="?android:attr/textColorPrimary" />
<ImageButton android:id="@+id/overflow_menu"
- android:layout_width="wrap_content"
+ android:layout_width="48dip"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
- android:src="@drawable/ic_menu_overflow" />
+ android:src="@drawable/ic_menu_overflow"
+ android:background="@android:color/transparent"/>
</RelativeLayout>
diff --git a/res/layout/playback_layout.xml b/res/layout/playback_layout.xml
index 83b1c01..bb32014 100644
--- a/res/layout/playback_layout.xml
+++ b/res/layout/playback_layout.xml
@@ -69,19 +69,18 @@
android:progressDrawable="@drawable/seekbar_drawable"
android:thumb="@drawable/seek_bar_thumb"
android:thumbOffset="8dip"
- android:progress="20"
+ android:progress="0"
android:paddingLeft="8dip"
android:paddingRight="8dip"
android:paddingTop="30dip"
android:paddingBottom="20dip"
android:layout_marginRight="64dip"
android:layout_marginLeft="64dip"
- android:max="50"
+ android:max="0"
android:layout_centerVertical="true"
/>
<TextView
android:id="@+id/playback_position_text"
- android:text="@string/voicemail_initial_time"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textSize="14sp"
diff --git a/res/values-long/dimens.xml b/res/values-long/dimens.xml
deleted file mode 100644
index af51d4c..0000000
--- a/res/values-long/dimens.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<resources>
- <dimen name="dialpad_digits_height">80dip</dimen>
- <dimen name="dialpad_additional_buttons_height">58dip</dimen>
- <dimen name="dialpad_button_height">70dip</dimen>
-</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 793365c..69441fd 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -194,14 +194,15 @@
<dimen name="group_editor_member_list_height">550dip</dimen>
<!-- Height of edit text in dialpad fragment -->
- <dimen name="dialpad_digits_height">67dip</dimen>
- <dimen name="dialpad_digits_text_size">33sp</dimen>
- <dimen name="dialpad_additional_buttons_height">50dip</dimen>
- <dimen name="dialpad_button_height">50dip</dimen>
+ <dimen name="dialpad_horizontal_margin">4dip</dimen>
+ <dimen name="dialpad_vertical_margin">2dip</dimen>
+ <dimen name="dialpad_digits_text_size">35sp</dimen>
+
<!-- Just used in landscape mode -->
- <dimen name="dialpad_digits_margin_top">1dip</dimen>
- <!-- Just used in landscape mode -->
- <dimen name="dialpad_digits_margin_bottom">50dip</dimen>
+ <dimen name="dialpad_button_height">0px</dimen>
+ <dimen name="dialpad_digits_height">0px</dimen>
+ <dimen name="dialpad_digits_margin_top">0px</dimen>
+ <dimen name="dialpad_digits_margin_bottom">0px</dimen>
<!-- Width of search view in action bar. Use 0dip for MATCH_PARENT -->
<dimen name="search_view_width">0dip</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2e8983f..0c0a20a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -314,14 +314,14 @@
<!-- Displayed in a spinner dialog as user changes to display options are saved -->
<string name="savingDisplayGroups">Saving display options\u2026</string>
- <!-- Toast displayed when a contact is saved -->
- <string name="contactSavedToast">Contact saved.</string>
+ <!-- Toast displayed when a contact is saved [CHAR LIMIT=NONE] -->
+ <string name="contactSavedToast">Contact saved</string>
<!-- Toast displayed when saving a contact failed -->
<string name="contactSavedErrorToast">Error, unable to save contact changes.</string>
<!-- Toast displayed when a group is saved [CHAR LIMIT=NONE] -->
- <string name="groupSavedToast">Group saved.</string>
+ <string name="groupSavedToast">Group saved</string>
<!-- Toast displayed when saving a group failed [CHAR LIMIT=NONE] -->
<string name="groupSavedErrorToast">Error, unable to save group changes.</string>
@@ -1051,7 +1051,7 @@
<!-- Header that expands to list all website types when editing a website of a contact [CHAR LIMIT=20] -->
<string name="websiteLabelsGroup">Website</string>
<!-- Header that expands to list all event types when editing an event of a contact [CHAR LIMIT=20] -->
- <string name="eventLabelsGroup">Event</string>
+ <string name="eventLabelsGroup">Events</string>
<!-- Header for the list of all relationships for a contact [CHAR LIMIT=20] -->
<string name="relationLabelsGroup">Relationship</string>
<!-- Header for the list of all groups for a contact [CHAR LIMIT=20] -->
@@ -1379,6 +1379,12 @@
<!-- The button to add an organization field to a contact in the Raw Contact Editor [CHAR LIMIT=22] -->
<string name="add_organization">Add organization</string>
+ <!-- The button to add an organization field to a contact in the Raw Contact Editor [CHAR LIMIT=12] -->
+ <string name="event_edit_field_hint_text">Date</string>
+
+ <!-- The button to add an organization field to a contact in the Raw Contact Editor [CHAR LIMIT=15] -->
+ <string name="group_edit_field_hint_text">Group name</string>
+
<!-- Attbution of a contact status update, when the time of update is unknown -->
<string name="contact_status_update_attribution">via <xliff:g id="source" example="Google Talk">%1$s</xliff:g></string>
@@ -1619,9 +1625,6 @@
<!-- Text used in the ticker to notify the user of the latest voicemail. [CHAR LIMIT=30] -->
<string name="notification_new_voicemail_ticker">New voicemail from <xliff:g id="caller">%1$s</xliff:g></string>
- <!-- Initial display for position of current playback, do not translate. -->
- <string name="voicemail_initial_time">00:05</string>
-
<!-- Message to show when there is an error playing back the voicemail. [CHAR LIMIT=40] -->
<string name="voicemail_playback_error">failed to play voicemail</string>
@@ -1732,6 +1735,34 @@
-->
<string name="description_call_log_voicemail">Voicemail</string>
+ <!-- String describing the button to add a contact for the current number.
+
+ Note: AccessibilityServices use this attribute to announce what the view represents.
+ This is especially valuable for views without textual representation like ImageView.
+ -->
+ <string name="description_add_contact">Add contact</string>
+
+ <!-- String describing the button to view the contact for the current number.
+
+ Note: AccessibilityServices use this attribute to announce what the view represents.
+ This is especially valuable for views without textual representation like ImageView.
+ -->
+ <string name="description_view_contact">View contact <xliff:g id="name">%1$s</xliff:g></string>
+
+ <!-- String describing the button to call a number or contact.
+
+ Note: AccessibilityServices use this attribute to announce what the view represents.
+ This is especially valuable for views without textual representation like ImageView.
+ -->
+ <string name="description_call">Call <xliff:g id="name">%1$s</xliff:g></string>
+
+ <!-- String describing the button to SMS a number or contact.
+
+ Note: AccessibilityServices use this attribute to announce what the view represents.
+ This is especially valuable for views without textual representation like ImageView.
+ -->
+ <string name="description_send_text_message">Send text message to <xliff:g id="name">%1$s</xliff:g></string>
+
<!-- String describing the icon in the call log used to represent an unheard voicemail left to
the user.
@@ -1746,6 +1777,12 @@
<!-- String describing the text on the header of the profile contact in the contacts list [CHAR LIMIT=20] -->
<string name="user_profile_contacts_list_header">ME</string>
+ <!-- Header label in the contact editor for a profile that is local to the device only (and not associated with any account) [CHAR LIMIT=25] -->
+ <string name="local_profile_title">My local profile</string>
+
+ <!-- Header label in the contact editor for a profile that comes from an external third-party app whose name is given by source [CHAR LIMIT=20] -->
+ <string name="external_profile_title">My <xliff:g id="external_source">%1$s</xliff:g> profile</string>
+
<!-- Toast shown when the app starts showing all contacts regardless of its current
contact filter state. [CHAR LIMIT=64] -->
<string name="toast_displaying_all_contacts">Displaying all contacts</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index cbb03c4..d202a0f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -280,7 +280,7 @@
<style name="DialtactsDialpadButtonStyle">
<item name="android:layout_width">0dip</item>
- <item name="android:layout_height">@dimen/dialpad_button_height</item>
+ <item name="android:layout_height">match_parent</item>
<item name="android:layout_weight">1</item>
<item name="android:background">@drawable/btn_dial</item>
<item name="android:soundEffectsEnabled">false</item>
diff --git a/src/com/android/contacts/BackScrollManager.java b/src/com/android/contacts/BackScrollManager.java
new file mode 100644
index 0000000..192b79e
--- /dev/null
+++ b/src/com/android/contacts/BackScrollManager.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2011 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.contacts;
+
+import android.view.View;
+import android.widget.AbsListView;
+import android.widget.ListView;
+
+/**
+ * Handles scrolling back of a list tied to a header.
+ * <p>
+ * This is used to implement a header that scrolls up with the content of a list to be partially
+ * obscured.
+ */
+public class BackScrollManager {
+ /** Defines the header to be scrolled. */
+ public interface ScrollableHeader {
+ /** Sets the offset by which to scroll. */
+ public void setOffset(int offset);
+ /** Gets the maximum offset that should be applied to the header. */
+ public int getMaximumScrollableHeaderOffset();
+ }
+
+ private final ScrollableHeader mHeader;
+ private final ListView mListView;
+
+ private final AbsListView.OnScrollListener mScrollListener =
+ new AbsListView.OnScrollListener() {
+ @Override
+ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
+ int totalItemCount) {
+ if (firstVisibleItem != 0) {
+ // The first item is not shown, the header should be pinned at the top.
+ mHeader.setOffset(mHeader.getMaximumScrollableHeaderOffset());
+ return;
+ }
+
+ View firstVisibleItemView = view.getChildAt(firstVisibleItem);
+ if (firstVisibleItemView == null) {
+ return;
+ }
+ // We scroll the header up, but at most pin it to the top of the screen.
+ int offset = Math.min(
+ (int) -view.getChildAt(firstVisibleItem).getY(),
+ mHeader.getMaximumScrollableHeaderOffset());
+ mHeader.setOffset(offset);
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {
+ // Nothing to do here.
+ }
+ };
+
+ /**
+ * Creates a new instance of a {@link BackScrollManager} that connected the header and the list
+ * view.
+ */
+ public static void bind(ScrollableHeader header, ListView listView) {
+ BackScrollManager backScrollManager = new BackScrollManager(header, listView);
+ backScrollManager.bind();
+ }
+
+ private BackScrollManager(ScrollableHeader header, ListView listView) {
+ mHeader = header;
+ mListView = listView;
+ }
+
+ private void bind() {
+ mListView.setOnScrollListener(mScrollListener);
+ // We disable the scroll bar because it would otherwise be incorrect because of the hidden
+ // header.
+ mListView.setVerticalScrollBarEnabled(false);
+ }
+}
diff --git a/src/com/android/contacts/CallDetailActivity.java b/src/com/android/contacts/CallDetailActivity.java
index 5a2e9ea..aa52d91 100644
--- a/src/com/android/contacts/CallDetailActivity.java
+++ b/src/com/android/contacts/CallDetailActivity.java
@@ -16,6 +16,7 @@
package com.android.contacts;
+import com.android.contacts.BackScrollManager.ScrollableHeader;
import com.android.contacts.calllog.CallDetailHistoryAdapter;
import com.android.contacts.calllog.CallTypeHelper;
import com.android.contacts.calllog.PhoneNumberHelper;
@@ -28,7 +29,7 @@
import com.android.contacts.voicemail.VoicemailStatusHelperImpl;
import android.app.ActionBar;
-import android.app.ListActivity;
+import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -37,6 +38,7 @@
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
@@ -54,15 +56,12 @@
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
-import java.util.ArrayList;
import java.util.List;
/**
@@ -71,7 +70,7 @@
* This activity can be either started with the URI of a single call log entry, or with the
* {@link #EXTRA_CALL_LOG_IDS} extra to specify a group of call log entries.
*/
-public class CallDetailActivity extends ListActivity {
+public class CallDetailActivity extends Activity {
private static final String TAG = "CallDetail";
/** A long array extra containing ids of call log entries to display. */
@@ -142,6 +141,20 @@
static final int COLUMN_INDEX_NORMALIZED_NUMBER = 5;
static final int COLUMN_INDEX_PHOTO_URI = 6;
+ private final View.OnClickListener mPrimaryActionListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(((ViewEntry) view.getTag()).primaryIntent);
+ }
+ };
+
+ private final View.OnClickListener mSecondaryActionListener = new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(((ViewEntry) view.getTag()).secondaryIntent);
+ }
+ };
+
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -222,7 +235,7 @@
values.put(Voicemails.IS_READ, true);
getContentResolver().update(voicemailUri, values, null, null);
}
- });
+ }, AsyncTask.THREAD_POOL_EXECUTOR);
}
/**
@@ -322,14 +335,25 @@
// contact from this number.
final Intent mainActionIntent;
final int mainActionIcon;
+ final String mainActionDescription;
+
+ final CharSequence nameOrNumber;
+ if (!TextUtils.isEmpty(firstDetails.name)) {
+ nameOrNumber = firstDetails.name;
+ } else {
+ nameOrNumber = firstDetails.number;
+ }
if (firstDetails.personId != -1) {
Uri personUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, personId);
mainActionIntent = new Intent(Intent.ACTION_VIEW, personUri);
mainActionIcon = R.drawable.ic_contacts_holo_dark;
+ mainActionDescription =
+ getString(R.string.description_view_contact, nameOrNumber);
} else if (isVoicemailNumber) {
mainActionIntent = null;
mainActionIcon = 0;
+ mainActionDescription = null;
} else if (isSipNumber) {
// TODO: This item is currently disabled for SIP addresses, because
// the Insert.PHONE extra only works correctly for PSTN numbers.
@@ -342,16 +366,19 @@
// and then we can remove the "!isSipNumber" check above.
mainActionIntent = null;
mainActionIcon = 0;
+ mainActionDescription = null;
} else if (canPlaceCallsTo) {
mainActionIntent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
mainActionIntent.setType(Contacts.CONTENT_ITEM_TYPE);
mainActionIntent.putExtra(Insert.PHONE, mNumber);
mainActionIcon = R.drawable.ic_add_contact_holo_dark;
+ mainActionDescription = getString(R.string.description_add_contact);
} else {
// If we cannot call the number, when we probably cannot add it as a contact either.
// This is usually the case of private, unknown, or payphone numbers.
mainActionIntent = null;
mainActionIcon = 0;
+ mainActionDescription = null;
}
if (mainActionIntent == null) {
@@ -367,11 +394,9 @@
startActivity(mainActionIntent);
}
});
+ mMainActionPushLayerView.setContentDescription(mainActionDescription);
}
- // Build list of various available actions.
- final List<ViewEntry> actions = new ArrayList<ViewEntry>();
-
// This action allows to call the number that places the call.
if (canPlaceCallsTo) {
final CharSequence displayNumber =
@@ -380,7 +405,8 @@
ViewEntry entry = new ViewEntry(
getString(R.string.menu_callNumber, displayNumber),
- new Intent(Intent.ACTION_CALL_PRIVILEGED, numberCallUri));
+ new Intent(Intent.ACTION_CALL_PRIVILEGED, numberCallUri),
+ getString(R.string.description_call, nameOrNumber));
// Only show a label if the number is shown and it is not a SIP address.
if (!TextUtils.isEmpty(firstDetails.number)
@@ -392,30 +418,44 @@
// The secondary action allows to send an SMS to the number that placed the
// call.
if (mPhoneNumberHelper.canSendSmsTo(mNumber)) {
- entry.setSecondaryAction(R.drawable.ic_text_holo_dark,
+ entry.setSecondaryAction(
+ R.drawable.ic_text_holo_dark,
new Intent(Intent.ACTION_SENDTO,
- Uri.fromParts("sms", mNumber, null)));
+ Uri.fromParts("sms", mNumber, null)),
+ getString(R.string.description_send_text_message, nameOrNumber));
}
- actions.add(entry);
+ configureCallButton(entry);
+ } else {
+ disableCallButton();
}
mHasEditNumberBeforeCall = canPlaceCallsTo && !isSipNumber && !isVoicemailNumber;
- if (actions.size() != 0) {
- // Set the actions for this phone number.
- setListAdapter(new ViewAdapter(CallDetailActivity.this, actions));
- getListView().setVisibility(View.VISIBLE);
- getListView().setItemsCanFocus(true);
- } else {
- getListView().setVisibility(View.GONE);
- }
-
ListView historyList = (ListView) findViewById(R.id.history);
historyList.setAdapter(
new CallDetailHistoryAdapter(CallDetailActivity.this, mInflater,
- mCallTypeHelper, details));
+ mCallTypeHelper, details, hasVoicemail(), canPlaceCallsTo));
+ BackScrollManager.bind(
+ new ScrollableHeader() {
+ private View controls = findViewById(R.id.controls);
+ private View photo = findViewById(R.id.contact_background_sizer);
+ private View nameHeader = findViewById(R.id.photo_text_bar);
+
+ @Override
+ public void setOffset(int offset) {
+ controls.setY(-offset);
+ }
+
+ @Override
+ public int getMaximumScrollableHeaderOffset() {
+ // We can scroll the photo out, but we should keep the header.
+ return photo.getHeight() - nameHeader.getHeight();
+ }
+ },
+ historyList);
loadContactPhotos(photoUri);
+ findViewById(R.id.call_detail).setVisibility(View.VISIBLE);
}
});
}
@@ -506,6 +546,8 @@
static final class ViewEntry {
public final String text;
public final Intent primaryIntent;
+ /** The description for accessibility of the primary action. */
+ public final String primaryDescription;
public CharSequence label = null;
public String number = null;
@@ -513,111 +555,72 @@
public int secondaryIcon = 0;
/** Intent for the secondary action. If not null, an icon must be defined. */
public Intent secondaryIntent = null;
+ /** The description for accessibility of the secondary action. */
+ public String secondaryDescription = null;
- public ViewEntry(String text, Intent intent) {
+ public ViewEntry(String text, Intent intent, String description) {
this.text = text;
- this.primaryIntent = intent;
+ primaryIntent = intent;
+ primaryDescription = description;
}
- public void setSecondaryAction(int icon, Intent intent) {
+ public void setSecondaryAction(int icon, Intent intent, String description) {
secondaryIcon = icon;
secondaryIntent = intent;
+ secondaryDescription = description;
}
}
- private static final class ViewAdapter extends BaseAdapter {
- private final Context mContext;
- private final List<ViewEntry> mActions;
- private final LayoutInflater mInflater;
+ /** Disables the call button area, e.g., for private numbers. */
+ private void disableCallButton() {
+ findViewById(R.id.call_and_sms).setVisibility(View.GONE);
+ }
- private final View.OnClickListener mPrimaryActionListener = new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- ViewEntry entry = (ViewEntry) view.getTag();
- mContext.startActivity(entry.primaryIntent);
- }
- };
+ /** Configures the call button area using the given entry. */
+ private void configureCallButton(ViewEntry entry) {
+ View convertView = findViewById(R.id.call_and_sms);
+ convertView.setVisibility(View.VISIBLE);
- private final View.OnClickListener mSecondaryActionListener = new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- ViewEntry entry = (ViewEntry) view.getTag();
- mContext.startActivity(entry.secondaryIntent);
- }
- };
+ ImageView icon = (ImageView) convertView.findViewById(R.id.call_and_sms_icon);
+ View divider = convertView.findViewById(R.id.call_and_sms_divider);
+ TextView text = (TextView) convertView.findViewById(R.id.call_and_sms_text1);
- public ViewAdapter(Context context, List<ViewEntry> actions) {
- mContext = context;
- mActions = actions;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ View mainAction = convertView.findViewById(R.id.call_and_sms_main_action);
+ mainAction.setOnClickListener(mPrimaryActionListener);
+ mainAction.setTag(entry);
+ mainAction.setContentDescription(entry.primaryDescription);
+
+ if (entry.secondaryIntent != null) {
+ icon.setOnClickListener(mSecondaryActionListener);
+ icon.setImageResource(entry.secondaryIcon);
+ icon.setVisibility(View.VISIBLE);
+ icon.setTag(entry);
+ icon.setContentDescription(entry.secondaryDescription);
+ divider.setVisibility(View.VISIBLE);
+ } else {
+ icon.setVisibility(View.GONE);
+ divider.setVisibility(View.GONE);
}
+ text.setText(entry.text);
- @Override
- public int getCount() {
- return mActions.size();
- }
+ View line2 = convertView.findViewById(R.id.call_and_sms_line2);
+ boolean numberEmpty = TextUtils.isEmpty(entry.number);
+ boolean labelEmpty = TextUtils.isEmpty(entry.label) || numberEmpty;
+ if (labelEmpty && numberEmpty) {
+ line2.setVisibility(View.GONE);
+ } else {
+ line2.setVisibility(View.VISIBLE);
- @Override
- public Object getItem(int position) {
- return mActions.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- // Make sure we have a valid convertView to start with
- if (convertView == null) {
- convertView = mInflater.inflate(R.layout.call_detail_list_item, parent, false);
- }
-
- // Fill action with icon and text.
- ViewEntry entry = mActions.get(position);
-
- ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
- View divider = convertView.findViewById(R.id.divider);
- TextView text = (TextView) convertView.findViewById(android.R.id.text1);
-
- View mainAction = convertView.findViewById(R.id.main_action);
- mainAction.setOnClickListener(mPrimaryActionListener);
- mainAction.setTag(entry);
-
- if (entry.secondaryIntent != null) {
- icon.setOnClickListener(mSecondaryActionListener);
- icon.setImageResource(entry.secondaryIcon);
- icon.setVisibility(View.VISIBLE);
- icon.setTag(entry);
- divider.setVisibility(View.VISIBLE);
+ TextView label = (TextView) convertView.findViewById(R.id.call_and_sms_label);
+ if (labelEmpty) {
+ label.setVisibility(View.GONE);
} else {
- icon.setVisibility(View.GONE);
- divider.setVisibility(View.GONE);
- }
- text.setText(entry.text);
-
- View line2 = convertView.findViewById(R.id.line2);
- boolean numberEmpty = TextUtils.isEmpty(entry.number);
- boolean labelEmpty = TextUtils.isEmpty(entry.label) || numberEmpty;
- if (labelEmpty && numberEmpty) {
- line2.setVisibility(View.GONE);
- } else {
- line2.setVisibility(View.VISIBLE);
-
- TextView label = (TextView) convertView.findViewById(R.id.label);
- if (labelEmpty) {
- label.setVisibility(View.GONE);
- } else {
- label.setText(entry.label);
- label.setVisibility(View.VISIBLE);
- }
-
- TextView number = (TextView) convertView.findViewById(R.id.number);
- number.setText(entry.number);
+ label.setText(entry.label);
+ label.setVisibility(View.VISIBLE);
}
- return convertView;
+ TextView number = (TextView) convertView.findViewById(R.id.call_and_sms_number);
+ number.setText(entry.number);
}
}
diff --git a/src/com/android/contacts/ContactsApplication.java b/src/com/android/contacts/ContactsApplication.java
index 1e791b6..0aba332 100644
--- a/src/com/android/contacts/ContactsApplication.java
+++ b/src/com/android/contacts/ContactsApplication.java
@@ -16,6 +16,8 @@
package com.android.contacts;
+import static com.android.contacts.util.BackgroundTaskService.createAsyncTaskBackgroundTaskService;
+
import com.android.contacts.model.AccountTypeManager;
import com.android.contacts.test.InjectedServices;
import com.android.contacts.util.BackgroundTaskService;
@@ -97,7 +99,7 @@
if (BackgroundTaskService.BACKGROUND_TASK_SERVICE.equals(name)) {
if (mBackgroundTaskService == null) {
- mBackgroundTaskService = BackgroundTaskService.createBackgroundTaskService();
+ mBackgroundTaskService = createAsyncTaskBackgroundTaskService();
}
return mBackgroundTaskService;
}
diff --git a/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java b/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java
index 3de5730..ed9c2e0 100644
--- a/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java
+++ b/src/com/android/contacts/calllog/CallDetailHistoryAdapter.java
@@ -32,42 +32,86 @@
* Adapter for a ListView containing history items from the details of a call.
*/
public class CallDetailHistoryAdapter extends BaseAdapter {
+ /** The top element is a blank header, which is hidden under the rest of the UI. */
+ private static final int VIEW_TYPE_HEADER = 0;
+ /** Each history item shows the detail of a call. */
+ private static final int VIEW_TYPE_HISTORY_ITEM = 1;
+
private final Context mContext;
private final LayoutInflater mLayoutInflater;
private final CallTypeHelper mCallTypeHelper;
private final PhoneCallDetails[] mPhoneCallDetails;
+ /** Whether the voicemail controls are shown. */
+ private final boolean mShowVoicemail;
+ /** Whether the call and SMS controls are shown. */
+ private final boolean mShowCallAndSms;
public CallDetailHistoryAdapter(Context context, LayoutInflater layoutInflater,
- CallTypeHelper callTypeHelper, PhoneCallDetails[] phoneCallDetails) {
+ CallTypeHelper callTypeHelper, PhoneCallDetails[] phoneCallDetails,
+ boolean showVoicemail, boolean showCallAndSms) {
mContext = context;
mLayoutInflater = layoutInflater;
mCallTypeHelper = callTypeHelper;
mPhoneCallDetails = phoneCallDetails;
+ mShowVoicemail = showVoicemail;
+ mShowCallAndSms = showCallAndSms;
}
@Override
public int getCount() {
- return mPhoneCallDetails.length;
+ return mPhoneCallDetails.length + 1;
}
@Override
public Object getItem(int position) {
- return mPhoneCallDetails[position];
+ if (position == 0) {
+ return null;
+ }
+ return mPhoneCallDetails[position - 1];
}
@Override
public long getItemId(int position) {
- return position;
+ if (position == 0) {
+ return -1;
+ }
+ return position - 1;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 2;
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ if (position == 0) {
+ return VIEW_TYPE_HEADER;
+ }
+ return VIEW_TYPE_HISTORY_ITEM;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
+ if (position == 0) {
+ final View header = convertView == null
+ ? mLayoutInflater.inflate(R.layout.call_detail_history_header, parent, false)
+ : convertView;
+ // Voicemail controls are only shown in the main UI if there is a voicemail.
+ View voicemailContainer = header.findViewById(R.id.header_voicemail_container);
+ voicemailContainer.setVisibility(mShowVoicemail ? View.VISIBLE : View.GONE);
+ // Call and SMS controls are only shown in the main UI if there is a known number.
+ View callAndSmsContainer = header.findViewById(R.id.header_call_and_sms_container);
+ callAndSmsContainer.setVisibility(mShowCallAndSms ? View.VISIBLE : View.GONE);
+ return header;
+ }
+
// Make sure we have a valid convertView to start with
final View result = convertView == null
? mLayoutInflater.inflate(R.layout.call_detail_history_item, parent, false)
: convertView;
- PhoneCallDetails details = mPhoneCallDetails[position];
+ PhoneCallDetails details = mPhoneCallDetails[position - 1];
CallTypeIconsView callTypeIconView =
(CallTypeIconsView) result.findViewById(R.id.call_type_icon);
TextView callTypeTextView = (TextView) result.findViewById(R.id.call_type_text);
diff --git a/src/com/android/contacts/editor/EventFieldEditorView.java b/src/com/android/contacts/editor/EventFieldEditorView.java
index e7da6c1..4a5a502 100644
--- a/src/com/android/contacts/editor/EventFieldEditorView.java
+++ b/src/com/android/contacts/editor/EventFieldEditorView.java
@@ -80,7 +80,7 @@
Resources resources = mContext.getResources();
mPrimaryTextColor = resources.getColor(R.color.primary_text_color);
mSecondaryTextColor = resources.getColor(R.color.secondary_text_color);
- mNoDateString = mContext.getString(R.string.add_new_entry_for_section);
+ mNoDateString = mContext.getString(R.string.event_edit_field_hint_text);
mDateView = (Button) findViewById(R.id.date_view);
mDateView.setOnClickListener(new OnClickListener() {
diff --git a/src/com/android/contacts/editor/GroupMembershipView.java b/src/com/android/contacts/editor/GroupMembershipView.java
index 042b80a..42d2edd 100644
--- a/src/com/android/contacts/editor/GroupMembershipView.java
+++ b/src/com/android/contacts/editor/GroupMembershipView.java
@@ -115,7 +115,7 @@
Resources resources = mContext.getResources();
mPrimaryTextColor = resources.getColor(R.color.primary_text_color);
mSecondaryTextColor = resources.getColor(R.color.secondary_text_color);
- mNoGroupString = mContext.getString(R.string.add_new_entry_for_section);
+ mNoGroupString = mContext.getString(R.string.group_edit_field_hint_text);
}
@Override
diff --git a/src/com/android/contacts/group/GroupDetailFragment.java b/src/com/android/contacts/group/GroupDetailFragment.java
index a27d3e0..1205c31 100644
--- a/src/com/android/contacts/group/GroupDetailFragment.java
+++ b/src/com/android/contacts/group/GroupDetailFragment.java
@@ -149,6 +149,7 @@
mGroupSourceViewContainer = (ViewGroup) mRootView.findViewById(
R.id.group_source_view_container);
mMemberListView = (ListView) mRootView.findViewById(android.R.id.list);
+ mMemberListView.setAdapter(mAdapter);
return mRootView;
}
@@ -162,11 +163,6 @@
mAdapter.enableQuickContact(enableQuickContact);
}
- private void configureAdapter(long groupId) {
- mGroupId = groupId;
- mMemberListView.setAdapter(mAdapter);
- }
-
private void configurePhotoLoader() {
if (mContext != null) {
if (mPhotoManager == null) {
@@ -234,7 +230,6 @@
bindGroupMetaData(data);
// Retrieve the list of members
- configureAdapter(mGroupId);
startGroupMembersLoader();
return;
}
diff --git a/src/com/android/contacts/list/ContactBrowseListFragment.java b/src/com/android/contacts/list/ContactBrowseListFragment.java
index fc9abe7..2380345 100644
--- a/src/com/android/contacts/list/ContactBrowseListFragment.java
+++ b/src/com/android/contacts/list/ContactBrowseListFragment.java
@@ -378,7 +378,8 @@
return;
}
- if (!isSearchMode() && mFilter != null) {
+ boolean searchMode = isSearchMode();
+ if (!searchMode && mFilter != null) {
adapter.setFilter(mFilter);
if (mSelectionRequired
|| mFilter.filterType == ContactListFilter.FILTER_TYPE_SINGLE_CONTACT) {
@@ -387,8 +388,8 @@
}
}
- // Display the user's profile.
- adapter.setIncludeProfile(true);
+ // Display the user's profile if not in search mode
+ adapter.setIncludeProfile(!searchMode);
}
@Override
diff --git a/src/com/android/contacts/list/DefaultContactListAdapter.java b/src/com/android/contacts/list/DefaultContactListAdapter.java
index e9804f5..f081921 100644
--- a/src/com/android/contacts/list/DefaultContactListAdapter.java
+++ b/src/com/android/contacts/list/DefaultContactListAdapter.java
@@ -196,7 +196,8 @@
+ "SELECT DISTINCT " + RawContacts.CONTACT_ID
+ " FROM raw_contacts"
+ " WHERE " + RawContacts.ACCOUNT_TYPE + "=?"
- + " AND " + RawContacts.ACCOUNT_NAME + "=?");
+ + " AND " + RawContacts.ACCOUNT_NAME + "=?"
+ + " OR " + Contacts.IS_USER_PROFILE + "=1");
selectionArgs.add(filter.accountType);
selectionArgs.add(filter.accountName);
if (filter.dataSet != null) {
diff --git a/src/com/android/contacts/util/BackgroundTaskService.java b/src/com/android/contacts/util/BackgroundTaskService.java
index 00f9e3e..310a178 100644
--- a/src/com/android/contacts/util/BackgroundTaskService.java
+++ b/src/com/android/contacts/util/BackgroundTaskService.java
@@ -18,25 +18,54 @@
import android.os.AsyncTask;
+import java.util.concurrent.Executor;
+
/**
* Service used to submit tasks to run in the background.
* <p>
* BackgroundTaskService makes the same memory-visibility guarantees that AsyncTask which it
* emulates makes, namely that fields set in the {@link BackgroundTask#doInBackground()} method
* will be visible to the {@link BackgroundTask#onPostExecute()} method.
+ * <p>
+ * You are not expected to derive from this class unless you are writing your own test
+ * implementation, or you are absolutely sure that the instance in
+ * {@link #createAsyncTaskBackgroundTaskService()} doesn't do what you need.
*/
public abstract class BackgroundTaskService {
public static final String BACKGROUND_TASK_SERVICE = BackgroundTaskService.class.getName();
+ /**
+ * Executes the given BackgroundTask with the default Executor.
+ * <p>
+ * All {@link BackgroundTask#doInBackground()} tasks will be guaranteed to happen serially.
+ * If this is not what you want, see {@link #submit(BackgroundTask, Executor)}.
+ */
public abstract void submit(BackgroundTask task);
- public static BackgroundTaskService createBackgroundTaskService() {
+ /**
+ * Executes the BackgroundTask with the supplied Executor.
+ * <p>
+ * The main use-case for this method will be to allow submitted tasks to perform their
+ * {@link BackgroundTask#doInBackground()} methods concurrently.
+ */
+ public abstract void submit(BackgroundTask task, Executor executor);
+
+ /**
+ * Creates a concrete BackgroundTaskService whose default Executor is
+ * {@link AsyncTask#SERIAL_EXECUTOR}.
+ */
+ public static BackgroundTaskService createAsyncTaskBackgroundTaskService() {
return new AsyncTaskBackgroundTaskService();
}
private static final class AsyncTaskBackgroundTaskService extends BackgroundTaskService {
@Override
- public void submit(final BackgroundTask task) {
+ public void submit(BackgroundTask task) {
+ submit(task, AsyncTask.SERIAL_EXECUTOR);
+ }
+
+ @Override
+ public void submit(final BackgroundTask task, Executor executor) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
@@ -48,7 +77,7 @@
protected void onPostExecute(Void result) {
task.onPostExecute();
}
- }.execute();
+ }.executeOnExecutor(executor);
}
}
}
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
index e901fab..494888c 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
@@ -27,6 +27,7 @@
import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.SeekBar;
@@ -165,7 +166,7 @@
mView.playbackError(mException);
}
}
- });
+ }, AsyncTask.THREAD_POOL_EXECUTOR);
}
private void postSuccessfulPrepareActions() {
diff --git a/tests/src/com/android/contacts/ContactLoaderTest.java b/tests/src/com/android/contacts/ContactLoaderTest.java
index ac691bc..a731f24 100644
--- a/tests/src/com/android/contacts/ContactLoaderTest.java
+++ b/tests/src/com/android/contacts/ContactLoaderTest.java
@@ -301,6 +301,7 @@
Contacts.SEND_TO_VOICEMAIL,
Contacts.CUSTOM_RINGTONE,
+ Contacts.IS_USER_PROFILE,
})
.withSortOrder(Contacts.Entity.RAW_CONTACT_ID)
.returnRow(
@@ -337,7 +338,8 @@
"content:some.photo.uri",
0,
- null
+ null,
+ 0
);
}
diff --git a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
index 40a33b6..bb93b98 100644
--- a/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
+++ b/tests/src/com/android/contacts/PhoneCallDetailsHelperTest.java
@@ -175,34 +175,25 @@
}
public void testSetPhoneCallDetails_Geocode() {
- setPhoneCallDetailsWithNumber("+14125555555", "1-412-555-5555");
+ setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", "Pennsylvania");
assertNameEquals("1-412-555-5555"); // The phone number is shown as the name.
assertNumberEquals("Pennsylvania"); // The geocode is shown as the number.
}
public void testSetPhoneCallDetails_NoGeocode() {
- setPhoneCallDetailsWithNumber("+0", "+0");
- assertNameEquals("+0"); // The phone number is shown as the name.
+ setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", null);
+ assertNameEquals("1-412-555-5555"); // The phone number is shown as the name.
assertNumberEquals("-"); // The empty geocode is shown as the number.
}
- public void testSetPhoneCallDetails_NoGeocodeForUnknown() {
- setPhoneCallDetailsWithNumber(CallerInfo.UNKNOWN_NUMBER, "");
- assertNumberEquals("-"); // The empty geocode is shown as the number.
- }
-
- public void testSetPhoneCallDetails_NoGeocodeForPrivate() {
- setPhoneCallDetailsWithNumber(CallerInfo.PRIVATE_NUMBER, "");
- assertNumberEquals("-"); // The empty geocode is shown as the number.
- }
-
- public void testSetPhoneCallDetails_NoGeocodeForPayphone() {
- setPhoneCallDetailsWithNumber(CallerInfo.PAYPHONE_NUMBER, "");
+ public void testSetPhoneCallDetails_EmptyGeocode() {
+ setPhoneCallDetailsWithNumberAndGeocode("+14125555555", "1-412-555-5555", "");
+ assertNameEquals("1-412-555-5555"); // The phone number is shown as the name.
assertNumberEquals("-"); // The empty geocode is shown as the number.
}
public void testSetPhoneCallDetails_NoGeocodeForVoicemail() {
- setPhoneCallDetailsWithNumber(TEST_VOICEMAIL_NUMBER, "");
+ setPhoneCallDetailsWithNumberAndGeocode(TEST_VOICEMAIL_NUMBER, "", "United States");
assertNumberEquals("-"); // The empty geocode is shown as the number.
}
@@ -269,8 +260,14 @@
/** Sets the phone call details with default values and the given number. */
private void setPhoneCallDetailsWithNumber(String number, String formattedNumber) {
+ setPhoneCallDetailsWithNumberAndGeocode(number, formattedNumber, TEST_GEOCODE);
+ }
+
+ /** Sets the phone call details with default values and the given number. */
+ private void setPhoneCallDetailsWithNumberAndGeocode(String number, String formattedNumber,
+ String geocodedLocation) {
mHelper.setPhoneCallDetails(mViews,
- new PhoneCallDetails(number, formattedNumber, TEST_COUNTRY_ISO, TEST_GEOCODE,
+ new PhoneCallDetails(number, formattedNumber, TEST_COUNTRY_ISO, geocodedLocation,
new int[]{ Calls.VOICEMAIL_TYPE }, TEST_DATE, TEST_DURATION),
true);
}
diff --git a/tests/src/com/android/contacts/activities/CallLogActivityTests.java b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
index ce2418f..070941c 100644
--- a/tests/src/com/android/contacts/activities/CallLogActivityTests.java
+++ b/tests/src/com/android/contacts/activities/CallLogActivityTests.java
@@ -69,6 +69,7 @@
Calls.TYPE,
Calls.COUNTRY_ISO,
Calls.VOICEMAIL_URI,
+ Calls.GEOCODED_LOCATION,
CallLogFragment.CallLogQuery.SECTION_NAME,
};
private static final int RAND_DURATION = -1;
@@ -505,6 +506,7 @@
row.add(type); // type
row.add(TEST_COUNTRY_ISO); // country ISO
row.add(null); // voicemail_uri
+ row.add(null); // geocoded_location
row.add(CallLogFragment.CallLogQuery.SECTION_OLD_ITEM); // section
}
@@ -535,6 +537,7 @@
row.add(Calls.VOICEMAIL_TYPE); // type
row.add(TEST_COUNTRY_ISO); // country ISO
row.add(voicemailUri); // voicemail_uri
+ row.add(null); // geocoded_location
row.add(CallLogFragment.CallLogQuery.SECTION_OLD_ITEM); // section
}
diff --git a/tests/src/com/android/contacts/calllog/CallLogGroupBuilderTest.java b/tests/src/com/android/contacts/calllog/CallLogGroupBuilderTest.java
index 9aa5d7b..8a7e946 100644
--- a/tests/src/com/android/contacts/calllog/CallLogGroupBuilderTest.java
+++ b/tests/src/com/android/contacts/calllog/CallLogGroupBuilderTest.java
@@ -224,7 +224,7 @@
}
mCursor.moveToNext();
mCursor.addRow(new Object[]{
- mCursor.getPosition(), number, 0L, 0L, type, "", "", section
+ mCursor.getPosition(), number, 0L, 0L, type, "", "", "", section
});
}
@@ -245,7 +245,7 @@
throw new IllegalArgumentException("not a header section: " + section);
}
mCursor.moveToNext();
- mCursor.addRow(new Object[]{ mCursor.getPosition(), "", 0L, 0L, 0, "", "", section });
+ mCursor.addRow(new Object[]{ mCursor.getPosition(), "", 0L, 0L, 0, "", "", "", section });
}
/** Asserts that the group matches the given values. */
diff --git a/tests/src/com/android/contacts/format/DisplayNameFormatterTest.java b/tests/src/com/android/contacts/format/DisplayNameFormatterTest.java
index fb834c0..24714cd 100644
--- a/tests/src/com/android/contacts/format/DisplayNameFormatterTest.java
+++ b/tests/src/com/android/contacts/format/DisplayNameFormatterTest.java
@@ -53,32 +53,32 @@
public void testSetDisplayName_Simple() {
setNames("John Doe", "Doe John");
setDisplayName();
- SpannedTestUtils.checkHtmlText("<b>John </b>Doe", mView);
+ SpannedTestUtils.checkHtmlText("John Doe", mView);
setNames("Jean Pierre Doe", "Doe Jean Pierre");
setDisplayName();
- SpannedTestUtils.checkHtmlText("<b>Jean Pierre </b>Doe", mView);
+ SpannedTestUtils.checkHtmlText("Jean Pierre Doe", mView);
setNames("John Doe Smith", "Doe Smith John");
setDisplayName();
- SpannedTestUtils.checkHtmlText("<b>John </b>Doe Smith", mView);
+ SpannedTestUtils.checkHtmlText("John Doe Smith", mView);
}
public void testSetDisplayName_AccidentalOverlap() {
// This is probably not what we want, but we assume that the two names differ only in the
// order in which the two components are listed.
setNames("Johnson John", "Johnson Smith");
setDisplayName();
- SpannedTestUtils.checkHtmlText("<b>Johnson </b>John", mView);
+ SpannedTestUtils.checkHtmlText("Johnson John", mView);
}
public void testSetDisplayName_Reversed() {
setNames("John Doe", "Doe John");
setDisplayNameReversed();
- SpannedTestUtils.checkHtmlText("John <b>Doe</b>", mView);
+ SpannedTestUtils.checkHtmlText("John Doe", mView);
setNames("Jean Pierre Doe", "Doe Jean Pierre");
setDisplayNameReversed();
- SpannedTestUtils.checkHtmlText("Jean Pierre <b>Doe</b>", mView);
+ SpannedTestUtils.checkHtmlText("Jean Pierre Doe", mView);
setNames("John Doe Smith", "Doe Smith John");
setDisplayNameReversed();
- SpannedTestUtils.checkHtmlText("John <b>Doe Smith</b>", mView);
+ SpannedTestUtils.checkHtmlText("John Doe Smith", mView);
}
public void testSetDisplayName_NoOverlap() {
@@ -90,26 +90,26 @@
public void testSetDisplayName_Prefix() {
setNames("John Doe", "Doe John");
setDisplayNameWithPrefix("DO");
- SpannedTestUtils.checkHtmlText("<b>John </b>" + START + "Do" + END + "e", mView);
+ SpannedTestUtils.checkHtmlText("John " + START + "Do" + END + "e", mView);
}
public void testSetDisplayName_PrefixFirstName() {
setNames("John Doe", "Doe John");
setDisplayNameWithPrefix("JO");
- SpannedTestUtils.checkHtmlText(START + "<b>Jo</b>" + END + "<b>hn </b>Doe", mView);
+ SpannedTestUtils.checkHtmlText(START + "Jo" + END + "hn Doe", mView);
}
public void testSetDisplayName_PrefixMiddleName() {
setNames("John Paul Doe", "Doe John Paul");
setDisplayNameWithPrefix("PAU");
- SpannedTestUtils.checkHtmlText("<b>John </b>" + START + "<b>Pau</b>" + END + "<b>l </b>Doe",
+ SpannedTestUtils.checkHtmlText("John " + START + "Pau" + END + "l Doe",
mView);
}
public void testSetDisplayName_ReversedPrefix() {
setNames("John Doe", "Doe John");
setDisplayNameReversedWithPrefix("DO");
- SpannedTestUtils.checkHtmlText("John " + START + "<b>Do</b>" + END + "<b>e</b>", mView);
+ SpannedTestUtils.checkHtmlText("John " + START + "Do" + END + "e", mView);
}
public void testSetDisplayName_Empty() {
@@ -136,7 +136,7 @@
mDisplayNameFormatter.setTextWithHighlightingFactory(new TestTextWithHighlightingFactory());
setNames("John Doe", "Doe John");
setDisplayNameWithHighlighting();
- SpannedTestUtils.checkHtmlText("<i><b>John </b></i><i>Doe</i> <i>Doe John</i>", mView);
+ SpannedTestUtils.checkHtmlText("<i>John Doe</i> <i>Doe John</i>", mView);
}
/**
diff --git a/tests/src/com/android/contacts/list/ContactListItemViewTest.java b/tests/src/com/android/contacts/list/ContactListItemViewTest.java
index 7764eb3..ccd2fb5 100644
--- a/tests/src/com/android/contacts/list/ContactListItemViewTest.java
+++ b/tests/src/com/android/contacts/list/ContactListItemViewTest.java
@@ -51,7 +51,7 @@
view.showDisplayName(cursor, 0, 1, false,
ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
- SpannedTestUtils.checkHtmlText("<b>John </b>Doe", view.getNameTextView());
+ SpannedTestUtils.checkHtmlText("John Doe", view.getNameTextView());
}
public void testShowDisplayName_Unknown() {
@@ -73,7 +73,7 @@
view.showDisplayName(cursor, 0, 1, false,
ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
- SpannedTestUtils.checkHtmlText("<b>John </b>" + START + "Doe" + END,
+ SpannedTestUtils.checkHtmlText("John " + START + "Doe" + END,
view.getNameTextView());
}
@@ -85,7 +85,7 @@
view.showDisplayName(cursor, 0, 1, false,
ContactsContract.Preferences.DISPLAY_ORDER_ALTERNATIVE);
- SpannedTestUtils.checkHtmlText("John " + START + "<b>Doe</b>" + END,
+ SpannedTestUtils.checkHtmlText("John " + START + "Doe" + END,
view.getNameTextView());
}
@@ -97,7 +97,7 @@
view.showDisplayName(cursor, 0, 1, true,
ContactsContract.Preferences.DISPLAY_ORDER_PRIMARY);
- SpannedTestUtils.checkHtmlText("<i><b>John </b></i><i>Doe</i> <i>Doe John</i>",
+ SpannedTestUtils.checkHtmlText("<i>John Doe</i> <i>Doe John</i>",
view.getNameTextView());
}
diff --git a/tests/src/com/android/contacts/util/FakeBackgroundTaskService.java b/tests/src/com/android/contacts/util/FakeBackgroundTaskService.java
index a9d80b4..26be519 100644
--- a/tests/src/com/android/contacts/util/FakeBackgroundTaskService.java
+++ b/tests/src/com/android/contacts/util/FakeBackgroundTaskService.java
@@ -35,6 +35,11 @@
mSubmittedTasks.add(task);
}
+ @Override
+ public void submit(BackgroundTask task, Executor executor) {
+ mSubmittedTasks.add(task);
+ }
+
public List<BackgroundTask> getSubmittedTasks() {
return mSubmittedTasks;
}