summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AndroidManifest.xml2
-rw-r--r--res/anim/quickcontact_above_enter.xml29
-rw-r--r--res/anim/quickcontact_above_exit.xml29
-rw-r--r--res/anim/quickcontact_below_enter.xml29
-rw-r--r--res/anim/quickcontact_below_exit.xml29
-rw-r--r--res/drawable-hdpi/ic_fav_quickcontact_holo_dark.pngbin0 -> 948 bytes
-rw-r--r--res/drawable-hdpi/ic_text_holo_dark.pngbin0 -> 1231 bytes
-rw-r--r--res/drawable-hdpi/quickactions_arrowdown_left_holo_light.9.pngbin433 -> 0 bytes
-rw-r--r--res/drawable-hdpi/quickactions_arrowdown_middle_holo_light.9.pngbin652 -> 0 bytes
-rw-r--r--res/drawable-hdpi/quickactions_arrowdown_right_holo_light.9.pngbin447 -> 0 bytes
-rw-r--r--res/drawable-hdpi/quickactions_arrowup_left_holo_light.9.pngbin437 -> 0 bytes
-rw-r--r--res/drawable-hdpi/quickactions_arrowup_middle_holo_light.9.pngbin680 -> 0 bytes
-rw-r--r--res/drawable-hdpi/quickactions_arrowup_right_holo_light.9.pngbin435 -> 0 bytes
-rw-r--r--res/drawable-hdpi/quickcon_background_texture.pngbin0 -> 303 bytes
-rw-r--r--res/drawable-mdpi/ic_fav_quickcontact_holo_dark.pngbin0 -> 813 bytes
-rw-r--r--res/drawable-mdpi/ic_text_holo_dark.pngbin0 -> 898 bytes
-rw-r--r--res/drawable-mdpi/quickactions_arrowdown_left_holo_light.9.pngbin340 -> 0 bytes
-rw-r--r--res/drawable-mdpi/quickactions_arrowdown_middle_holo_light.9.pngbin533 -> 0 bytes
-rw-r--r--res/drawable-mdpi/quickactions_arrowdown_right_holo_light.9.pngbin357 -> 0 bytes
-rw-r--r--res/drawable-mdpi/quickactions_arrowup_left_holo_light.9.pngbin336 -> 0 bytes
-rw-r--r--res/drawable-mdpi/quickactions_arrowup_middle_holo_light.9.pngbin488 -> 0 bytes
-rw-r--r--res/drawable-mdpi/quickactions_arrowup_right_holo_light.9.pngbin331 -> 0 bytes
-rw-r--r--res/drawable-mdpi/quickcon_background_texture.pngbin0 -> 273 bytes
-rw-r--r--res/drawable-xhdpi/ic_fav_quickcontact_holo_dark.pngbin0 -> 1103 bytes
-rw-r--r--res/drawable-xhdpi/ic_text_holo_dark.pngbin0 -> 1627 bytes
-rw-r--r--res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.pngbin546 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/quickactions_arrowdown_middle_holo_light.9.pngbin856 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.pngbin572 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.pngbin545 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/quickactions_arrowup_middle_holo_light.9.pngbin902 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.pngbin536 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/quickcon_background_texture.pngbin0 -> 281 bytes
-rw-r--r--res/drawable/quickactions_arrow_middle_holo_light.xml21
-rw-r--r--res/drawable/quickactions_arrow_right_holo_light.xml21
-rw-r--r--res/drawable/quickcontact_list_item_background.xml (renamed from res/drawable/quickactions_arrow_left_holo_light.xml)22
-rw-r--r--res/drawable/quickcontact_slider_btn.xml30
-rw-r--r--res/drawable/quickcontact_track_background.xml (renamed from res/layout/quickcontact_header_small.xml)11
-rw-r--r--res/layout-sw580dp/quickcontact_activity.xml42
-rw-r--r--res/layout-w470dp/quickcontact_activity.xml44
-rw-r--r--res/layout/quickcontact.xml136
-rw-r--r--res/layout/quickcontact_activity.xml22
-rwxr-xr-xres/layout/quickcontact_default_item.xml40
-rw-r--r--res/layout/quickcontact_header_large.xml79
-rw-r--r--res/layout/quickcontact_header_med.xml55
-rwxr-xr-x[-rw-r--r--]res/layout/quickcontact_list_fragment.xml (renamed from res/layout-finger/quickcontact_item_nodata.xml)29
-rwxr-xr-xres/layout/quickcontact_list_item.xml60
-rw-r--r--res/layout/quickcontact_photo_container.xml90
-rwxr-xr-xres/layout/quickcontact_resolve_item.xml40
-rw-r--r--res/layout/quickcontact_track.xml42
-rw-r--r--res/layout/quickcontact_track_button.xml (renamed from res/layout/quickcontact_item.xml)10
-rw-r--r--res/values-sw580dp-w1000dp/dimens.xml1
-rw-r--r--res/values-sw580dp/dimens.xml4
-rw-r--r--res/values-w470dp/dimens.xml3
-rw-r--r--res/values/colors.xml4
-rw-r--r--res/values/dimens.xml15
-rw-r--r--res/values/strings.xml21
-rw-r--r--res/values/styles.xml2
-rw-r--r--src/com/android/contacts/TypePrecedence.java2
-rw-r--r--src/com/android/contacts/list/ContactTileAdapter.java8
-rw-r--r--src/com/android/contacts/model/BaseAccountType.java1
-rw-r--r--src/com/android/contacts/model/DataKind.java3
-rw-r--r--src/com/android/contacts/quickcontact/Action.java17
-rw-r--r--src/com/android/contacts/quickcontact/ClearDefaultsAction.java82
-rw-r--r--src/com/android/contacts/quickcontact/DataAction.java107
-rw-r--r--src/com/android/contacts/quickcontact/FloatingChildLayout.java170
-rw-r--r--src/com/android/contacts/quickcontact/ProfileAction.java100
-rw-r--r--src/com/android/contacts/quickcontact/QuickContactActivity.java722
-rw-r--r--src/com/android/contacts/quickcontact/QuickContactBackgroundDrawable.java136
-rw-r--r--src/com/android/contacts/quickcontact/QuickContactListFragment.java151
-rw-r--r--src/com/android/contacts/quickcontact/QuickContactWindow.java1026
-rw-r--r--src/com/android/contacts/quickcontact/ResolveCache.java8
-rw-r--r--src/com/android/contacts/util/Constants.java9
-rw-r--r--tests/res/layout/quick_contact_tests.xml12
73 files changed, 1394 insertions, 2122 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4c5b19f43..b669152a7 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -390,7 +390,7 @@
<!-- Used to show QuickContact window over a translucent activity, which is a
temporary hack until we add better framework support. -->
<activity
- android:name=".quickcontact.QuickContactWindow"
+ android:name=".quickcontact.QuickContactActivity"
android:theme="@style/Theme.QuickContact"
android:launchMode="singleTop"
android:excludeFromRecents="true"
diff --git a/res/anim/quickcontact_above_enter.xml b/res/anim/quickcontact_above_enter.xml
deleted file mode 100644
index d86c98c49..000000000
--- a/res/anim/quickcontact_above_enter.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android">
- <scale android:interpolator="@android:interpolator/decelerate_quint"
- android:fromXScale="1" android:toXScale="1.0"
- android:fromYScale="0.8" android:toYScale="1.0"
- android:pivotX="50%" android:pivotY="100%"
- android:duration="@android:integer/config_shortAnimTime" />
- <alpha android:interpolator="@android:interpolator/decelerate_cubic"
- android:fromAlpha="0.0" android:toAlpha="1.0"
- android:duration="@android:integer/config_shortAnimTime" />
-</set>
diff --git a/res/anim/quickcontact_above_exit.xml b/res/anim/quickcontact_above_exit.xml
deleted file mode 100644
index e8a16b4bf..000000000
--- a/res/anim/quickcontact_above_exit.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android">
- <scale android:interpolator="@android:interpolator/accelerate_quint"
- android:fromXScale="1.0" android:toXScale="1.0"
- android:fromYScale="1.0" android:toYScale=".8"
- android:pivotX="50%" android:pivotY="100%"
- android:duration="@android:integer/config_shortAnimTime" />
- <alpha android:interpolator="@android:interpolator/accelerate_cubic"
- android:fromAlpha="1.0" android:toAlpha="0"
- android:duration="@android:integer/config_shortAnimTime" />
-</set>
diff --git a/res/anim/quickcontact_below_enter.xml b/res/anim/quickcontact_below_enter.xml
deleted file mode 100644
index 39aa17746..000000000
--- a/res/anim/quickcontact_below_enter.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android">
- <scale android:interpolator="@android:interpolator/decelerate_quint"
- android:fromXScale="1" android:toXScale="1.0"
- android:fromYScale="0.8" android:toYScale="1.0"
- android:pivotX="50%" android:pivotY="0%"
- android:duration="@android:integer/config_shortAnimTime" />
- <alpha android:interpolator="@android:interpolator/decelerate_cubic"
- android:fromAlpha="0.0" android:toAlpha="1.0"
- android:duration="@android:integer/config_shortAnimTime" />
-</set>
diff --git a/res/anim/quickcontact_below_exit.xml b/res/anim/quickcontact_below_exit.xml
deleted file mode 100644
index 8f70751d4..000000000
--- a/res/anim/quickcontact_below_exit.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android">
- <scale android:interpolator="@android:interpolator/accelerate_quint"
- android:fromXScale="1.0" android:toXScale="1.0"
- android:fromYScale="1.0" android:toYScale="0.8"
- android:pivotX="50%" android:pivotY="0%"
- android:duration="@android:integer/config_shortAnimTime" />
- <alpha android:interpolator="@android:interpolator/accelerate_cubic"
- android:fromAlpha="1.0" android:toAlpha="0"
- android:duration="@android:integer/config_shortAnimTime" />
-</set>
diff --git a/res/drawable-hdpi/ic_fav_quickcontact_holo_dark.png b/res/drawable-hdpi/ic_fav_quickcontact_holo_dark.png
new file mode 100644
index 000000000..06dc777e0
--- /dev/null
+++ b/res/drawable-hdpi/ic_fav_quickcontact_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/ic_text_holo_dark.png b/res/drawable-hdpi/ic_text_holo_dark.png
new file mode 100644
index 000000000..181620118
--- /dev/null
+++ b/res/drawable-hdpi/ic_text_holo_dark.png
Binary files differ
diff --git a/res/drawable-hdpi/quickactions_arrowdown_left_holo_light.9.png b/res/drawable-hdpi/quickactions_arrowdown_left_holo_light.9.png
deleted file mode 100644
index b09016bb5..000000000
--- a/res/drawable-hdpi/quickactions_arrowdown_left_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/quickactions_arrowdown_middle_holo_light.9.png b/res/drawable-hdpi/quickactions_arrowdown_middle_holo_light.9.png
deleted file mode 100644
index 670d89fe2..000000000
--- a/res/drawable-hdpi/quickactions_arrowdown_middle_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/quickactions_arrowdown_right_holo_light.9.png b/res/drawable-hdpi/quickactions_arrowdown_right_holo_light.9.png
deleted file mode 100644
index 81f4859a5..000000000
--- a/res/drawable-hdpi/quickactions_arrowdown_right_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/quickactions_arrowup_left_holo_light.9.png b/res/drawable-hdpi/quickactions_arrowup_left_holo_light.9.png
deleted file mode 100644
index 99ad9e21d..000000000
--- a/res/drawable-hdpi/quickactions_arrowup_left_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/quickactions_arrowup_middle_holo_light.9.png b/res/drawable-hdpi/quickactions_arrowup_middle_holo_light.9.png
deleted file mode 100644
index 500d82093..000000000
--- a/res/drawable-hdpi/quickactions_arrowup_middle_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/quickactions_arrowup_right_holo_light.9.png b/res/drawable-hdpi/quickactions_arrowup_right_holo_light.9.png
deleted file mode 100644
index d99058b02..000000000
--- a/res/drawable-hdpi/quickactions_arrowup_right_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-hdpi/quickcon_background_texture.png b/res/drawable-hdpi/quickcon_background_texture.png
new file mode 100644
index 000000000..60bb6cca7
--- /dev/null
+++ b/res/drawable-hdpi/quickcon_background_texture.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_fav_quickcontact_holo_dark.png b/res/drawable-mdpi/ic_fav_quickcontact_holo_dark.png
new file mode 100644
index 000000000..a089a6755
--- /dev/null
+++ b/res/drawable-mdpi/ic_fav_quickcontact_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/ic_text_holo_dark.png b/res/drawable-mdpi/ic_text_holo_dark.png
new file mode 100644
index 000000000..bbaa84f82
--- /dev/null
+++ b/res/drawable-mdpi/ic_text_holo_dark.png
Binary files differ
diff --git a/res/drawable-mdpi/quickactions_arrowdown_left_holo_light.9.png b/res/drawable-mdpi/quickactions_arrowdown_left_holo_light.9.png
deleted file mode 100644
index bd43850ae..000000000
--- a/res/drawable-mdpi/quickactions_arrowdown_left_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/quickactions_arrowdown_middle_holo_light.9.png b/res/drawable-mdpi/quickactions_arrowdown_middle_holo_light.9.png
deleted file mode 100644
index c284dbbf5..000000000
--- a/res/drawable-mdpi/quickactions_arrowdown_middle_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/quickactions_arrowdown_right_holo_light.9.png b/res/drawable-mdpi/quickactions_arrowdown_right_holo_light.9.png
deleted file mode 100644
index c057f71a5..000000000
--- a/res/drawable-mdpi/quickactions_arrowdown_right_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/quickactions_arrowup_left_holo_light.9.png b/res/drawable-mdpi/quickactions_arrowup_left_holo_light.9.png
deleted file mode 100644
index 85d092fe7..000000000
--- a/res/drawable-mdpi/quickactions_arrowup_left_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/quickactions_arrowup_middle_holo_light.9.png b/res/drawable-mdpi/quickactions_arrowup_middle_holo_light.9.png
deleted file mode 100644
index 828b7185c..000000000
--- a/res/drawable-mdpi/quickactions_arrowup_middle_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/quickactions_arrowup_right_holo_light.9.png b/res/drawable-mdpi/quickactions_arrowup_right_holo_light.9.png
deleted file mode 100644
index e4994b4cc..000000000
--- a/res/drawable-mdpi/quickactions_arrowup_right_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/quickcon_background_texture.png b/res/drawable-mdpi/quickcon_background_texture.png
new file mode 100644
index 000000000..86e1635e3
--- /dev/null
+++ b/res/drawable-mdpi/quickcon_background_texture.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_fav_quickcontact_holo_dark.png b/res/drawable-xhdpi/ic_fav_quickcontact_holo_dark.png
new file mode 100644
index 000000000..0384abcd8
--- /dev/null
+++ b/res/drawable-xhdpi/ic_fav_quickcontact_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/ic_text_holo_dark.png b/res/drawable-xhdpi/ic_text_holo_dark.png
new file mode 100644
index 000000000..8c697d979
--- /dev/null
+++ b/res/drawable-xhdpi/ic_text_holo_dark.png
Binary files differ
diff --git a/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png b/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png
deleted file mode 100644
index 12e2988db..000000000
--- a/res/drawable-xhdpi/quickactions_arrowdown_left_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/quickactions_arrowdown_middle_holo_light.9.png b/res/drawable-xhdpi/quickactions_arrowdown_middle_holo_light.9.png
deleted file mode 100644
index bff78a49d..000000000
--- a/res/drawable-xhdpi/quickactions_arrowdown_middle_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png b/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png
deleted file mode 100644
index 1ef71917c..000000000
--- a/res/drawable-xhdpi/quickactions_arrowdown_right_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png b/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png
deleted file mode 100644
index cf280d959..000000000
--- a/res/drawable-xhdpi/quickactions_arrowup_left_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/quickactions_arrowup_middle_holo_light.9.png b/res/drawable-xhdpi/quickactions_arrowup_middle_holo_light.9.png
deleted file mode 100644
index b5d9a0d4a..000000000
--- a/res/drawable-xhdpi/quickactions_arrowup_middle_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png b/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png
deleted file mode 100644
index 6c6a99c23..000000000
--- a/res/drawable-xhdpi/quickactions_arrowup_right_holo_light.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/quickcon_background_texture.png b/res/drawable-xhdpi/quickcon_background_texture.png
new file mode 100644
index 000000000..9134f93a8
--- /dev/null
+++ b/res/drawable-xhdpi/quickcon_background_texture.png
Binary files differ
diff --git a/res/drawable/quickactions_arrow_middle_holo_light.xml b/res/drawable/quickactions_arrow_middle_holo_light.xml
deleted file mode 100644
index f88b513f3..000000000
--- a/res/drawable/quickactions_arrow_middle_holo_light.xml
+++ /dev/null
@@ -1,21 +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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_first="true" android:drawable="@drawable/quickactions_arrowdown_middle_holo_light" />
- <item android:state_last="true" android:drawable="@drawable/quickactions_arrowup_middle_holo_light" />
- <!-- TODO: provide callout-less state -->
- <item android:drawable="@drawable/quickactions_arrowup_middle_holo_light" />
-</selector>
diff --git a/res/drawable/quickactions_arrow_right_holo_light.xml b/res/drawable/quickactions_arrow_right_holo_light.xml
deleted file mode 100644
index 3e309fe28..000000000
--- a/res/drawable/quickactions_arrow_right_holo_light.xml
+++ /dev/null
@@ -1,21 +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.
--->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_first="true" android:drawable="@drawable/quickactions_arrowdown_right_holo_light" />
- <item android:state_last="true" android:drawable="@drawable/quickactions_arrowup_right_holo_light" />
- <!-- TODO: provide callout-less state -->
- <item android:drawable="@drawable/quickactions_arrowup_right_holo_light" />
-</selector>
diff --git a/res/drawable/quickactions_arrow_left_holo_light.xml b/res/drawable/quickcontact_list_item_background.xml
index c1e18bd1d..e6d773e37 100644
--- a/res/drawable/quickactions_arrow_left_holo_light.xml
+++ b/res/drawable/quickcontact_list_item_background.xml
@@ -13,9 +13,23 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
+
+<!-- TODO These all have to be refined -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_first="true" android:drawable="@drawable/quickactions_arrowdown_left_holo_light" />
- <item android:state_last="true" android:drawable="@drawable/quickactions_arrowup_left_holo_light" />
- <!-- TODO: provide callout-less state -->
- <item android:drawable="@drawable/quickactions_arrowup_left_holo_light" />
+ <item
+ android:state_window_focused="false"
+ android:drawable="@drawable/list_background_holo" />
+ <item
+ android:state_focused="true"
+ android:state_pressed="true"
+ android:drawable="@drawable/list_pressed_holo" />
+ <item
+ android:state_focused="false"
+ android:state_pressed="true"
+ android:drawable="@drawable/list_pressed_holo" />
+ <item
+ android:state_focused="true"
+ android:drawable="@drawable/list_focused_holo" />
+ <item
+ android:drawable="@color/people_app_theme_color" />
</selector>
diff --git a/res/drawable/quickcontact_slider_btn.xml b/res/drawable/quickcontact_slider_btn.xml
deleted file mode 100644
index b3d0ec7d7..000000000
--- a/res/drawable/quickcontact_slider_btn.xml
+++ /dev/null
@@ -1,30 +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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android"
- android:dither="true">
- <!-- TODO Still a hack. This needs a default from the framework instead for the checked state -->
- <item android:state_checked="true"
- android:drawable="@drawable/quickactions_icon_activated" />
- <item android:state_window_focused="false"
- android:drawable="@android:color/transparent" />
- <item android:state_pressed="true"
- android:drawable="@drawable/quickactions_icon_activated" />
- <item android:state_focused="true"
- android:drawable="@drawable/quickactions_icon_activated" />
- <item
- android:drawable="@android:color/transparent" />
-</selector>
diff --git a/res/layout/quickcontact_header_small.xml b/res/drawable/quickcontact_track_background.xml
index f3a46d5fc..fcf61fd38 100644
--- a/res/layout/quickcontact_header_small.xml
+++ b/res/drawable/quickcontact_track_background.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!-- 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.
@@ -14,9 +14,6 @@
limitations under the License.
-->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/header_small"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" />
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+ android:src="@drawable/quickcon_background_texture"
+ android:tileMode="repeat" />
diff --git a/res/layout-sw580dp/quickcontact_activity.xml b/res/layout-sw580dp/quickcontact_activity.xml
new file mode 100644
index 000000000..6b381a997
--- /dev/null
+++ b/res/layout-sw580dp/quickcontact_activity.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+<view
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.android.contacts.quickcontact.FloatingChildLayout"
+ android:id="@+id/floating_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:descendantFocusability="afterDescendants">
+ <LinearLayout
+ android:id="@android:id/content"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+ <include layout="@layout/quickcontact_photo_container" />
+ <View
+ android:id="@+id/line_before_track"
+ android:layout_width="match_parent"
+ android:layout_height="2dip"
+ android:background="@color/quickcontact_list_background" />
+ <include layout="@layout/quickcontact_track" />
+ <android.support.v4.view.ViewPager
+ android:id="@+id/item_list_pager"
+ android:layout_width="match_parent"
+ android:layout_height="180dip" />
+ </LinearLayout>
+</view>
diff --git a/res/layout-w470dp/quickcontact_activity.xml b/res/layout-w470dp/quickcontact_activity.xml
new file mode 100644
index 000000000..df68761f8
--- /dev/null
+++ b/res/layout-w470dp/quickcontact_activity.xml
@@ -0,0 +1,44 @@
+<?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.
+-->
+<view
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ class="com.android.contacts.quickcontact.FloatingChildLayout"
+ android:id="@+id/floating_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:focusable="true"
+ android:focusableInTouchMode="true"
+ android:descendantFocusability="afterDescendants">
+ <LinearLayout
+ android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/quick_contact_picture_height"
+ android:padding="32dip"
+ android:orientation="horizontal">
+ <include layout="@layout/quickcontact_photo_container" />
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/quick_contact_picture_height"
+ android:orientation="vertical">
+ <include layout="@layout/quickcontact_track" />
+ <android.support.v4.view.ViewPager
+ android:id="@+id/item_list_pager"
+ android:background="@color/quickcontact_list_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ </LinearLayout>
+ </LinearLayout>
+</view>
diff --git a/res/layout/quickcontact.xml b/res/layout/quickcontact.xml
deleted file mode 100644
index e2b291c8f..000000000
--- a/res/layout/quickcontact.xml
+++ /dev/null
@@ -1,136 +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:id="@android:id/content"
- android:layout_width="@dimen/quick_contact_width"
- android:layout_height="wrap_content"
- android:visibility="invisible"
- android:orientation="vertical">
-
- <FrameLayout
- android:id="@+id/header"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="10dip">
-
- <ViewStub
- android:id="@+id/header_small"
- android:inflatedId="@+id/header_small"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout="@layout/quickcontact_header_small" />
-
- <ViewStub
- android:id="@+id/header_medium"
- android:inflatedId="@+id/header_medium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout="@layout/quickcontact_header_med" />
-
- <ViewStub
- android:id="@+id/header_large"
- android:inflatedId="@+id/header_large"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout="@layout/quickcontact_header_large" />
-
- </FrameLayout>
-
- <HorizontalScrollView
- android:id="@+id/scroll"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="5dip"
- android:layout_marginLeft="15dip"
- android:layout_marginRight="15dip"
- android:layout_marginBottom="10dip"
- android:fadingEdgeLength="0dip"
- android:scrollbars="none">
-
- <LinearLayout
- android:id="@+id/quickcontact"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="horizontal" />
- </HorizontalScrollView>
-
- <FrameLayout
- android:id="@+id/footer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone">
- <LinearLayout
- android:id="@+id/footer_disambig"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:visibility="gone">
-
- <ListView
- android:id="@android:id/list"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:layout_marginLeft="5dip"
- android:layout_marginRight="5dip"
- android:cacheColorHint="@null" />
-
- <CheckBox
- android:id="@android:id/checkbox"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="19dip"
- android:layout_marginRight="19dip"
- android:minHeight="60dip"
- android:textColor="#f000"
- android:textStyle="bold"
- android:text="@string/quickcontact_remember_choice"
- android:textAppearance="?android:attr/textAppearanceSmallInverse" />
-
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/footer_clear_defaults"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:visibility="gone">
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="30dip"
- android:layout_marginRight="5dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:text="@string/quickcontact_clear_defaults_caption" />
- <ListView
- android:id="@+id/defaults_list"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:layout_marginLeft="5dip"
- android:layout_marginRight="5dip"
- android:cacheColorHint="@null" />
- <Button
- android:id="@+id/clear_defaults_button"
- android:layout_marginLeft="20dip"
- android:layout_marginBottom="20dip"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/quickcontact_clear_defaults_button" />
- </LinearLayout>
- </FrameLayout>
-</LinearLayout>
diff --git a/res/layout/quickcontact_activity.xml b/res/layout/quickcontact_activity.xml
index aced4a8eb..7aa2aa4a9 100644
--- a/res/layout/quickcontact_activity.xml
+++ b/res/layout/quickcontact_activity.xml
@@ -22,7 +22,23 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:descendantFocusability="afterDescendants">
-
- <include layout="@layout/quickcontact" />
-
+ <LinearLayout
+ android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="15dip"
+ android:paddingRight="15dip"
+ android:orientation="vertical">
+ <include layout="@layout/quickcontact_photo_container" />
+ <View
+ android:id="@+id/line_before_track"
+ android:layout_width="match_parent"
+ android:layout_height="2dip"
+ android:background="@color/quickcontact_list_background" />
+ <include layout="@layout/quickcontact_track" />
+ <android.support.v4.view.ViewPager
+ android:id="@+id/item_list_pager"
+ android:layout_width="match_parent"
+ android:layout_height="180dip" />
+ </LinearLayout>
</view>
diff --git a/res/layout/quickcontact_default_item.xml b/res/layout/quickcontact_default_item.xml
deleted file mode 100755
index 3a918f0f9..000000000
--- a/res/layout/quickcontact_default_item.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 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="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="25dip"
- android:paddingRight="25dip"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:gravity="center_vertical">
-
- <TextView
- android:id="@android:id/text1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textStyle="bold"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@android:id/text2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="-4dip"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
-</LinearLayout>
diff --git a/res/layout/quickcontact_header_large.xml b/res/layout/quickcontact_header_large.xml
deleted file mode 100644
index b8a19cf3a..000000000
--- a/res/layout/quickcontact_header_large.xml
+++ /dev/null
@@ -1,79 +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:id="@+id/header_large"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="87dip"
- android:gravity="center_vertical"
- android:orientation="horizontal">
-
- <ImageView
- android:id="@+id/photo"
- android:layout_width="64dip"
- android:layout_height="64dip"
- android:layout_marginLeft="15dip" />
-
- <LinearLayout
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginLeft="15dip"
- android:paddingRight="8dip"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="end"
- android:textColor="@*android:color/primary_text_light"
- android:textStyle="bold"
- android:textSize="18dip" />
-
- <TextView
- android:id="@+id/status"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="end"
- android:textColor="@*android:color/secondary_text_light"
- android:textSize="15dip"
- android:layout_marginTop="-3dip" />
-
- <TextView
- android:id="@+id/timestamp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="end"
- android:textColor="@*android:color/secondary_text_light"
- android:textSize="12dip"
- android:layout_marginTop="-2dip" />
-
- </LinearLayout>
-
- <ImageView
- android:id="@+id/presence"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginRight="15dip"
- android:scaleType="centerInside" />
-
-</LinearLayout>
diff --git a/res/layout/quickcontact_header_med.xml b/res/layout/quickcontact_header_med.xml
deleted file mode 100644
index 77cb1a5b0..000000000
--- a/res/layout/quickcontact_header_med.xml
+++ /dev/null
@@ -1,55 +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:id="@+id/header_medium"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:minHeight="51dip"
- android:gravity="center_vertical"
- android:orientation="horizontal">
-
- <LinearLayout
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginLeft="15dip"
- android:layout_marginRight="15dip"
- android:orientation="vertical">
-
- <TextView
- android:id="@+id/status"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="end"
- android:textColor="@*android:color/primary_text_light"
- android:textSize="15sp" />
-
- <TextView
- android:id="@+id/timestamp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="end"
- android:textColor="@*android:color/secondary_text_light"
- android:textSize="12sp"
- android:layout_marginTop="-2dip" />
-
- </LinearLayout>
-
-</LinearLayout>
diff --git a/res/layout-finger/quickcontact_item_nodata.xml b/res/layout/quickcontact_list_fragment.xml
index 5f951e2fd..8c62c4c77 100644..100755
--- a/res/layout-finger/quickcontact_item_nodata.xml
+++ b/res/layout/quickcontact_list_fragment.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 The Android Open Source Project
+<!-- 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.
@@ -14,15 +14,22 @@
limitations under the License.
-->
-<TextView
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingLeft="12dip"
- android:paddingRight="12dip"
- android:scaleType="centerInside"
- android:focusable="false"
- android:clickable="false"
- android:gravity="center_vertical"
- android:textColor="@android:color/black"
- android:text="@string/quickcontact_no_data" />
+ android:layout_height="wrap_content">
+ <!-- Line that looks like a list divider -->
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="1dip"
+ android:background="@color/quickcontact_list_divider" />
+ <ListView
+ android:id="@+id/list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:divider="@color/quickcontact_list_divider"
+ android:dividerHeight="1dip"
+ android:background="@color/quickcontact_list_background"
+ android:cacheColorHint="@null" />
+</LinearLayout>
diff --git a/res/layout/quickcontact_list_item.xml b/res/layout/quickcontact_list_item.xml
new file mode 100755
index 000000000..f77ed3fc8
--- /dev/null
+++ b/res/layout/quickcontact_list_item.xml
@@ -0,0 +1,60 @@
+<?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.
+-->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:background="@drawable/quickcontact_list_item_background"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:gravity="center_vertical">
+ <LinearLayout
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingLeft="16dip"
+ android:paddingRight="16dip"
+ android:gravity="center_vertical">
+ <TextView
+ android:id="@android:id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@android:color/white"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+ <TextView
+ android:id="@android:id/text2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@android:color/white"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
+ <View
+ android:id="@+id/vertical_divider"
+ android:layout_width="1dip"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:background="@drawable/ic_divider_dashed_holo_dark" />
+ <ImageView
+ android:id="@+id/secondary_action_button"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/detail_item_icon_margin"
+ android:paddingRight="@dimen/detail_item_icon_margin"
+ android:background="@drawable/quickcontact_list_item_background"
+ android:duplicateParentState="false" />
+</LinearLayout>
diff --git a/res/layout/quickcontact_photo_container.xml b/res/layout/quickcontact_photo_container.xml
new file mode 100644
index 000000000..3e0c935a7
--- /dev/null
+++ b/res/layout/quickcontact_photo_container.xml
@@ -0,0 +1,90 @@
+<?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.
+-->
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <RelativeLayout
+ android:id="@+id/photo_container"
+ android:layout_width="@dimen/quick_contact_picture_width"
+ android:layout_height="@dimen/quick_contact_picture_height"
+ android:gravity="center_vertical">
+ <ImageView
+ android:id="@+id/photo"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:scaleType="centerCrop" />
+ <View
+ android:id="@+id/photo_text_bar"
+ android:layout_width="0dip"
+ android:layout_height="42dip"
+ android:layout_alignBottom="@id/photo"
+ android:layout_alignLeft="@id/photo"
+ android:layout_alignRight="@id/photo"
+ android:alpha="0.5"
+ android:background="@android:color/black" />
+ <ImageButton
+ android:id="@+id/open_details_button"
+ android:src="@drawable/ic_fav_quickcontact_holo_dark"
+ android:background="?android:attr/selectableItemBackground"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginRight="16dip"
+ android:layout_marginBottom="5dip"
+ android:layout_alignBottom="@id/photo_text_bar"
+ android:layout_alignRight="@id/photo_text_bar" />
+ <TextView
+ android:id="@+id/name"
+ android:layout_width="wrap_content"
+ android:layout_height="42dip"
+ android:layout_alignBottom="@id/photo"
+ android:layout_alignLeft="@id/photo"
+ android:layout_toLeftOf="@id/open_details_button"
+ android:gravity="center_vertical"
+ android:paddingLeft="8dip"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@android:color/white"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+ <TextView
+ android:id="@+id/status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@*android:color/secondary_text_light"
+ android:textSize="15dip"
+ android:layout_marginTop="-3dip" />
+ <TextView
+ android:id="@+id/timestamp"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:textColor="@*android:color/secondary_text_light"
+ android:textSize="12dip"
+ android:layout_marginTop="-2dip" />
+ <ImageView
+ android:id="@+id/presence"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="15dip"
+ android:scaleType="centerInside" />
+ <ImageButton
+ android:id="@+id/open_details_push_layer"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="?android:attr/selectableItemBackground" />
+ </RelativeLayout>
+</merge>
diff --git a/res/layout/quickcontact_resolve_item.xml b/res/layout/quickcontact_resolve_item.xml
deleted file mode 100755
index 280572208..000000000
--- a/res/layout/quickcontact_resolve_item.xml
+++ /dev/null
@@ -1,40 +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="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="25dip"
- android:paddingRight="25dip"
- android:minHeight="?android:attr/listPreferredItemHeight"
- android:gravity="center_vertical">
-
- <TextView
- android:id="@android:id/text1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textStyle="bold"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@android:id/text2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="-4dip"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
-</LinearLayout>
diff --git a/res/layout/quickcontact_track.xml b/res/layout/quickcontact_track.xml
new file mode 100644
index 000000000..817717491
--- /dev/null
+++ b/res/layout/quickcontact_track.xml
@@ -0,0 +1,42 @@
+<?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.
+-->
+<merge
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <HorizontalScrollView
+ android:id="@+id/track_scroller"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:fadingEdgeLength="0dip"
+ android:background="@drawable/quickcontact_track_background"
+ android:scrollbars="none">
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <LinearLayout
+ android:id="@+id/track"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" />
+ <View
+ android:id="@+id/selected_tab_rectangle"
+ android:layout_width="60dip"
+ android:layout_height="8dip"
+ android:layout_alignBottom="@id/track"
+ android:layout_alignParentLeft="true"
+ android:background="@color/quickcontact_list_background" />
+ </RelativeLayout>
+ </HorizontalScrollView>
+</merge>
diff --git a/res/layout/quickcontact_item.xml b/res/layout/quickcontact_track_button.xml
index ca57d667a..f1353f25e 100644
--- a/res/layout/quickcontact_item.xml
+++ b/res/layout/quickcontact_track_button.xml
@@ -4,9 +4,9 @@
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.
@@ -16,8 +16,8 @@
<com.android.contacts.quickcontact.CheckableImageView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="59dip"
- android:layout_height="51dip"
+ android:layout_width="60dip"
+ android:layout_height="60dip"
android:paddingLeft="12dip"
android:paddingRight="12dip"
android:paddingTop="8dip"
@@ -25,4 +25,4 @@
android:scaleType="centerInside"
android:focusable="true"
android:clickable="true"
- android:background="@drawable/quickcontact_slider_btn" />
+ android:background="?android:attr/selectableItemBackground" />
diff --git a/res/values-sw580dp-w1000dp/dimens.xml b/res/values-sw580dp-w1000dp/dimens.xml
index ac30b762e..7ff902645 100644
--- a/res/values-sw580dp-w1000dp/dimens.xml
+++ b/res/values-sw580dp-w1000dp/dimens.xml
@@ -14,7 +14,6 @@
limitations under the License.
-->
<resources>
- <dimen name="quick_contact_width">452dip</dimen>
<dimen name="action_bar_filter_min_width">220dip</dimen>
<dimen name="action_bar_filter_max_width">300dip</dimen>
<dimen name="action_bar_search_max_width">336dip</dimen>
diff --git a/res/values-sw580dp/dimens.xml b/res/values-sw580dp/dimens.xml
index 9fbdc8e17..60da57a1c 100644
--- a/res/values-sw580dp/dimens.xml
+++ b/res/values-sw580dp/dimens.xml
@@ -23,7 +23,6 @@
<dimen name="editor_field_top_padding">12dip</dimen>
<dimen name="editor_field_bottom_padding">12dip</dimen>
<dimen name="detail_item_side_margin">19dip</dimen>
- <dimen name="quick_contact_width">356dip</dimen>
<dimen name="contact_name_text_size">26sp</dimen>
<dimen name="action_bar_filter_min_width">120dip</dimen>
<dimen name="action_bar_filter_max_width">120dip</dimen>
@@ -37,4 +36,7 @@
<dimen name="search_view_width">400dip</dimen>
<dimen name="contact_browser_list_left_margin">0dip</dimen>
<dimen name="contacts_count_right_margin">24dip</dimen>
+ <dimen name="quick_contact_top_position">-1px</dimen>
+ <dimen name="quick_contact_picture_width">400dip</dimen>
+ <dimen name="quick_contact_picture_height">200dip</dimen>
</resources>
diff --git a/res/values-w470dp/dimens.xml b/res/values-w470dp/dimens.xml
index ba7f3f85d..c77d8c25e 100644
--- a/res/values-w470dp/dimens.xml
+++ b/res/values-w470dp/dimens.xml
@@ -15,4 +15,7 @@
-->
<resources>
<dimen name="detail_tab_carousel_height">0dip</dimen>
+ <dimen name="quick_contact_top_position">-1px</dimen>
+ <dimen name="quick_contact_picture_width">174dip</dimen>
+ <dimen name="quick_contact_picture_height">-1px</dimen>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 579bf84fd..325d2e797 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -17,8 +17,8 @@
<color name="textColorIconOverlay">#fff</color>
<color name="textColorIconOverlayShadow">#000</color>
- <color name="quickcontact_disambig">#f2f2f2</color>
- <color name="quickcontact_disambig_divider">#afafaf</color>
+ <color name="quickcontact_list_divider">#ff48bde8</color>
+ <color name="quickcontact_list_background">#ff33b5e6</color>
<color name="edit_divider">#ff666666</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 2b71c849e..45aa75e36 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -30,10 +30,17 @@
<dimen name="photo_action_popup_width">400dip</dimen>
- <!-- Width of the quick contact popup. This size is chosen so that the last icon is clipped
- to indicate horizontal scrollability. Also, this size is the same as the widget to make them
- aligned -->
- <dimen name="quick_contact_width">352dip</dimen>
+ <!-- Top position of quick contact. If this is -1, the vertical position is determined
+ based on the source of the request -->
+ <dimen name="quick_contact_top_position">48dip</dimen>
+
+ <!-- Width of the picture in the QuickContact popup. This can be -1 for the full width
+ of the parent -->
+ <dimen name="quick_contact_picture_width">-1px</dimen>
+
+ <!-- Height of the picture in the QuickContact popup. This can be -1 for the full height
+ of the parent -->
+ <dimen name="quick_contact_picture_height">174dip</dimen>
<!-- Padding of the rounded plus/minus/expand/collapse buttons in the editor -->
<dimen name="editor_round_button_padding_left">2dip</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0fbc6bf20..20326ef03 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1015,32 +1015,13 @@
<!-- Message next to disamgiguation dialog check box -->
<string name="make_primary">Remember this choice</string>
- <!-- Shown as a toast when the user taps on a Fast-Track icon, and no application
+ <!-- Shown as a toast when the user taps on a QuickContact icon, and no application
was found that could perform the selected action -->
<string name="quickcontact_missing_app">No application found to handle this action</string>
- <!-- Shown as the checkbox label that, when checked, will store remember the
- selected choice and shortcut to it in the future. For example, this would
- make a selected phone number the default. -->
- <string name="quickcontact_remember_choice">Remember this choice</string>
-
<!-- Shown as the header name for a person when the name is missing or unknown. -->
<string name="quickcontact_missing_name">Unknown</string>
- <!-- Text that is shown in the Badge, when there is no data to display -->
- <string name="quickcontact_no_data">No data</string>
-
- <!-- Accessibility description for the button in QuickContacts that allows the user to clear
- defaults of a contact (like primary email). [CHAR LIMIT=100] -->
- <string name="quickcontact_clear_defaults_description">Clear defaults</string>
-
- <!-- Caption that shows above the list of defaults (like primary email). [CHAR LIMIT=40] -->
- <string name="quickcontact_clear_defaults_caption">Defaults set for this contact:</string>
-
- <!-- Button caption that allows the user to clear the defaults (like primary email) of one
- contact. [CHAR LIMIT=15] -->
- <string name="quickcontact_clear_defaults_button">Clear</string>
-
<!-- The menu item to open the list of accounts -->
<string name="menu_accounts">Accounts</string>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index f32ae4cc6..b58706e03 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -97,7 +97,7 @@
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowAnimationStyle">@null</item>
<item name="android:windowIsFloating">false</item>
- <item name="android:backgroundDimEnabled">false</item>
+ <item name="android:backgroundDimEnabled">true</item>
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
</style>
diff --git a/src/com/android/contacts/TypePrecedence.java b/src/com/android/contacts/TypePrecedence.java
index e89c5aa36..92f3a6e32 100644
--- a/src/com/android/contacts/TypePrecedence.java
+++ b/src/com/android/contacts/TypePrecedence.java
@@ -100,8 +100,6 @@ public final class TypePrecedence {
private static int[] getTypePrecedenceList(String mimetype) {
if (mimetype.equals(Phone.CONTENT_ITEM_TYPE)) {
return TYPE_PRECEDENCE_PHONES;
- } else if (mimetype.equals(Constants.MIME_TYPE_SMS_ADDRESS)) {
- return TYPE_PRECEDENCE_PHONES;
} else if (mimetype.equals(Email.CONTENT_ITEM_TYPE)) {
return TYPE_PRECEDENCE_EMAIL;
} else if (mimetype.equals(StructuredPostal.CONTENT_ITEM_TYPE)) {
diff --git a/src/com/android/contacts/list/ContactTileAdapter.java b/src/com/android/contacts/list/ContactTileAdapter.java
index 6150670b7..7691587ca 100644
--- a/src/com/android/contacts/list/ContactTileAdapter.java
+++ b/src/com/android/contacts/list/ContactTileAdapter.java
@@ -289,11 +289,9 @@ public class ContactTileAdapter extends BaseAdapter {
@Override
public long getItemId(int position) {
- /*
- * As we show several selectable items for each ListView row,
- * we can not determine a stable id. But as we don't rely on ListView's selection,
- * this should not be a problem.
- */
+ // As we show several selectable items for each ListView row,
+ // we can not determine a stable id. But as we don't rely on ListView's selection,
+ // this should not be a problem.
return position;
}
diff --git a/src/com/android/contacts/model/BaseAccountType.java b/src/com/android/contacts/model/BaseAccountType.java
index 06cb0395e..c627c8017 100644
--- a/src/com/android/contacts/model/BaseAccountType.java
+++ b/src/com/android/contacts/model/BaseAccountType.java
@@ -205,6 +205,7 @@ public class BaseAccountType extends AccountType {
android.R.drawable.sym_action_call, 10, true,
R.layout.text_fields_editor_view, android.R.style.TextAppearance_Medium));
kind.iconAltRes = R.drawable.sym_action_sms;
+ kind.iconAltResDark = R.drawable.ic_text_holo_dark;
kind.actionHeader = new PhoneActionInflater();
kind.actionAltHeader = new PhoneActionAltInflater();
kind.actionBody = new SimpleInflater(Phone.NUMBER);
diff --git a/src/com/android/contacts/model/DataKind.java b/src/com/android/contacts/model/DataKind.java
index 40f6f99d1..a3b31e3b3 100644
--- a/src/com/android/contacts/model/DataKind.java
+++ b/src/com/android/contacts/model/DataKind.java
@@ -27,7 +27,10 @@ public class DataKind {
public String mimeType;
public int titleRes;
public int iconRes;
+ /** Icon used for secondary action when shown on top of a bright background */
public int iconAltRes;
+ /** Icon used for secondary action when shown on top of a dark background */
+ public int iconAltResDark;
public int weight;
public boolean editable;
diff --git a/src/com/android/contacts/quickcontact/Action.java b/src/com/android/contacts/quickcontact/Action.java
index bdfbe487c..f6e282c66 100644
--- a/src/com/android/contacts/quickcontact/Action.java
+++ b/src/com/android/contacts/quickcontact/Action.java
@@ -27,20 +27,21 @@ import android.net.Uri;
* string description and icon.
*/
public interface Action extends Collapser.Collapsible<Action> {
- public CharSequence getHeader();
public CharSequence getBody();
+ public CharSequence getSubtitle();
public String getMimeType();
- public Drawable getFallbackIcon();
- /**
- * Build an {@link Intent} that will perform this action.
- */
+ /** Returns an icon that can be clicked for the alternate action. */
+ public Drawable getAlternateIcon();
+
+ /** Build an {@link Intent} that will perform this action. */
public Intent getIntent();
- /**
- * Checks if the contact data for this action is primary.
- */
+ /** Build an {@link Intent} that will perform the alternate action. */
+ public Intent getAlternateIntent();
+
+ /** Checks if the contact data for this action is primary. */
public Boolean isPrimary();
/**
diff --git a/src/com/android/contacts/quickcontact/ClearDefaultsAction.java b/src/com/android/contacts/quickcontact/ClearDefaultsAction.java
deleted file mode 100644
index d1acc6b66..000000000
--- a/src/com/android/contacts/quickcontact/ClearDefaultsAction.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2010 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.quickcontact;
-
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-
-/**
- * Action that expands to show and allow clearing the currently selected defaults.
- */
-public class ClearDefaultsAction implements Action {
- /**
- * This is a pseudo-mimetype that is only needed for the action list. It has to be
- * different from the real mime-types used
- */
- public static final String PSEUDO_MIME_TYPE = "__clear_defaults_mime_type";
-
- @Override
- public boolean collapseWith(Action t) {
- return false;
- }
-
- @Override
- public boolean shouldCollapseWith(Action t) {
- return false;
- }
-
- @Override
- public CharSequence getHeader() {
- return null;
- }
-
- @Override
- public CharSequence getBody() {
- return null;
- }
-
- @Override
- public String getMimeType() {
- return PSEUDO_MIME_TYPE;
- }
-
- @Override
- public Drawable getFallbackIcon() {
- return null;
- }
-
- @Override
- public Intent getIntent() {
- return null;
- }
-
- @Override
- public Boolean isPrimary() {
- return null;
- }
-
- @Override
- public Uri getDataUri() {
- return null;
- }
-
- @Override
- public long getDataId() {
- return -1;
- }
-}
diff --git a/src/com/android/contacts/quickcontact/DataAction.java b/src/com/android/contacts/quickcontact/DataAction.java
index 787d482c2..6f719af82 100644
--- a/src/com/android/contacts/quickcontact/DataAction.java
+++ b/src/com/android/contacts/quickcontact/DataAction.java
@@ -3,6 +3,7 @@ package com.android.contacts.quickcontact;
import com.android.contacts.ContactsUtils;
import com.android.contacts.R;
import com.android.contacts.model.DataKind;
+import com.android.contacts.model.AccountType.EditType;
import com.android.contacts.util.Constants;
import com.android.contacts.util.PhoneCapabilityTester;
@@ -34,11 +35,12 @@ public class DataAction implements Action {
private final DataKind mKind;
private final String mMimeType;
- private CharSequence mHeader;
private CharSequence mBody;
+ private CharSequence mSubtitle;
private Intent mIntent;
+ private Intent mAlternateIntent;
+ private int mAlternateIconRes;
- private boolean mAlternate;
private Uri mDataUri;
private long mDataId;
private boolean mIsPrimary;
@@ -46,18 +48,33 @@ public class DataAction implements Action {
/**
* Create an action from common {@link Data} elements.
*/
- public DataAction(Context context, String mimeType, DataKind kind,
- long dataId, Cursor cursor) {
+ public DataAction(Context context, String mimeType, DataKind kind, long dataId, Cursor cursor) {
mContext = context;
mKind = kind;
mMimeType = mimeType;
- // Inflate strings from cursor
- mAlternate = Constants.MIME_TYPE_SMS_ADDRESS.equals(mimeType);
- if (mAlternate && mKind.actionAltHeader != null) {
- mHeader = mKind.actionAltHeader.inflateUsing(context, cursor);
- } else if (mKind.actionHeader != null) {
- mHeader = mKind.actionHeader.inflateUsing(context, cursor);
+ // Determine type for subtitle
+ mSubtitle = "";
+ if (kind.typeColumn != null) {
+ final int typeColumnIndex = cursor.getColumnIndex(kind.typeColumn);
+ if (typeColumnIndex != -1) {
+ final int typeValue = cursor.getInt(typeColumnIndex);
+
+ // get type string
+ for (EditType type : kind.typeList) {
+ if (type.rawValue == typeValue) {
+ if (type.customColumn == null) {
+ // Non-custom type. Get its description from the resource
+ mSubtitle = context.getString(type.labelRes);
+ } else {
+ // Custom type. Read it from the database
+ mSubtitle = cursor.getString(cursor.getColumnIndexOrThrow(
+ type.customColumn));
+ }
+ break;
+ }
+ }
+ }
}
if (getAsInt(cursor, Data.IS_SUPER_PRIMARY) != 0) {
@@ -71,13 +88,30 @@ public class DataAction implements Action {
mDataId = dataId;
mDataUri = ContentUris.withAppendedId(Data.CONTENT_URI, dataId);
+ final boolean hasPhone = PhoneCapabilityTester.isPhone(mContext);
+ final boolean hasSms = PhoneCapabilityTester.isSmsIntentRegistered(mContext);
+
// Handle well-known MIME-types with special care
if (Phone.CONTENT_ITEM_TYPE.equals(mimeType)) {
if (PhoneCapabilityTester.isPhone(mContext)) {
final String number = getAsString(cursor, Phone.NUMBER);
if (!TextUtils.isEmpty(number)) {
- final Uri callUri = Uri.fromParts(Constants.SCHEME_TEL, number, null);
- mIntent = new Intent(Intent.ACTION_CALL_PRIVILEGED, callUri);
+
+ final Intent phoneIntent = hasPhone ? new Intent(Intent.ACTION_CALL_PRIVILEGED,
+ Uri.fromParts(Constants.SCHEME_TEL, number, null)) : null;
+ final Intent smsIntent = hasSms ? new Intent(Intent.ACTION_SENDTO,
+ Uri.fromParts(Constants.SCHEME_SMSTO, number, null)) : null;
+
+ // Configure Icons and Intents. Notice actionIcon is already set to the phone
+ if (hasPhone && hasSms) {
+ mIntent = phoneIntent;
+ mAlternateIntent = smsIntent;
+ mAlternateIconRes = kind.iconAltResDark;
+ } else if (hasPhone) {
+ mIntent = phoneIntent;
+ } else if (hasSms) {
+ mIntent = smsIntent;
+ }
}
}
} else if (SipAddress.CONTENT_ITEM_TYPE.equals(mimeType)) {
@@ -94,14 +128,6 @@ public class DataAction implements Action {
// for the SIP-related intent-filters in its manifest.
}
}
- } else if (Constants.MIME_TYPE_SMS_ADDRESS.equals(mimeType)) {
- if (PhoneCapabilityTester.isSmsIntentRegistered(mContext)) {
- final String number = getAsString(cursor, Phone.NUMBER);
- if (!TextUtils.isEmpty(number)) {
- final Uri smsUri = Uri.fromParts(Constants.SCHEME_SMSTO, number, null);
- mIntent = new Intent(Intent.ACTION_SENDTO, smsUri);
- }
- }
} else if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
final String address = getAsString(cursor, Email.DATA);
if (!TextUtils.isEmpty(address)) {
@@ -127,7 +153,7 @@ public class DataAction implements Action {
if (isEmail) {
// Use Google Talk string when using Email, and clear data
// Uri so we don't try saving Email as primary.
- mHeader = context.getText(R.string.chat_gtalk);
+ mSubtitle = context.getText(R.string.chat_gtalk);
mDataUri = null;
}
@@ -189,66 +215,59 @@ public class DataAction implements Action {
return true;
}
- /** {@inheritDoc} */
@Override
- public CharSequence getHeader() {
- return mHeader;
+ public CharSequence getSubtitle() {
+ return mSubtitle;
}
- /** {@inheritDoc} */
@Override
public CharSequence getBody() {
return mBody;
}
- /** {@inheritDoc} */
@Override
public String getMimeType() {
return mMimeType;
}
- /** {@inheritDoc} */
@Override
public Uri getDataUri() {
return mDataUri;
}
- /** {@inheritDoc} */
@Override
public long getDataId() {
return mDataId;
}
- /** {@inheritDoc} */
@Override
public Boolean isPrimary() {
return mIsPrimary;
}
- /** {@inheritDoc} */
@Override
- public Drawable getFallbackIcon() {
- // Bail early if no valid resources
+ public Drawable getAlternateIcon() {
+ if (mAlternateIconRes == 0) return null;
+
final String resPackageName = mKind.resPackageName;
- if (resPackageName == null) return null;
+ if (resPackageName == null) {
+ return mContext.getResources().getDrawable(mAlternateIconRes);
+ }
final PackageManager pm = mContext.getPackageManager();
- if (mAlternate && mKind.iconAltRes != -1) {
- return pm.getDrawable(resPackageName, mKind.iconAltRes, null);
- } else if (mKind.iconRes != -1) {
- return pm.getDrawable(resPackageName, mKind.iconRes, null);
- } else {
- return null;
- }
+ return pm.getDrawable(resPackageName, mAlternateIconRes, null);
}
- /** {@inheritDoc} */
@Override
public Intent getIntent() {
return mIntent;
}
- /** {@inheritDoc} */
+ @Override
+ public Intent getAlternateIntent() {
+ return mAlternateIntent;
+ }
+
@Override
public boolean collapseWith(Action other) {
if (!shouldCollapseWith(other)) {
@@ -257,7 +276,6 @@ public class DataAction implements Action {
return true;
}
- /** {@inheritDoc} */
@Override
public boolean shouldCollapseWith(Action t) {
if (t == null) {
@@ -276,8 +294,7 @@ public class DataAction implements Action {
return false;
}
if (!TextUtils.equals(mMimeType, other.mMimeType)
- || !ContactsUtils.areIntentActionEqual(mIntent, other.mIntent)
- ) {
+ || !ContactsUtils.areIntentActionEqual(mIntent, other.mIntent)) {
return false;
}
return true;
diff --git a/src/com/android/contacts/quickcontact/FloatingChildLayout.java b/src/com/android/contacts/quickcontact/FloatingChildLayout.java
index ddba609f5..11d317672 100644
--- a/src/com/android/contacts/quickcontact/FloatingChildLayout.java
+++ b/src/com/android/contacts/quickcontact/FloatingChildLayout.java
@@ -18,15 +18,16 @@ package com.android.contacts.quickcontact;
import com.android.contacts.R;
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
-import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
-import android.view.animation.Animation;
-import android.view.animation.Animation.AnimationListener;
+import android.view.ViewPropertyAnimator;
import android.view.animation.AnimationUtils;
import android.widget.FrameLayout;
import android.widget.PopupWindow;
@@ -46,22 +47,28 @@ import android.widget.PopupWindow;
*/
public class FloatingChildLayout extends FrameLayout {
private static final String TAG = "FloatingChild";
+ private int mFixedTopPosition;
+ private View mChild;
+ private Rect mTargetScreen = new Rect();
+ private final int mAnimationDuration;
public FloatingChildLayout(Context context, AttributeSet attrs) {
super(context, attrs);
+ final Resources resources = getResources();
+ mFixedTopPosition =
+ resources.getDimensionPixelOffset(R.dimen.quick_contact_top_position);
+ mAnimationDuration = resources.getInteger(android.R.integer.config_shortAnimTime);
}
- private View mChild;
-
- private Rect mTargetScreen = new Rect();
-
- private int mCalloutState = 0;
- private int mCalloutLeft;
-
@Override
protected void onFinishInflate() {
mChild = findViewById(android.R.id.content);
mChild.setDuplicateParentStateEnabled(true);
+
+ // this will be expanded in showChild()
+ mChild.setScaleX(0.0f);
+ mChild.setScaleY(0.0f);
+ mChild.setAlpha(0.0f);
}
public View getChild() {
@@ -90,26 +97,6 @@ public class FloatingChildLayout extends FrameLayout {
return target;
}
- private void updateCallout(int calloutState, int calloutLeft) {
- if (mCalloutState != calloutState) {
- mCalloutState = calloutState;
- mChild.refreshDrawableState();
- }
-
- final Drawable background = mChild.getBackground();
- if (background != null && mCalloutLeft != calloutLeft) {
- mCalloutLeft = calloutLeft;
- background.setLevel(calloutLeft);
- }
- }
-
- @Override
- protected int[] onCreateDrawableState(int extraSpace) {
- final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
- mergeDrawableStates(drawableState, new int[] { mCalloutState });
- return drawableState;
- }
-
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
@@ -119,38 +106,23 @@ public class FloatingChildLayout extends FrameLayout {
final int childWidth = child.getMeasuredWidth();
final int childHeight = child.getMeasuredHeight();
- // default is no callout, left-aligned, and vertically centered
- int calloutState = 0;
- int childLeft = target.left;
- int childTop = target.centerY() - (childHeight / 2);
-
- // when target is wide, horizontally center instead of left-align
- if (target.width() > childWidth / 2) {
- childLeft = target.centerX() - (childWidth / 2);
- }
-
- final int areaAboveTarget = target.top;
- final int areaBelowTarget = getHeight() - target.bottom;
+ if (mFixedTopPosition != -1) {
+ // Horizontally centered, vertically fixed position
+ final int childLeft = (getWidth() - childWidth) / 2;
+ final int childTop = mFixedTopPosition;
+ layoutChild(child, childLeft, childTop);
+ } else {
+ // default is centered horizontally around target...
+ final int childLeft = target.centerX() - (childWidth / 2);
+ // ... and vertically aligned at the top
+ final int childTop = target.top;
- if (areaAboveTarget >= childHeight) {
- // enough room above target, place above and callout down
- calloutState = android.R.attr.state_first;
- childTop = target.top - childHeight;
+ // when child is outside bounds, nudge back inside
+ final int clampedChildLeft = clampDimension(childLeft, childWidth, getWidth());
+ final int clampedChildTop = clampDimension(childTop, childHeight, getHeight());
- } else if (areaBelowTarget >= childHeight) {
- // enough room below target, place below and callout up
- calloutState = android.R.attr.state_last;
- childTop = target.bottom;
+ layoutChild(child, clampedChildLeft, clampedChildTop);
}
-
- // when child is outside bounds, nudge back inside
- childLeft = clampDimension(childLeft, childWidth, getWidth());
- childTop = clampDimension(childTop, childHeight, getHeight());
-
- final int calloutLeft = target.centerX() - childLeft;
- updateCallout(calloutState, calloutLeft);
- layoutChild(child, childLeft, childTop);
-
}
private static int clampDimension(int value, int size, int max) {
@@ -159,58 +131,55 @@ public class FloatingChildLayout extends FrameLayout {
return (max - size) / 2;
}
- // clamp to lower bound
- value = Math.max(value, 0);
- // clamp to higher bound
- value = Math.min(value, max - size);
-
- return value;
+ // clamp to bounds
+ return Math.min(Math.max(value, 0), max - size);
}
private static void layoutChild(View child, int left, int top) {
child.layout(left, top, left + child.getMeasuredWidth(), top + child.getMeasuredHeight());
}
- /**
- * Begin animating {@link #getChild()} visible.
- */
- public void showChild() {
- final boolean calloutAbove = mCalloutState == android.R.attr.state_first;
- final Animation anim = AnimationUtils.loadAnimation(getContext(),
- calloutAbove ? R.anim.quickcontact_above_enter : R.anim.quickcontact_below_enter);
- mChild.startAnimation(anim);
- mChild.setVisibility(View.VISIBLE);
+ /** Begin animating {@link #getChild()} visible. */
+ public void showChild(Runnable onAnimationEndRunnable) {
+ animateScale(false, onAnimationEndRunnable);
}
- /**
- * Begin animating {@link #getChild()} invisible.
- */
- public void hideChild(final Runnable onAnimationEnd) {
- final boolean calloutAbove = mCalloutState == android.R.attr.state_first;
- final Animation anim = AnimationUtils.loadAnimation(getContext(),
- calloutAbove ? R.anim.quickcontact_above_exit : R.anim.quickcontact_below_exit);
-
- if (onAnimationEnd != null) {
- anim.setAnimationListener(new AnimationListener() {
- /** {@inheritDoc} */
- public void onAnimationStart(Animation animation) {
- // ignored
- }
-
- /** {@inheritDoc} */
- public void onAnimationRepeat(Animation animation) {
- // ignored
- }
+ /** Begin animating {@link #getChild()} invisible. */
+ public void hideChild(Runnable onAnimationEndRunnable) {
+ animateScale(true, onAnimationEndRunnable);
+ }
- /** {@inheritDoc} */
- public void onAnimationEnd(Animation animation) {
- onAnimationEnd.run();
+ /** Creates the open/close animation */
+ private void animateScale(boolean isExitAnimation, final Runnable onAnimationEndRunnable) {
+ mChild.setPivotX(mTargetScreen.centerX() - mChild.getLeft());
+ mChild.setPivotY(mTargetScreen.centerY() - mChild.getTop());
+ ViewPropertyAnimator animator = mChild.animate();
+ animator.setDuration(mAnimationDuration);
+ final int scaleInterpolator = isExitAnimation ? android.R.interpolator.accelerate_quint
+ : android.R.interpolator.decelerate_quint;
+ animator.setInterpolator(AnimationUtils.loadInterpolator(getContext(), scaleInterpolator));
+ final float scaleTarget = isExitAnimation ? 0.7f : 1.0f;
+ animator.scaleX(scaleTarget);
+ animator.scaleY(scaleTarget);
+ animator.alpha(isExitAnimation ? 0.0f : 1.0f);
+
+ if (onAnimationEndRunnable != null) {
+ animator.setListener(new AnimatorListener() {
+ @Override
+ public void onAnimationStart(Animator animation) {}
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {}
+
+ @Override
+ public void onAnimationCancel(Animator animation) {}
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ onAnimationEndRunnable.run();
}
});
}
-
- mChild.startAnimation(anim);
- mChild.setVisibility(View.INVISIBLE);
}
private View.OnTouchListener mOutsideTouchListener;
@@ -224,8 +193,7 @@ public class FloatingChildLayout extends FrameLayout {
// at this point, touch wasn't handled by child view; assume outside
if (mOutsideTouchListener != null) {
return mOutsideTouchListener.onTouch(this, event);
- } else {
- return false;
}
+ return false;
}
}
diff --git a/src/com/android/contacts/quickcontact/ProfileAction.java b/src/com/android/contacts/quickcontact/ProfileAction.java
deleted file mode 100644
index a04e52211..000000000
--- a/src/com/android/contacts/quickcontact/ProfileAction.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2010 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.quickcontact;
-
-import com.android.contacts.R;
-
-import android.content.Context;
-import android.content.Intent;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.provider.ContactsContract.Contacts;
-
-/**
- * Specific action that launches the profile card.
- */
-public class ProfileAction implements Action {
- private final Context mContext;
- private final Uri mLookupUri;
-
- public ProfileAction(Context context, Uri lookupUri) {
- mContext = context;
- mLookupUri = lookupUri;
- }
-
- /** {@inheritDoc} */
- @Override
- public CharSequence getHeader() {
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public CharSequence getBody() {
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public String getMimeType() {
- return Contacts.CONTENT_ITEM_TYPE;
- }
-
- /** {@inheritDoc} */
- @Override
- public Drawable getFallbackIcon() {
- return mContext.getResources().getDrawable(R.drawable.ic_contacts_details);
- }
-
- /** {@inheritDoc} */
- @Override
- public Intent getIntent() {
- final Intent intent = new Intent(Intent.ACTION_VIEW, mLookupUri);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- return intent;
- }
-
- /** {@inheritDoc} */
- @Override
- public Boolean isPrimary() {
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public Uri getDataUri() {
- return null;
- }
-
- /** {@inheritDoc} */
- @Override
- public long getDataId() {
- return -1;
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean collapseWith(Action t) {
- return false; // Never dup.
- }
-
- /** {@inheritDoc} */
- @Override
- public boolean shouldCollapseWith(Action t) {
- return false; // Never dup.
- }
-}
diff --git a/src/com/android/contacts/quickcontact/QuickContactActivity.java b/src/com/android/contacts/quickcontact/QuickContactActivity.java
new file mode 100644
index 000000000..933b96651
--- /dev/null
+++ b/src/com/android/contacts/quickcontact/QuickContactActivity.java
@@ -0,0 +1,722 @@
+/*
+ * 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.
+ */
+
+package com.android.contacts.quickcontact;
+
+import com.android.contacts.Collapser;
+import com.android.contacts.ContactPresenceIconUtil;
+import com.android.contacts.R;
+import com.android.contacts.model.AccountTypeManager;
+import com.android.contacts.model.DataKind;
+import com.android.contacts.util.Constants;
+import com.android.contacts.util.ContactBadgeUtil;
+import com.android.contacts.util.DataStatus;
+import com.android.contacts.util.NotifyingAsyncQueryHandler;
+import com.android.contacts.util.NotifyingAsyncQueryHandler.AsyncQueryListener;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.ActivityNotFoundException;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.AssetFileDescriptor;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Handler;
+import android.provider.ContactsContract.CommonDataKinds.Email;
+import android.provider.ContactsContract.CommonDataKinds.Im;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.CommonDataKinds.Photo;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
+import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
+import android.provider.ContactsContract.CommonDataKinds.Website;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Data;
+import android.provider.ContactsContract.DisplayPhoto;
+import android.provider.ContactsContract.QuickContact;
+import android.provider.ContactsContract.RawContacts;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.support.v4.view.ViewPager.SimpleOnPageChangeListener;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.HorizontalScrollView;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+// TODO: Save selected tab index during rotation
+// TODO: Handle GTalk Audio/Videochat secondary actions
+// TODO: Don't do a query in QuickContactBadge
+// TODO: Fix bug when QuickContact is dismissed using HOME or task switching
+// (it will relaunch with the previous contact)
+
+// Missing assets and specs:
+// Pushed states for list items
+
+/**
+ * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads
+ * data asynchronously, and then shows a popup with details centered around
+ * {@link Intent#getSourceBounds()}.
+ */
+public class QuickContactActivity extends Activity {
+ private static final String TAG = "QuickContact";
+
+ private static final boolean TRACE_LAUNCH = false;
+ private static final String TRACE_TAG = "quickcontact";
+
+ @SuppressWarnings("deprecation")
+ private static final String LEGACY_AUTHORITY = android.provider.Contacts.AUTHORITY;
+
+ private NotifyingAsyncQueryHandler mHandler;
+
+ private Uri mLookupUri;
+ private String[] mExcludeMimes;
+ private List<String> mSortedActionMimeTypes = Lists.newArrayList();
+
+ private boolean mHasFinishedAnimatingIn = false;
+ private boolean mHasStartedAnimatingOut = false;
+
+ private FloatingChildLayout mFloatingLayout;
+
+ private View mPhotoContainer;
+ private ViewGroup mTrack;
+ private HorizontalScrollView mTrackScroller;
+ private View mSelectedTabRectangle;
+ /** Line before the track. Depending on the layout, this can be null */
+ private View mLineBeforeTrack;
+
+ private ImageButton mOpenDetailsButton;
+ private ImageButton mOpenDetailsPushLayerButton;
+ private ViewPager mListPager;
+
+ /**
+ * Keeps the default action per mimetype. Empty if no default actions are set
+ */
+ private HashMap<String, Action> mDefaultsMap = new HashMap<String, Action>();
+
+ /**
+ * Set of {@link Action} that are associated with the aggregate currently
+ * displayed by this dialog, represented as a map from {@link String}
+ * MIME-type to a list of {@link Action}.
+ */
+ private ActionMultiMap mActions = new ActionMultiMap();
+
+ /**
+ * {@link #LEADING_MIMETYPES} and {@link #TRAILING_MIMETYPES} are used to sort MIME-types.
+ *
+ * <p>The MIME-types in {@link #LEADING_MIMETYPES} appear in the front of the dialog,
+ * in the order specified here.</p>
+ *
+ * <p>The ones in {@link #TRAILING_MIMETYPES} appear in the end of the dialog, in the order
+ * specified here.</p>
+ *
+ * <p>The rest go between them, in the order in the array.</p>
+ */
+ private static final List<String> LEADING_MIMETYPES = Lists.newArrayList(
+ Phone.CONTENT_ITEM_TYPE, SipAddress.CONTENT_ITEM_TYPE, Email.CONTENT_ITEM_TYPE);
+
+ /** See {@link #LEADING_MIMETYPES}. */
+ private static final List<String> TRAILING_MIMETYPES = Lists.newArrayList(
+ StructuredPostal.CONTENT_ITEM_TYPE, Website.CONTENT_ITEM_TYPE);
+
+ /** Id for the background handler that loads the data */
+ private static final int HANDLER_ID_DATA = 1;
+
+ @Override
+ protected void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ setContentView(R.layout.quickcontact_activity);
+
+ mFloatingLayout = (FloatingChildLayout) findViewById(R.id.floating_layout);
+ mTrack = (ViewGroup) findViewById(R.id.track);
+ mTrackScroller = (HorizontalScrollView) findViewById(R.id.track_scroller);
+ mOpenDetailsButton = (ImageButton) findViewById(R.id.open_details_button);
+ mOpenDetailsPushLayerButton = (ImageButton) findViewById(R.id.open_details_push_layer);
+ mListPager = (ViewPager) findViewById(R.id.item_list_pager);
+ mSelectedTabRectangle = findViewById(R.id.selected_tab_rectangle);
+ mLineBeforeTrack = findViewById(R.id.line_before_track);
+
+ mFloatingLayout.setOnOutsideTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return handleOutsideTouch();
+ }
+ });
+
+ final OnClickListener openDetailsClickHandler = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final Intent intent = new Intent(Intent.ACTION_VIEW, mLookupUri);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(intent);
+ hide(false);
+ }
+ };
+ mOpenDetailsButton.setOnClickListener(openDetailsClickHandler);
+ mOpenDetailsPushLayerButton.setOnClickListener(openDetailsClickHandler);
+ mListPager.setAdapter(new ViewPagerAdapter(getFragmentManager()));
+ mListPager.setOnPageChangeListener(new PageChangeListener());
+
+ mHandler = new NotifyingAsyncQueryHandler(this, mQueryListener);
+
+ show();
+ }
+
+ private void show() {
+
+ if (TRACE_LAUNCH) {
+ android.os.Debug.startMethodTracing(TRACE_TAG);
+ }
+
+ final Intent intent = getIntent();
+
+ Uri lookupUri = intent.getData();
+
+ // Check to see whether it comes from the old version.
+ if (LEGACY_AUTHORITY.equals(lookupUri.getAuthority())) {
+ final long rawContactId = ContentUris.parseId(lookupUri);
+ lookupUri = RawContacts.getContactLookupUri(getContentResolver(),
+ ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
+ }
+
+ mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri");
+
+ // Read requested parameters for displaying
+ final Rect targetScreen = intent.getSourceBounds();
+ Preconditions.checkNotNull(targetScreen, "missing targetScreen");
+ mFloatingLayout.setChildTargetScreen(targetScreen);
+
+ mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES);
+
+ // find and prepare correct header view
+ mPhotoContainer = findViewById(R.id.photo_container);
+ setHeaderText(R.id.name, R.string.quickcontact_missing_name);
+ setHeaderText(R.id.status, null);
+ setHeaderText(R.id.timestamp, null);
+ setHeaderImage(R.id.presence, null);
+
+ // Start background query for data, but only select photo rows when they
+ // directly match the super-primary PHOTO_ID.
+ final Uri dataUri = Uri.withAppendedPath(lookupUri, Contacts.Data.CONTENT_DIRECTORY);
+ mHandler.cancelOperation(HANDLER_ID_DATA);
+
+ // Select all data items of the contact (except for photos, where we only select the display
+ // photo)
+ mHandler.startQuery(HANDLER_ID_DATA, lookupUri, dataUri, DataQuery.PROJECTION, Data.MIMETYPE
+ + "!=? OR (" + Data.MIMETYPE + "=? AND " + Data._ID + "=" + Contacts.PHOTO_ID
+ + ")", new String[] { Photo.CONTENT_ITEM_TYPE, Photo.CONTENT_ITEM_TYPE }, null);
+ }
+
+ private boolean handleOutsideTouch() {
+ if (!mHasFinishedAnimatingIn) return false;
+ if (mHasStartedAnimatingOut) return false;
+
+ mHasStartedAnimatingOut = true;
+ hide(true);
+ return true;
+ }
+
+ private void hide(boolean withAnimation) {
+ // cancel any pending queries
+ mHandler.cancelOperation(HANDLER_ID_DATA);
+
+ if (withAnimation) {
+ mFloatingLayout.hideChild(new Runnable() {
+ @Override
+ public void run() {
+ finish();
+ }
+ });
+ } else {
+ mFloatingLayout.hideChild(null);
+ finish();
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ hide(true);
+ }
+
+ private final AsyncQueryListener mQueryListener = new AsyncQueryListener() {
+ @Override
+ public synchronized void onQueryComplete(int token, Object cookie, Cursor cursor) {
+ try {
+ if (isFinishing()) {
+ hide(false);
+ return;
+ } else if (cursor == null || cursor.getCount() == 0) {
+ Toast.makeText(QuickContactActivity.this, R.string.invalidContactMessage,
+ Toast.LENGTH_LONG).show();
+ hide(false);
+ return;
+ }
+
+ bindData(cursor);
+
+ if (TRACE_LAUNCH) {
+ android.os.Debug.stopMethodTracing();
+ }
+
+ // Data bound and ready, pull curtain to show. Put this on the Handler to ensure
+ // that the layout passes are completed
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mFloatingLayout.showChild(new Runnable() {
+ @Override
+ public void run() {
+ mHasFinishedAnimatingIn = true;
+ }
+ });
+ }
+ });
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+ };
+
+ /** Assign this string to the view, if found in {@link #mPhotoContainer}. */
+ private void setHeaderText(int id, int resId) {
+ setHeaderText(id, getText(resId));
+ }
+
+ /** Assign this string to the view, if found in {@link #mPhotoContainer}. */
+ private void setHeaderText(int id, CharSequence value) {
+ final View view = mPhotoContainer.findViewById(id);
+ if (view instanceof TextView) {
+ ((TextView)view).setText(value);
+ view.setVisibility(TextUtils.isEmpty(value) ? View.GONE : View.VISIBLE);
+ }
+ }
+
+ /** Assign this image to the view, if found in {@link #mPhotoContainer}. */
+ private void setHeaderImage(int id, Drawable drawable) {
+ final View view = mPhotoContainer.findViewById(id);
+ if (view instanceof ImageView) {
+ ((ImageView)view).setImageDrawable(drawable);
+ view.setVisibility(drawable == null ? View.GONE : View.VISIBLE);
+ }
+ }
+
+ /**
+ * Check if the given MIME-type appears in the list of excluded MIME-types
+ * that the most-recent caller requested.
+ */
+ private boolean isMimeExcluded(String mimeType) {
+ if (mExcludeMimes == null) return false;
+ for (String excludedMime : mExcludeMimes) {
+ if (TextUtils.equals(excludedMime, mimeType)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Handle the result from the {@link #TOKEN_DATA} query.
+ */
+ private void bindData(Cursor cursor) {
+ final ResolveCache cache = ResolveCache.getInstance(this);
+ final Context context = this;
+
+ mOpenDetailsButton.setVisibility(isMimeExcluded(Contacts.CONTENT_ITEM_TYPE) ? View.GONE
+ : View.VISIBLE);
+
+ mDefaultsMap.clear();
+
+ final DataStatus status = new DataStatus();
+ final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
+ context.getApplicationContext());
+ final ImageView photoView = (ImageView) mPhotoContainer.findViewById(R.id.photo);
+
+ Bitmap photoBitmap = null;
+ while (cursor.moveToNext()) {
+ // Handle any social status updates from this row
+ status.possibleUpdate(cursor);
+
+ final String mimeType = cursor.getString(DataQuery.MIMETYPE);
+
+ // Skip this data item if MIME-type excluded
+ if (isMimeExcluded(mimeType)) continue;
+
+ final long dataId = cursor.getLong(DataQuery._ID);
+ final String accountType = cursor.getString(DataQuery.ACCOUNT_TYPE);
+ final boolean isPrimary = cursor.getInt(DataQuery.IS_PRIMARY) != 0;
+ final boolean isSuperPrimary = cursor.getInt(DataQuery.IS_SUPER_PRIMARY) != 0;
+
+ // Handle photos included as data row
+ if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ final int displayPhotoColumnIndex = cursor.getColumnIndex(Photo.PHOTO_FILE_ID);
+ final boolean hasDisplayPhoto = !cursor.isNull(displayPhotoColumnIndex);
+ if (hasDisplayPhoto) {
+ final long displayPhotoId = cursor.getLong(displayPhotoColumnIndex);
+ final Uri displayPhotoUri = ContentUris.withAppendedId(
+ DisplayPhoto.CONTENT_URI, displayPhotoId);
+ // Fetch and JPEG uncompress on the background thread
+ new AsyncTask<Void, Void, Bitmap>() {
+ @Override
+ protected Bitmap doInBackground(Void... params) {
+ try {
+ AssetFileDescriptor fd = getContentResolver()
+ .openAssetFileDescriptor(displayPhotoUri, "r");
+ return BitmapFactory.decodeStream(fd.createInputStream());
+ } catch (IOException e) {
+ Log.e(TAG, "Error getting display photo. Ignoring, as we already " +
+ "have the thumbnail", e);
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap result) {
+ if (result == null) return;
+ photoView.setImageBitmap(result);
+ }
+ }.execute();
+ }
+ final int photoColumnIndex = cursor.getColumnIndex(Photo.PHOTO);
+ final byte[] photoBlob = cursor.getBlob(photoColumnIndex);
+ if (photoBlob != null) {
+ photoBitmap = BitmapFactory.decodeByteArray(photoBlob, 0, photoBlob.length);
+ }
+ continue;
+ }
+
+ final DataKind kind = accountTypes.getKindOrFallback(accountType, mimeType);
+
+ if (kind != null) {
+ // Build an action for this data entry, find a mapping to a UI
+ // element, build its summary from the cursor, and collect it
+ // along with all others of this MIME-type.
+ final Action action = new DataAction(context, mimeType, kind, dataId, cursor);
+ final boolean wasAdded = considerAdd(action, cache);
+ if (wasAdded) {
+ // Remember the default
+ if (isSuperPrimary || (isPrimary && (mDefaultsMap.get(mimeType) == null))) {
+ mDefaultsMap.put(mimeType, action);
+ }
+ }
+ }
+
+ boolean isIm = Im.CONTENT_ITEM_TYPE.equals(mimeType);
+
+ // Handle Email rows with presence data as Im entry
+ final boolean hasPresence = !cursor.isNull(DataQuery.PRESENCE);
+ if (hasPresence && Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
+ final DataKind imKind = accountTypes.getKindOrFallback(accountType,
+ Im.CONTENT_ITEM_TYPE);
+ if (imKind != null) {
+ final DataAction action = new DataAction(context, Im.CONTENT_ITEM_TYPE, imKind,
+ dataId, cursor);
+ considerAdd(action, cache);
+ isIm = true;
+ }
+ }
+
+ if (hasPresence && isIm) {
+ int chatCapability = cursor.getInt(DataQuery.CHAT_CAPABILITY);
+ if ((chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
+ final DataKind imKind = accountTypes.getKindOrFallback(accountType,
+ Im.CONTENT_ITEM_TYPE);
+ if (imKind != null) {
+ final DataAction chatAction = new DataAction(context,
+ Constants.MIME_TYPE_VIDEO_CHAT, imKind, dataId, cursor);
+ considerAdd(chatAction, cache);
+ }
+ }
+ }
+ }
+
+ // Collapse Action Lists (remove e.g. duplicate e-mail addresses from different sources)
+ for (List<Action> actionChildren : mActions.values()) {
+ Collapser.collapseList(actionChildren);
+ }
+
+ if (cursor.moveToLast()) {
+ // Read contact information from last data row
+ final String name = cursor.getString(DataQuery.DISPLAY_NAME);
+ final int presence = cursor.getInt(DataQuery.CONTACT_PRESENCE);
+ final int chatCapability = cursor.getInt(DataQuery.CONTACT_CHAT_CAPABILITY);
+ final Drawable statusIcon = ContactPresenceIconUtil.getChatCapabilityIcon(
+ context, presence, chatCapability);
+
+ setHeaderText(R.id.name, name);
+ // TODO: Bring this back once we have a design
+// setHeaderImage(R.id.presence, statusIcon);
+ }
+
+ if (photoView != null) {
+ // Place photo when discovered in data, otherwise show generic avatar
+ photoView.setImageBitmap(photoBitmap != null ? photoBitmap
+ : ContactBadgeUtil.loadPlaceholderPhoto(context));
+ }
+
+ // TODO: Bring this back once we have a design
+// if (status.isValid()) {
+// // Update status when valid was found
+// setHeaderText(R.id.status, status.getStatus());
+// setHeaderText(R.id.timestamp, status.getTimestampLabel(context));
+// }
+
+ // All the mime-types to add.
+ final Set<String> containedTypes = new HashSet<String>(mActions.keySet());
+ mSortedActionMimeTypes.clear();
+ // First, add LEADING_MIMETYPES, which are most common.
+ for (String mimeType : LEADING_MIMETYPES) {
+ if (containedTypes.contains(mimeType)) {
+ mSortedActionMimeTypes.add(mimeType);
+ containedTypes.remove(mimeType);
+ }
+ }
+
+ // Add all the remaining ones that are not TRAILING
+ for (String mimeType : containedTypes.toArray(new String[containedTypes.size()])) {
+ if (!TRAILING_MIMETYPES.contains(mimeType)) {
+ mSortedActionMimeTypes.add(mimeType);
+ containedTypes.remove(mimeType);
+ }
+ }
+
+ // Then, add TRAILING_MIMETYPES, which are least common.
+ for (String mimeType : TRAILING_MIMETYPES) {
+ if (containedTypes.contains(mimeType)) {
+ containedTypes.remove(mimeType);
+ mSortedActionMimeTypes.add(mimeType);
+ }
+ }
+
+ // Add buttons for each mimetype
+ for (String mimeType : mSortedActionMimeTypes) {
+ final View actionView = inflateAction(mimeType, cache, mTrack);
+ mTrack.addView(actionView);
+ }
+
+ final boolean hasData = !mSortedActionMimeTypes.isEmpty();
+ if (mLineBeforeTrack != null) {
+ mLineBeforeTrack.setVisibility(hasData ? View.VISIBLE : View.GONE);
+ }
+ mTrackScroller.setVisibility(hasData ? View.VISIBLE : View.GONE);
+ mSelectedTabRectangle.setVisibility(hasData ? View.VISIBLE : View.GONE);
+ mListPager.setVisibility(hasData ? View.VISIBLE : View.GONE);
+ }
+
+ /**
+ * Consider adding the given {@link Action}, which will only happen if
+ * {@link PackageManager} finds an application to handle
+ * {@link Action#getIntent()}.
+ * @return true if action has been added
+ */
+ private boolean considerAdd(Action action, ResolveCache resolveCache) {
+ if (resolveCache.hasResolve(action)) {
+ mActions.put(action.getMimeType(), action);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Inflate the in-track view for the action of the given MIME-type, collapsing duplicate values.
+ * Will use the icon provided by the {@link DataKind}.
+ */
+ private View inflateAction(String mimeType, ResolveCache resolveCache, ViewGroup root) {
+ final CheckableImageView typeView = (CheckableImageView) getLayoutInflater().inflate(
+ R.layout.quickcontact_track_button, root, false);
+
+ List<Action> children = mActions.get(mimeType);
+ typeView.setTag(mimeType);
+ final Action firstInfo = children.get(0);
+
+ // Set icon and listen for clicks
+ final CharSequence descrip = resolveCache.getDescription(firstInfo);
+ final Drawable icon = resolveCache.getIcon(firstInfo);
+ typeView.setChecked(false);
+ typeView.setContentDescription(descrip);
+ typeView.setImageDrawable(icon);
+ typeView.setOnClickListener(mTypeViewClickListener);
+
+ return typeView;
+ }
+
+ private CheckableImageView getActionViewAt(int position) {
+ return (CheckableImageView) mTrack.getChildAt(position);
+ }
+
+ @Override
+ public void onAttachFragment(Fragment fragment) {
+ final QuickContactListFragment listFragment = (QuickContactListFragment) fragment;
+ listFragment.setListener(mListFragmentListener);
+ }
+
+ /** A type (e.g. Call/Addresses was clicked) */
+ private final OnClickListener mTypeViewClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ final CheckableImageView actionView = (CheckableImageView)view;
+ final String mimeType = (String) actionView.getTag();
+ int index = mSortedActionMimeTypes.indexOf(mimeType);
+ mListPager.setCurrentItem(index, true);
+ }
+ };
+
+ private class ViewPagerAdapter extends FragmentPagerAdapter {
+ public ViewPagerAdapter(FragmentManager fragmentManager) {
+ super(fragmentManager);
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ QuickContactListFragment fragment = new QuickContactListFragment();
+ final String mimeType = mSortedActionMimeTypes.get(position);
+ final List<Action> actions = mActions.get(mimeType);
+ fragment.setActions(actions);
+ return fragment;
+ }
+
+ @Override
+ public int getCount() {
+ return mSortedActionMimeTypes.size();
+ }
+ }
+
+ private class PageChangeListener extends SimpleOnPageChangeListener {
+ @Override
+ public void onPageSelected(int position) {
+ final CheckableImageView actionView = getActionViewAt(position);
+ mTrackScroller.requestChildRectangleOnScreen(actionView,
+ new Rect(0, 0, actionView.getWidth(), actionView.getHeight()), false);
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ final RelativeLayout.LayoutParams layoutParams =
+ (RelativeLayout.LayoutParams) mSelectedTabRectangle.getLayoutParams();
+ final int width = mSelectedTabRectangle.getWidth();
+ layoutParams.leftMargin = (int) ((position + positionOffset) * width);
+ mSelectedTabRectangle.setLayoutParams(layoutParams);
+ }
+ }
+
+ private final QuickContactListFragment.Listener mListFragmentListener =
+ new QuickContactListFragment.Listener() {
+ @Override
+ public void onOutsideClick() {
+ // If there is no background, we want to dismiss, because to the user it seems
+ // like he had touched outside. If the ViewPager is solid however, those taps
+ // must be ignored
+ final boolean isTransparent = mListPager.getBackground() == null;
+ if (isTransparent) handleOutsideTouch();
+ }
+
+ @Override
+ public void onItemClicked(final Action action, final boolean alternate) {
+ final Runnable startAppRunnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ startActivity(alternate ? action.getAlternateIntent() : action.getIntent());
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(QuickContactActivity.this, R.string.quickcontact_missing_app,
+ Toast.LENGTH_SHORT).show();
+ }
+
+ hide(false);
+ }
+ };
+ // Defer the action to make the window properly repaint
+ new Handler().post(startAppRunnable);
+ }
+ };
+
+ private interface DataQuery {
+ final String[] PROJECTION = new String[] {
+ Data._ID,
+
+ RawContacts.ACCOUNT_TYPE,
+ Contacts.STARRED,
+ Contacts.DISPLAY_NAME,
+ Contacts.CONTACT_PRESENCE,
+ Contacts.CONTACT_CHAT_CAPABILITY,
+
+ Data.STATUS,
+ Data.STATUS_RES_PACKAGE,
+ Data.STATUS_ICON,
+ Data.STATUS_LABEL,
+ Data.STATUS_TIMESTAMP,
+ Data.PRESENCE,
+ Data.CHAT_CAPABILITY,
+
+ Data.RES_PACKAGE,
+ Data.MIMETYPE,
+ Data.IS_PRIMARY,
+ Data.IS_SUPER_PRIMARY,
+ Data.RAW_CONTACT_ID,
+
+ Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5,
+ Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10, Data.DATA11,
+ Data.DATA12, Data.DATA13, Data.DATA14, Data.DATA15,
+ };
+
+ final int _ID = 0;
+
+ final int ACCOUNT_TYPE = 1;
+ final int STARRED = 2;
+ final int DISPLAY_NAME = 3;
+ final int CONTACT_PRESENCE = 4;
+ final int CONTACT_CHAT_CAPABILITY = 5;
+
+ final int STATUS = 6;
+ final int STATUS_RES_PACKAGE = 7;
+ final int STATUS_ICON = 8;
+ final int STATUS_LABEL = 9;
+ final int STATUS_TIMESTAMP = 10;
+ final int PRESENCE = 11;
+ final int CHAT_CAPABILITY = 12;
+
+ final int RES_PACKAGE = 13;
+ final int MIMETYPE = 14;
+ final int IS_PRIMARY = 15;
+ final int IS_SUPER_PRIMARY = 16;
+ }
+}
diff --git a/src/com/android/contacts/quickcontact/QuickContactBackgroundDrawable.java b/src/com/android/contacts/quickcontact/QuickContactBackgroundDrawable.java
deleted file mode 100644
index 15311f9d5..000000000
--- a/src/com/android/contacts/quickcontact/QuickContactBackgroundDrawable.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 2010 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.quickcontact;
-
-import com.android.contacts.R;
-
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-
-/**
- * Background {@link Drawable} for {@link QuickContactWindow} that draws arrow
- * centered around requested position.
- */
-public class QuickContactBackgroundDrawable extends Drawable {
- private Drawable mLeftDrawable;
- private Drawable mMiddleDrawable;
- private Drawable mRightDrawable;
-
- private int mBottomOverride = Integer.MIN_VALUE;
-
- public QuickContactBackgroundDrawable(Resources res) {
- mLeftDrawable = res.getDrawable(R.drawable.quickactions_arrow_left_holo_light);
- mMiddleDrawable = res.getDrawable(R.drawable.quickactions_arrow_middle_holo_light);
- mRightDrawable = res.getDrawable(R.drawable.quickactions_arrow_right_holo_light);
- }
-
- @Override
- public void setAlpha(int alpha) {
- mLeftDrawable.setAlpha(alpha);
- mMiddleDrawable.setAlpha(alpha);
- mRightDrawable.setAlpha(alpha);
- }
-
- /**
- * Overrides the bottom bounds. This is used for the animation when the
- * QuickContact expands/collapses options
- */
- public void setBottomOverride(int value) {
- mBottomOverride = value;
- onBoundsChange(getBounds());
- invalidateSelf();
- }
-
- public void clearBottomOverride() {
- mBottomOverride = Integer.MIN_VALUE;
- onBoundsChange(getBounds());
- invalidateSelf();
- }
-
- public float getBottomOverride() {
- return mBottomOverride;
- }
-
- @Override
- public boolean isStateful() {
- return true;
- }
-
- @Override
- protected boolean onStateChange(int[] state) {
- super.onStateChange(state);
- mLeftDrawable.setState(state);
- mMiddleDrawable.setState(state);
- mRightDrawable.setState(state);
- return true;
- }
-
- @Override
- protected boolean onLevelChange(int level) {
- return true;
- }
-
- @Override
- public void setColorFilter(ColorFilter cf) {
- mLeftDrawable.setColorFilter(cf);
- mMiddleDrawable.setColorFilter(cf);
- mRightDrawable.setColorFilter(cf);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
-
- @Override
- protected void onBoundsChange(Rect bounds) {
- final int requestedX = getLevel();
-
- int middleLeft = requestedX - mMiddleDrawable.getIntrinsicWidth() / 2;
- int middleRight = requestedX + mMiddleDrawable.getIntrinsicWidth() / 2;
-
- // ensure left drawable is not smaller than its Intrinsic Width
- final int leftExtra = (middleLeft - bounds.left) - mLeftDrawable.getIntrinsicWidth();
- if (leftExtra < 0) {
- middleLeft -= leftExtra;
- middleRight -= leftExtra;
- }
-
- // ensure right drawable is not smaller than its Intrinsic Width
- final int rightExtra = (bounds.right - middleRight) - mRightDrawable.getIntrinsicWidth();
- if (rightExtra < 0) {
- middleLeft += rightExtra;
- middleRight += rightExtra;
- }
-
- final int bottom = mBottomOverride == Integer.MIN_VALUE ? bounds.bottom : mBottomOverride;
- mLeftDrawable.setBounds(bounds.left, bounds.top, middleLeft, bottom);
- mMiddleDrawable.setBounds(middleLeft, bounds.top, middleRight, bottom);
- mRightDrawable.setBounds(middleRight, bounds.top, bounds.right, bottom);
- }
-
- @Override
- public void draw(Canvas canvas) {
- mLeftDrawable.draw(canvas);
- mMiddleDrawable.draw(canvas);
- mRightDrawable.draw(canvas);
- }
-}
diff --git a/src/com/android/contacts/quickcontact/QuickContactListFragment.java b/src/com/android/contacts/quickcontact/QuickContactListFragment.java
new file mode 100644
index 000000000..910fedef2
--- /dev/null
+++ b/src/com/android/contacts/quickcontact/QuickContactListFragment.java
@@ -0,0 +1,151 @@
+/*
+ * 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.quickcontact;
+
+import com.android.contacts.R;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.List;
+
+/** A fragment that shows the list of resolve items below a tab */
+public class QuickContactListFragment extends Fragment {
+ private ListView mListView;
+ private List<Action> mActions;
+ private LinearLayout mFragmentContainer;
+ private Listener mListener;
+
+ public QuickContactListFragment() {
+ setRetainInstance(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ mFragmentContainer = (LinearLayout) inflater.inflate(R.layout.quickcontact_list_fragment,
+ container, false);
+ mListView = (ListView) mFragmentContainer.findViewById(R.id.list);
+ mListView.setOnItemClickListener(mItemClickListener);
+ mFragmentContainer.setOnClickListener(mOutsideClickListener);
+ configureAdapter();
+ return mFragmentContainer;
+ }
+
+ public void setActions(List<Action> actions) {
+ mActions = actions;
+ configureAdapter();
+ }
+
+ public void setListener(Listener value) {
+ mListener = value;
+ }
+
+ private void configureAdapter() {
+ if (mActions == null || mListView == null) return;
+
+ mListView.setAdapter(new BaseAdapter() {
+ @Override
+ public int getCount() {
+ return mActions.size();
+ }
+
+ @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) {
+ final View resultView = convertView != null ? convertView
+ : getActivity().getLayoutInflater()
+ .inflate(R.layout.quickcontact_list_item, parent, false);
+
+ // Set action title based on summary value
+ final Action action = mActions.get(position);
+
+ // TODO: Put those findViewByIds in a container
+ final TextView text1 = (TextView) resultView.findViewById(
+ android.R.id.text1);
+ final TextView text2 = (TextView) resultView.findViewById(
+ android.R.id.text2);
+ final ImageView alternateActionButton = (ImageView) resultView.findViewById(
+ R.id.secondary_action_button);
+ final View alternateActionDivider = resultView.findViewById(R.id.vertical_divider);
+
+ alternateActionButton.setOnClickListener(mSecondaryActionClickListener);
+ alternateActionButton.setTag(action);
+
+ final boolean hasAlternateAction = action.getAlternateIntent() != null;
+ alternateActionDivider.setVisibility(hasAlternateAction ? View.VISIBLE : View.GONE);
+ alternateActionButton.setImageDrawable(action.getAlternateIcon());
+
+ text1.setText(action.getBody());
+ text2.setText(action.getSubtitle().toString().toUpperCase());
+
+ resultView.setTag(action);
+ return resultView;
+ }
+ });
+ }
+
+ /** A secondary action (SMS) was clicked */
+ protected final OnClickListener mSecondaryActionClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final Action action = (Action) v.getTag();
+ if (mListener != null) mListener.onItemClicked(action, true);
+ }
+ };
+
+ /** A data item (e.g. phone number) was clicked */
+ private final AbsListView.OnItemClickListener mItemClickListener =
+ new AbsListView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ final Action action = (Action) view.getTag();
+ if (mListener != null) mListener.onItemClicked(action, false);
+ }
+ };
+
+ private final OnClickListener mOutsideClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (mListener != null) mListener.onOutsideClick();
+ }
+ };
+
+ public interface Listener {
+ void onOutsideClick();
+ void onItemClicked(Action action, boolean alternate);
+ }
+}
diff --git a/src/com/android/contacts/quickcontact/QuickContactWindow.java b/src/com/android/contacts/quickcontact/QuickContactWindow.java
deleted file mode 100644
index 5f4bcc98e..000000000
--- a/src/com/android/contacts/quickcontact/QuickContactWindow.java
+++ /dev/null
@@ -1,1026 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.contacts.quickcontact;
-
-import com.android.contacts.Collapser;
-import com.android.contacts.ContactPresenceIconUtil;
-import com.android.contacts.ContactSaveService;
-import com.android.contacts.R;
-import com.android.contacts.model.AccountTypeManager;
-import com.android.contacts.model.DataKind;
-import com.android.contacts.util.Constants;
-import com.android.contacts.util.DataStatus;
-import com.android.contacts.util.NotifyingAsyncQueryHandler;
-import com.google.android.collect.Lists;
-import com.google.common.base.Preconditions;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.ContentUris;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.provider.ContactsContract.CommonDataKinds.Email;
-import android.provider.ContactsContract.CommonDataKinds.Im;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.Photo;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
-import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
-import android.provider.ContactsContract.CommonDataKinds.Website;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.QuickContact;
-import android.provider.ContactsContract.RawContacts;
-import android.text.TextUtils;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewStub;
-import android.widget.AbsListView;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.Toast;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * Mostly translucent {@link Activity} that shows QuickContact dialog. It loads
- * data asynchronously, and then shows a popup with details centered around
- * {@link Intent#getSourceBounds()}.
- */
-public class QuickContactWindow extends Activity implements
- NotifyingAsyncQueryHandler.AsyncQueryListener, View.OnClickListener,
- AbsListView.OnItemClickListener {
- private static final String TAG = "QuickContact";
-
- private static final boolean TRACE_LAUNCH = false;
- private static final String TRACE_TAG = "quickcontact";
-
- private static final int ANIMATION_FADE_IN_TIME = 100;
- private static final int ANIMATION_FADE_OUT_TIME = 100;
- private static final int ANIMATION_EXPAND_TIME = 100;
- private static final int ANIMATION_COLLAPSE_TIME = 100;
-
- private NotifyingAsyncQueryHandler mHandler;
-
- private Uri mLookupUri;
- private int mMode;
- private String[] mExcludeMimes;
-
- private boolean mHasValidSocial = false;
-
- private FloatingChildLayout mFloatingLayout;
- private QuickContactBackgroundDrawable mBackground;
-
- private View mHeader;
- private ViewGroup mTrack;
- private FrameLayout mFooter;
- private LinearLayout mFooterDisambig;
- private LinearLayout mFooterClearDefaults;
-
- private ListView mResolveList;
- private CheckableImageView mLastAction;
- private CheckBox mSetPrimaryCheckBox;
- private ListView mDefaultsListView;
- private Button mClearDefaultsButton;
-
- /**
- * Keeps the default action per mimetype. Empty if no default actions are set
- */
- private HashMap<String, Action> mDefaultsMap = new HashMap<String, Action>();
-
- /**
- * Set of {@link Action} that are associated with the aggregate currently
- * displayed by this dialog, represented as a map from {@link String}
- * MIME-type to a list of {@link Action}.
- */
- private ActionMultiMap mActions = new ActionMultiMap();
-
- /**
- * {@link #PRECEDING_MIMETYPES} and {@link #FOLLOWING_MIMETYPES} are used to sort MIME-types.
- *
- * <p>The MIME-types in {@link #PRECEDING_MIMETYPES} appear in the front of the dialog,
- * in the order in the array.
- *
- * <p>The ones in {@link #FOLLOWING_MIMETYPES} appear in the end of the dialog, in alphabetical
- * order.
- *
- * <p>The rest go between them, in the order in the array.
- */
- private static final String[] PRECEDING_MIMETYPES = new String[] {
- Phone.CONTENT_ITEM_TYPE,
- SipAddress.CONTENT_ITEM_TYPE,
- Contacts.CONTENT_ITEM_TYPE,
- Constants.MIME_TYPE_SMS_ADDRESS,
- Email.CONTENT_ITEM_TYPE,
- };
-
- /**
- * See {@link #PRECEDING_MIMETYPES}.
- */
- private static final String[] FOLLOWING_MIMETYPES = new String[] {
- StructuredPostal.CONTENT_ITEM_TYPE,
- Website.CONTENT_ITEM_TYPE,
- };
-
- /**
- * List of MIMETYPES that do not represent real data rows and can therefore not be set
- * as defaults
- */
- private static final ArrayList<String> VIRTUAL_MIMETYPES = Lists.newArrayList(new String[] {
- Im.CONTENT_ITEM_TYPE,
- Constants.MIME_TYPE_SMS_ADDRESS,
- Constants.MIME_TYPE_VIDEO_CHAT,
- });
- private static final int TOKEN_DATA = 1;
-
- @Override
- protected void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- setContentView(R.layout.quickcontact_activity);
-
- mBackground = new QuickContactBackgroundDrawable(getResources());
-
- mFloatingLayout = findTypedViewById(R.id.floating_layout);
- mFloatingLayout.getChild().setBackgroundDrawable(mBackground);
- mFloatingLayout.setOnOutsideTouchListener(mOnOutsideTouchListener);
-
- mTrack = findTypedViewById(R.id.quickcontact);
- mFooter = findTypedViewById(R.id.footer);
- mFooterDisambig = findTypedViewById(R.id.footer_disambig);
- mFooterClearDefaults = findTypedViewById(R.id.footer_clear_defaults);
- mResolveList = findTypedViewById(android.R.id.list);
- mSetPrimaryCheckBox = findTypedViewById(android.R.id.checkbox);
-
- mDefaultsListView = findTypedViewById(R.id.defaults_list);
-
- mClearDefaultsButton = findTypedViewById(R.id.clear_defaults_button);
- mClearDefaultsButton.setOnClickListener(mOnClearDefaultsClickListener);
-
- mResolveList.setOnItemClickListener(this);
-
- mHandler = new NotifyingAsyncQueryHandler(this, this);
-
- show();
- }
-
- private View getHeaderView(int mode) {
- View header = null;
- switch (mode) {
- case QuickContact.MODE_SMALL:
- header = findViewById(R.id.header_small);
- break;
- case QuickContact.MODE_MEDIUM:
- header = findViewById(R.id.header_medium);
- break;
- case QuickContact.MODE_LARGE:
- header = findViewById(R.id.header_large);
- break;
- }
-
- if (header instanceof ViewStub) {
- // Inflate actual header if we picked a stub
- final ViewStub stub = (ViewStub)header;
- header = stub.inflate();
- } else if (header != null) {
- header.setVisibility(View.VISIBLE);
- }
-
- return header;
- }
-
- private void show() {
-
- if (TRACE_LAUNCH) {
- android.os.Debug.startMethodTracing(TRACE_TAG);
- }
-
- final Intent intent = getIntent();
-
- Uri lookupUri = intent.getData();
-
- // Check to see whether it comes from the old version.
- if (android.provider.Contacts.AUTHORITY.equals(lookupUri.getAuthority())) {
- final long rawContactId = ContentUris.parseId(lookupUri);
- lookupUri = RawContacts.getContactLookupUri(getContentResolver(),
- ContentUris.withAppendedId(RawContacts.CONTENT_URI, rawContactId));
- }
-
- mLookupUri = Preconditions.checkNotNull(lookupUri, "missing lookupUri");
-
- // Read requested parameters for displaying
- final Rect targetScreen = intent.getSourceBounds();
- Preconditions.checkNotNull(targetScreen, "missing targetScreen");
- mFloatingLayout.setChildTargetScreen(targetScreen);
-
- mMode = intent.getIntExtra(QuickContact.EXTRA_MODE, QuickContact.MODE_MEDIUM);
- mExcludeMimes = intent.getStringArrayExtra(QuickContact.EXTRA_EXCLUDE_MIMES);
-
- switch (mMode) {
- case QuickContact.MODE_SMALL:
- case QuickContact.MODE_MEDIUM:
- case QuickContact.MODE_LARGE:
- break;
- default:
- throw new IllegalArgumentException("Unexpected mode: " + mMode);
- }
-
- // find and prepare correct header view
- mHeader = getHeaderView(mMode);
- setHeaderText(R.id.name, R.string.quickcontact_missing_name);
- setHeaderText(R.id.status, null);
- setHeaderText(R.id.timestamp, null);
- setHeaderImage(R.id.presence, null);
-
- // Start background query for data, but only select photo rows when they
- // directly match the super-primary PHOTO_ID.
- final Uri dataUri = Uri.withAppendedPath(lookupUri, Contacts.Data.CONTENT_DIRECTORY);
- mHandler.cancelOperation(TOKEN_DATA);
-
- // Only request photo data when required by mode
- if (mMode == QuickContact.MODE_LARGE) {
- // Select photos, but only super-primary
- mHandler.startQuery(TOKEN_DATA, lookupUri, dataUri, DataQuery.PROJECTION, Data.MIMETYPE
- + "!=? OR (" + Data.MIMETYPE + "=? AND " + Data._ID + "=" + Contacts.PHOTO_ID
- + ")", new String[] { Photo.CONTENT_ITEM_TYPE, Photo.CONTENT_ITEM_TYPE }, null);
- } else {
- // Exclude all photos from cursor
- mHandler.startQuery(TOKEN_DATA, lookupUri, dataUri, DataQuery.PROJECTION, Data.MIMETYPE
- + "!=?", new String[] { Photo.CONTENT_ITEM_TYPE }, null);
- }
- }
-
- @SuppressWarnings("unchecked")
- private <T> T findTypedViewById(int id) {
- return (T) super.findViewById(id);
- }
-
- private View.OnTouchListener mOnOutsideTouchListener = new View.OnTouchListener() {
- /** {@inheritDoc} */
- public boolean onTouch(View v, MotionEvent event) {
- hide(true);
- return true;
- }
- };
-
- private View.OnClickListener mOnClearDefaultsClickListener = new View.OnClickListener() {
- /** {@inheritDoc} */
- public void onClick(View v) {
- clearDefaults();
- }
- };
-
- private void hide(boolean withAnimation) {
- // cancel any pending queries
- mHandler.cancelOperation(TOKEN_DATA);
-
- if (withAnimation) {
- mFloatingLayout.hideChild(new Runnable() {
- /** {@inheritDoc} */
- public void run() {
- finish();
- }
- });
- } else {
- mFloatingLayout.hideChild(null);
- finish();
- }
- }
-
- @Override
- public void onBackPressed() {
- hide(true);
- }
-
- /** {@inheritDoc} */
- public synchronized void onQueryComplete(int token, Object cookie, Cursor cursor) {
- try {
- if (isFinishing()) {
- hide(false);
- return;
- } else if (cursor == null || cursor.getCount() == 0) {
- Toast.makeText(this, R.string.invalidContactMessage, Toast.LENGTH_LONG).show();
- hide(false);
- return;
- }
-
- bindData(cursor);
-
- if (mMode == QuickContact.MODE_MEDIUM && !mHasValidSocial) {
- // Missing valid social, swap medium for small header
- mHeader.setVisibility(View.GONE);
- mHeader = getHeaderView(QuickContact.MODE_SMALL);
- }
-
- if (TRACE_LAUNCH) {
- android.os.Debug.stopMethodTracing();
- }
-
- // data bound and ready, pull curtain to show
- mFloatingLayout.showChild();
-
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- /** Assign this string to the view, if found in {@link #mHeader}. */
- private void setHeaderText(int id, int resId) {
- setHeaderText(id, getText(resId));
- }
-
- /** Assign this string to the view, if found in {@link #mHeader}. */
- private void setHeaderText(int id, CharSequence value) {
- final View view = mHeader.findViewById(id);
- if (view instanceof TextView) {
- ((TextView)view).setText(value);
- view.setVisibility(TextUtils.isEmpty(value) ? View.GONE : View.VISIBLE);
- }
- }
-
- /** Assign this image to the view, if found in {@link #mHeader}. */
- private void setHeaderImage(int id, Drawable drawable) {
- final View view = mHeader.findViewById(id);
- if (view instanceof ImageView) {
- ((ImageView)view).setImageDrawable(drawable);
- view.setVisibility(drawable == null ? View.GONE : View.VISIBLE);
- }
- }
-
- /**
- * Check if the given MIME-type appears in the list of excluded MIME-types
- * that the most-recent caller requested.
- */
- private boolean isMimeExcluded(String mimeType) {
- if (mExcludeMimes == null) return false;
- for (String excludedMime : mExcludeMimes) {
- if (TextUtils.equals(excludedMime, mimeType)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Handle the result from the {@link #TOKEN_DATA} query.
- */
- private void bindData(Cursor cursor) {
- final ResolveCache cache = ResolveCache.getInstance(this);
- final Context context = this;
-
- if (!isMimeExcluded(Contacts.CONTENT_ITEM_TYPE)) {
- // Add the profile shortcut action
- final Action action = new ProfileAction(context, mLookupUri);
- mActions.put(Contacts.CONTENT_ITEM_TYPE, action);
- }
-
- mDefaultsMap.clear();
-
- final DataStatus status = new DataStatus();
- final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
- context.getApplicationContext());
- final ImageView photoView = (ImageView) mHeader.findViewById(R.id.photo);
-
- Bitmap photoBitmap = null;
- while (cursor.moveToNext()) {
- final long dataId = cursor.getLong(DataQuery._ID);
- final String accountType = cursor.getString(DataQuery.ACCOUNT_TYPE);
- final String mimeType = cursor.getString(DataQuery.MIMETYPE);
- final boolean isPrimary = cursor.getInt(DataQuery.IS_PRIMARY) != 0;
- final boolean isSuperPrimary = cursor.getInt(DataQuery.IS_SUPER_PRIMARY) != 0;
-
- // Handle any social status updates from this row
- status.possibleUpdate(cursor);
-
- // Skip this data item if MIME-type excluded
- if (isMimeExcluded(mimeType)) continue;
-
- // Handle photos included as data row
- if (Photo.CONTENT_ITEM_TYPE.equals(mimeType)) {
- final int colPhoto = cursor.getColumnIndex(Photo.PHOTO);
- final byte[] photoBlob = cursor.getBlob(colPhoto);
- if (photoBlob != null) {
- photoBitmap = BitmapFactory.decodeByteArray(photoBlob, 0, photoBlob.length);
- }
- continue;
- }
-
- final DataKind kind = accountTypes.getKindOrFallback(accountType, mimeType);
-
- if (kind != null) {
- // Build an action for this data entry, find a mapping to a UI
- // element, build its summary from the cursor, and collect it
- // along with all others of this MIME-type.
- final Action action = new DataAction(context, mimeType, kind, dataId, cursor);
- final boolean wasAdded = considerAdd(action, cache);
- if (wasAdded) {
- // Remember the default
- if (isSuperPrimary || (isPrimary && (mDefaultsMap.get(mimeType) == null))) {
- mDefaultsMap.put(mimeType, action);
- }
- }
- }
-
- // If phone number, also insert as text message action
- if (Phone.CONTENT_ITEM_TYPE.equals(mimeType) && kind != null) {
- final DataAction action = new DataAction(context, Constants.MIME_TYPE_SMS_ADDRESS,
- kind, dataId, cursor);
- considerAdd(action, cache);
- }
-
- boolean isIm = Im.CONTENT_ITEM_TYPE.equals(mimeType);
-
- // Handle Email rows with presence data as Im entry
- final boolean hasPresence = !cursor.isNull(DataQuery.PRESENCE);
- if (hasPresence && Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
- final DataKind imKind = accountTypes.getKindOrFallback(accountType,
- Im.CONTENT_ITEM_TYPE);
- if (imKind != null) {
- final DataAction action = new DataAction(context, Im.CONTENT_ITEM_TYPE, imKind,
- dataId, cursor);
- considerAdd(action, cache);
- isIm = true;
- }
- }
-
- if (hasPresence && isIm) {
- int chatCapability = cursor.getInt(DataQuery.CHAT_CAPABILITY);
- if ((chatCapability & Im.CAPABILITY_HAS_CAMERA) != 0) {
- final DataKind imKind = accountTypes.getKindOrFallback(accountType,
- Im.CONTENT_ITEM_TYPE);
- if (imKind != null) {
- final DataAction chatAction = new DataAction(context,
- Constants.MIME_TYPE_VIDEO_CHAT, imKind, dataId, cursor);
- considerAdd(chatAction, cache);
- }
- }
- }
- }
-
- // Collapse Action Lists (remove e.g. duplicate e-mail addresses from different sources)
- for (ArrayList<Action> actionChildren : mActions.values()) {
- Collapser.collapseList(actionChildren);
- }
-
- // Make sure that we only display the "clear default" action if there
- // are actually several items to chose from
- boolean shouldDisplayClearDefaults = false;
- for (String mimetype : mDefaultsMap.keySet()) {
- if (mActions.get(mimetype).size() > 1) {
- shouldDisplayClearDefaults = true;
- break;
- }
- }
-
- if (shouldDisplayClearDefaults) {
- final Action action = new ClearDefaultsAction();
- mActions.put(action.getMimeType(), action);
- }
-
- if (cursor.moveToLast()) {
- // Read contact information from last data row
- final String name = cursor.getString(DataQuery.DISPLAY_NAME);
- final int presence = cursor.getInt(DataQuery.CONTACT_PRESENCE);
- final int chatCapability = cursor.getInt(DataQuery.CONTACT_CHAT_CAPABILITY);
- final Drawable statusIcon = ContactPresenceIconUtil.getChatCapabilityIcon(
- context, presence, chatCapability);
-
- setHeaderText(R.id.name, name);
- setHeaderImage(R.id.presence, statusIcon);
- }
-
- if (photoView != null) {
- // Place photo when discovered in data, otherwise hide
- photoView.setVisibility(photoBitmap != null ? View.VISIBLE : View.GONE);
- photoView.setImageBitmap(photoBitmap);
- }
-
- mHasValidSocial = status.isValid();
- if (mHasValidSocial && mMode != QuickContact.MODE_SMALL) {
- // Update status when valid was found
- setHeaderText(R.id.status, status.getStatus());
- setHeaderText(R.id.timestamp, status.getTimestampLabel(context));
- }
-
- // Turn our list of actions into UI elements
-
- // All the mime-types to add.
- final Set<String> containedTypes = new HashSet<String>(mActions.keySet());
-
- boolean hasData = false;
-
- // First, add PRECEDING_MIMETYPES, which are most common.
- for (String mimeType : PRECEDING_MIMETYPES) {
- if (containedTypes.contains(mimeType)) {
- hasData = true;
- mTrack.addView(inflateAction(mimeType, cache, mTrack));
- containedTypes.remove(mimeType);
- }
- }
-
- // Keep the current index to append non PRECEDING/FOLLOWING items.
- final int indexAfterPreceding = mTrack.getChildCount() - 1;
-
- // Then, add FOLLOWING_MIMETYPES, which are least common.
- for (String mimeType : FOLLOWING_MIMETYPES) {
- if (containedTypes.contains(mimeType)) {
- hasData = true;
- mTrack.addView(inflateAction(mimeType, cache, mTrack));
- containedTypes.remove(mimeType);
- }
- }
-
- // Show the clear-defaults button? If yes, it goes to the end of the list
- if (containedTypes.contains(ClearDefaultsAction.PSEUDO_MIME_TYPE)) {
- final ClearDefaultsAction action = (ClearDefaultsAction) mActions.get(
- ClearDefaultsAction.PSEUDO_MIME_TYPE).get(0);
- final CheckableImageView view = (CheckableImageView) getLayoutInflater().inflate(
- R.layout.quickcontact_item, mTrack, false);
-
- view.setChecked(false);
- final String description = context.getResources().getString(
- R.string.quickcontact_clear_defaults_description);
- view.setContentDescription(description);
- view.setImageResource(R.drawable.ic_menu_settings_holo_light);
- view.setOnClickListener(this);
- view.setTag(action);
- mTrack.addView(view);
- containedTypes.remove(ClearDefaultsAction.PSEUDO_MIME_TYPE);
- }
-
- // Go back to just after PRECEDING_MIMETYPES, and append the rest.
- int index = indexAfterPreceding;
- final String[] remainingTypes = containedTypes.toArray(new String[containedTypes.size()]);
- if (remainingTypes.length > 0) hasData = true;
- Arrays.sort(remainingTypes);
- for (String mimeType : remainingTypes) {
- mTrack.addView(inflateAction(mimeType, cache, mTrack), index++);
- }
-
- if (!hasData) {
- // When there is no data to display, add a TextView to show the user there's no data
- View view = getLayoutInflater().inflate(
- R.layout.quickcontact_item_nodata, mTrack, false);
- mTrack.addView(view, index++);
- }
- }
-
- /**
- * Clears the defaults currently set on the Contact
- */
- private void clearDefaults() {
- final Context context = this;
- final Set<String> mimeTypesKeySet = mDefaultsMap.keySet();
-
- // Copy to array so that we can modify the HashMap below
- final String[] mimeTypes = new String[mimeTypesKeySet.size()];
- mimeTypesKeySet.toArray(mimeTypes);
-
- // Send clear default Intents, one by one
- for (String mimeType : mimeTypes) {
- final Action action = mDefaultsMap.get(mimeType);
- final Intent intent = ContactSaveService.createClearPrimaryIntent(
- context, action.getDataId());
- context.startService(intent);
- mDefaultsMap.remove(mimeType);
- }
-
- // Close up and remove the configure default button
- animateCollapse(new Runnable() {
- @Override
- public void run() {
- for (int i = mTrack.getChildCount() - 1; i >= 0; i--) {
- final CheckableImageView button = (CheckableImageView) mTrack.getChildAt(i);
- if (button.getTag() instanceof ClearDefaultsAction) {
- mTrack.removeViewAt(i);
- break;
- }
- }
- }
- });
- }
-
- /**
- * Consider adding the given {@link Action}, which will only happen if
- * {@link PackageManager} finds an application to handle
- * {@link Action#getIntent()}.
- * @return true if action has been added
- */
- private boolean considerAdd(Action action, ResolveCache resolveCache) {
- if (resolveCache.hasResolve(action)) {
- mActions.put(action.getMimeType(), action);
- return true;
- }
- return false;
- }
-
- /**
- * Inflate the in-track view for the action of the given MIME-type, collapsing duplicate values.
- * Will use the icon provided by the {@link DataKind}.
- */
- private View inflateAction(String mimeType, ResolveCache resolveCache, ViewGroup root) {
- final CheckableImageView view = (CheckableImageView) getLayoutInflater().inflate(
- R.layout.quickcontact_item, root, false);
-
- // Add direct intent if single child, otherwise flag for multiple
- List<Action> children = mActions.get(mimeType);
- view.setTag(mimeType);
- final Action firstInfo = children.get(0);
-
- // Set icon and listen for clicks
- final CharSequence descrip = resolveCache.getDescription(firstInfo);
- final Drawable icon = resolveCache.getIcon(firstInfo);
- view.setChecked(false);
- view.setContentDescription(descrip);
- view.setImageDrawable(icon);
- view.setOnClickListener(this);
- return view;
- }
-
- /** {@inheritDoc} */
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- // Pass list item clicks along so that Intents are handled uniformly
- onClick(view);
- }
-
- /**
- * Helper for checking an action view
- */
- private void setNewActionViewChecked(CheckableImageView actionView) {
- if (mLastAction != null) mLastAction.setChecked(false);
- if (actionView != null) actionView.setChecked(true);
- mLastAction = actionView;
- }
-
- /**
- * Animates collpasing of the disambig area. When done, it expands again to the new size
- */
- private void animateCollapse(final Runnable whenDone) {
- final int oldBottom = mBackground.getBounds().bottom;
- mBackground.setBottomOverride(oldBottom);
-
- final ObjectAnimator fadeOutAnimator = ObjectAnimator.ofFloat(mFooter, "alpha",
- 1.0f, 0.0f);
- fadeOutAnimator.setDuration(ANIMATION_FADE_OUT_TIME);
- fadeOutAnimator.start();
-
- final ObjectAnimator collapseAnimator = ObjectAnimator.ofInt(mBackground,
- "bottomOverride", oldBottom, oldBottom - mFooter.getHeight());
- collapseAnimator.setDuration(ANIMATION_COLLAPSE_TIME);
- collapseAnimator.setStartDelay(ANIMATION_FADE_OUT_TIME);
- collapseAnimator.start();
-
- collapseAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mFooter.setVisibility(View.GONE);
- new Handler().post(whenDone);
- }
- });
- }
-
- /**
- * Animates expansion of the disambig area.
- * @param showClearDefaults true to expand to clear defaults. false to expand to intent disambig
- */
- private void animateExpand(boolean showClearDefaults) {
- mFooter.setVisibility(View.VISIBLE);
- mFooterDisambig.setVisibility(showClearDefaults ? View.GONE : View.VISIBLE);
- mFooterClearDefaults.setVisibility(showClearDefaults ? View.VISIBLE : View.GONE);
- final int oldBottom = mBackground.getBounds().bottom;
- mBackground.setBottomOverride(oldBottom);
- mFooter.setAlpha(0.0f);
- new Handler().post(new Runnable() {
- @Override
- public void run() {
- final int newBottom = mBackground.getBounds().bottom;
- final ObjectAnimator expandAnimator = ObjectAnimator.ofInt(mBackground,
- "bottomOverride", oldBottom, newBottom);
- expandAnimator.setDuration(ANIMATION_EXPAND_TIME);
- expandAnimator.start();
-
- expandAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- mBackground.clearBottomOverride();
- }
- });
-
- final ObjectAnimator fadeInAnimator = ObjectAnimator.ofFloat(mFooter,
- "alpha", 0.0f, 1.0f);
- fadeInAnimator.setDuration(ANIMATION_FADE_IN_TIME);
- fadeInAnimator.setStartDelay(ANIMATION_EXPAND_TIME);
- fadeInAnimator.start();
- }
- });
- }
-
- /** {@inheritDoc} */
- @Override
- public void onClick(View view) {
- final Context context = this;
-
- final boolean isActionView = (view instanceof CheckableImageView);
- final CheckableImageView actionView = isActionView ? (CheckableImageView)view : null;
- final Object tag = view.getTag();
-
- if (tag instanceof ClearDefaultsAction) {
- // Do nothing if already open
- if (actionView == mLastAction) return;
- // collapse any disambig that may already be open. the open clearing-defaults
- final Runnable expandClearDefaultsRunnable = new Runnable() {
- @Override
- public void run() {
- // Show resolution list and set adapter
- setNewActionViewChecked(actionView);
- final Action[] actions = new Action[mDefaultsMap.size()];
- mDefaultsMap.values().toArray(actions);
-
- mDefaultsListView.setAdapter(new BaseAdapter() {
- @Override
- public int getCount() {
- return actions.length;
- }
-
- @Override
- public Object getItem(int position) {
- return actions[position];
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- return false;
- }
-
- @Override
- public boolean isEnabled(int position) {
- return false;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = getLayoutInflater().inflate(
- R.layout.quickcontact_default_item, parent, false);
- }
-
- // Set action title based on summary value
- final Action defaultAction = actions[position];
-
- final TextView text1 = (TextView) convertView.findViewById(
- android.R.id.text1);
- final TextView text2 = (TextView) convertView.findViewById(
- android.R.id.text2);
-
- text1.setText(defaultAction.getHeader());
- text2.setText(defaultAction.getBody());
-
- convertView.setTag(defaultAction);
- return convertView;
- }
- });
-
- animateExpand(true);
- }
- };
- if (mFooter.getVisibility() == View.VISIBLE) {
- animateCollapse(expandClearDefaultsRunnable);
- } else {
- new Handler().post(expandClearDefaultsRunnable);
- }
- return;
- }
-
- // Determine whether to launch a specific Action or show a disambig-List
- final Action action;
- final List<Action> actionList;
- final boolean fromDisambigList;
- final String mimeType;
- if (tag instanceof Action) {
- action = (Action) tag;
- actionList = null;
- fromDisambigList = true;
- mimeType = action.getMimeType();
- } else if (tag instanceof String) {
- mimeType = (String) tag;
- actionList = mActions.get(mimeType);
-
- if (actionList.size() == 1) {
- // Just one item? Pick that one
- action = actionList.get(0);
- } else if (mDefaultsMap.containsKey(mimeType)) {
- // Default item? pick that one
- action = mDefaultsMap.get(mimeType);
- } else {
- // Several actions and none is default.
- action = null;
- }
- fromDisambigList = false;
- } else {
- throw new IllegalStateException("tag is neither Action nor (mimetype-) String");
- }
-
- if (action != null) {
- final boolean isVirtual = VIRTUAL_MIMETYPES.contains(mimeType);
- final boolean makePrimary = fromDisambigList && mSetPrimaryCheckBox.isChecked() &&
- !isVirtual;
- final Runnable startAppRunnable = new Runnable() {
- @Override
- public void run() {
- // Incoming tag is concrete intent, so try launching
- try {
- context.startActivity(action.getIntent());
- } catch (ActivityNotFoundException e) {
- Toast.makeText(context, R.string.quickcontact_missing_app,
- Toast.LENGTH_SHORT).show();
- }
-
- // Hide the resolution list, if present
- setNewActionViewChecked(null);
-
- // Set default?
- final long dataId = action.getDataId();
- if (makePrimary && dataId != -1) {
- Intent serviceIntent = ContactSaveService.createSetSuperPrimaryIntent(
- context, dataId);
- context.startService(serviceIntent);
- }
-
- hide(false);
- }
- };
- if (isActionView && mFooter.getVisibility() == View.VISIBLE) {
- // If the footer is currently opened, animate its collapse and then
- // execute the target app
- animateCollapse(startAppRunnable);
- } else {
- // Defer the action to make the window properly repaint
- new Handler().post(startAppRunnable);
- }
- return;
- }
-
- // This was not a specific Action. Expand the disambig-list
- if (actionList == null) throw new IllegalStateException();
-
- // Don't do anything if already open
- if (actionView == mLastAction) return;
- final Runnable configureListRunnable = new Runnable() {
- @Override
- public void run() {
- // Show resolution list and set adapter
- setNewActionViewChecked(actionView);
- final boolean isVirtual = VIRTUAL_MIMETYPES.contains(mimeType);
- mSetPrimaryCheckBox.setVisibility(isVirtual ? View.GONE : View.VISIBLE);
-
- mResolveList.setAdapter(new BaseAdapter() {
- @Override
- public int getCount() {
- return actionList.size();
- }
-
- @Override
- public Object getItem(int position) {
- return actionList.get(position);
- }
-
- @Override
- public long getItemId(int position) {
- return position;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
- convertView = getLayoutInflater().inflate(
- R.layout.quickcontact_resolve_item, parent, false);
- }
-
- // Set action title based on summary value
- final Action listAction = actionList.get(position);
-
- final TextView text1 = (TextView) convertView.findViewById(
- android.R.id.text1);
- final TextView text2 = (TextView) convertView.findViewById(
- android.R.id.text2);
-
- text1.setText(listAction.getHeader());
- text2.setText(listAction.getBody());
-
- convertView.setTag(listAction);
- return convertView;
- }
- });
-
- animateExpand(false);
- }
- };
-
- if (mFooter.getVisibility() == View.VISIBLE) {
- // If the expansion list is currently opened, animate its collapse and then
- // execute the target app
- animateCollapse(configureListRunnable);
- } else {
- // Defer the action to make the window properly repaint
- configureListRunnable.run();
- }
- }
-
-
- private interface DataQuery {
- final String[] PROJECTION = new String[] {
- Data._ID,
-
- RawContacts.ACCOUNT_TYPE,
- Contacts.STARRED,
- Contacts.DISPLAY_NAME,
- Contacts.CONTACT_PRESENCE,
- Contacts.CONTACT_CHAT_CAPABILITY,
-
- Data.STATUS,
- Data.STATUS_RES_PACKAGE,
- Data.STATUS_ICON,
- Data.STATUS_LABEL,
- Data.STATUS_TIMESTAMP,
- Data.PRESENCE,
- Data.CHAT_CAPABILITY,
-
- Data.RES_PACKAGE,
- Data.MIMETYPE,
- Data.IS_PRIMARY,
- Data.IS_SUPER_PRIMARY,
- Data.RAW_CONTACT_ID,
-
- Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5,
- Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10, Data.DATA11,
- Data.DATA12, Data.DATA13, Data.DATA14, Data.DATA15,
- };
-
- final int _ID = 0;
-
- final int ACCOUNT_TYPE = 1;
- final int STARRED = 2;
- final int DISPLAY_NAME = 3;
- final int CONTACT_PRESENCE = 4;
- final int CONTACT_CHAT_CAPABILITY = 5;
-
- final int STATUS = 6;
- final int STATUS_RES_PACKAGE = 7;
- final int STATUS_ICON = 8;
- final int STATUS_LABEL = 9;
- final int STATUS_TIMESTAMP = 10;
- final int PRESENCE = 11;
- final int CHAT_CAPABILITY = 12;
-
- final int RES_PACKAGE = 13;
- final int MIMETYPE = 14;
- final int IS_PRIMARY = 15;
- final int IS_SUPER_PRIMARY = 16;
- }
-}
diff --git a/src/com/android/contacts/quickcontact/ResolveCache.java b/src/com/android/contacts/quickcontact/ResolveCache.java
index 2b9e92ff4..71c4d0a99 100644
--- a/src/com/android/contacts/quickcontact/ResolveCache.java
+++ b/src/com/android/contacts/quickcontact/ResolveCache.java
@@ -134,7 +134,7 @@ public class ResolveCache {
/**
* Best {@link ResolveInfo} when multiple found. Ties are broken by
- * selecting first from the {QuickContactWindow#sPreferResolve} list of
+ * selecting first from the {@link QuickContactActivity#sPreferResolve} list of
* preferred packages, second by apps that live on the system partition,
* otherwise the app from the top of the list. This is
* <strong>only</strong> used for selecting a default icon for
@@ -182,10 +182,10 @@ public class ResolveCache {
* for accessibility purposes.
*/
public CharSequence getDescription(Action action) {
- final CharSequence actionHeader = action.getHeader();
+ final CharSequence actionSubtitle = action.getSubtitle();
final ResolveInfo info = getEntry(action).bestResolve;
- if (!TextUtils.isEmpty(actionHeader)) {
- return actionHeader;
+ if (!TextUtils.isEmpty(actionSubtitle)) {
+ return actionSubtitle;
} else if (info != null) {
return info.loadLabel(mPackageManager);
} else {
diff --git a/src/com/android/contacts/util/Constants.java b/src/com/android/contacts/util/Constants.java
index 24576003c..a8ba05964 100644
--- a/src/com/android/contacts/util/Constants.java
+++ b/src/com/android/contacts/util/Constants.java
@@ -16,15 +16,7 @@
package com.android.contacts.util;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-
public class Constants {
- /**
- * Specific MIME-type for {@link Phone#CONTENT_ITEM_TYPE} entries that
- * distinguishes actions that should initiate a text message.
- */
- public static final String MIME_TYPE_SMS_ADDRESS = "vnd.android.cursor.item/sms-address";
-
public static final String MIME_TYPE_VIDEO_CHAT = "vnd.android.cursor.item/video-chat-address";
public static final String SCHEME_TEL = "tel";
@@ -32,5 +24,4 @@ public class Constants {
public static final String SCHEME_MAILTO = "mailto";
public static final String SCHEME_IMTO = "imto";
public static final String SCHEME_SIP = "sip";
-
}
diff --git a/tests/res/layout/quick_contact_tests.xml b/tests/res/layout/quick_contact_tests.xml
index fb2d51875..aa0648e99 100644
--- a/tests/res/layout/quick_contact_tests.xml
+++ b/tests/res/layout/quick_contact_tests.xml
@@ -29,19 +29,19 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/quickContactBadgeStyleWindowSmall"
- android:layout_marginLeft="32dip" />
+ android:layout_marginLeft="4dip" />
<QuickContactBadge
android:id="@+id/medium_badge1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/quickContactBadgeStyleWindowMedium"
- android:layout_marginLeft="64dip" />
+ android:layout_marginLeft="4dip" />
<QuickContactBadge
android:id="@+id/large_badge1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/quickContactBadgeStyleWindowLarge"
- android:layout_marginLeft="64dip" />
+ android:layout_marginLeft="4dip" />
</LinearLayout>
<View
android:layout_width="match_parent"
@@ -77,19 +77,19 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/quickContactBadgeStyleSmallWindowSmall"
- android:layout_marginLeft="32dip" />
+ android:layout_marginLeft="4dip" />
<QuickContactBadge
android:id="@+id/medium_badge2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/quickContactBadgeStyleSmallWindowMedium"
- android:layout_marginLeft="64dip" />
+ android:layout_marginLeft="4dip" />
<QuickContactBadge
android:id="@+id/large_badge2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="?android:attr/quickContactBadgeStyleSmallWindowLarge"
- android:layout_marginLeft="64dip" />
+ android:layout_marginLeft="4dip" />
</LinearLayout>
</LinearLayout>