Merge "Re-introduce appropriate "activated" background"
diff --git a/res/color/list_secondary_text_color.xml b/res/color/list_secondary_text_color.xml
deleted file mode 100644
index edf8678..0000000
--- a/res/color/list_secondary_text_color.xml
+++ /dev/null
@@ -1,22 +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_activated="true" android:color="@color/secondary_text_color_activated" />
- <item android:color="@color/secondary_text_color" /> <!-- not selected -->
-
-</selector>
diff --git a/res/color/list_primary_text_color.xml b/res/color/primary_text_color.xml
similarity index 81%
copy from res/color/list_primary_text_color.xml
copy to res/color/primary_text_color.xml
index 7c185fc..acc2fb7 100644
--- a/res/color/list_primary_text_color.xml
+++ b/res/color/primary_text_color.xml
@@ -16,7 +16,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:color="@color/primary_text_color_activated"/>
- <item android:color="@color/primary_text_color" /> <!-- not selected -->
+ <item android:state_activated="true" android:color="#FFFFFF" />
+ <item android:color="#333333" /> <!-- not selected -->
</selector>
diff --git a/res/color/list_primary_text_color.xml b/res/color/secondary_text_color.xml
similarity index 81%
rename from res/color/list_primary_text_color.xml
rename to res/color/secondary_text_color.xml
index 7c185fc..1c62458 100644
--- a/res/color/list_primary_text_color.xml
+++ b/res/color/secondary_text_color.xml
@@ -16,7 +16,7 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:color="@color/primary_text_color_activated"/>
- <item android:color="@color/primary_text_color" /> <!-- not selected -->
+ <item android:state_activated="true" android:color="#FFFFFF" />
+ <item android:color="#777777" /> <!-- not selected -->
</selector>
diff --git a/res/drawable-hdpi/ab_solid_custom_blue_inverse_holo.9.png b/res/drawable-hdpi/ab_solid_custom_blue_inverse_holo.9.png
index 80fb400..956d61b 100644
--- a/res/drawable-hdpi/ab_solid_custom_blue_inverse_holo.9.png
+++ b/res/drawable-hdpi/ab_solid_custom_blue_inverse_holo.9.png
Binary files differ
diff --git a/res/drawable-hdpi/account_spinner_icon.png b/res/drawable-hdpi/account_spinner_icon.png
index 3e82e51..9566386 100644
--- a/res/drawable-hdpi/account_spinner_icon.png
+++ b/res/drawable-hdpi/account_spinner_icon.png
Binary files differ
diff --git a/res/drawable-hdpi/list_section_divider_holo_custom.9.png b/res/drawable-hdpi/list_section_divider_holo_custom.9.png
index 6c0d251..1e3e778 100644
--- a/res/drawable-hdpi/list_section_divider_holo_custom.9.png
+++ b/res/drawable-hdpi/list_section_divider_holo_custom.9.png
Binary files differ
diff --git a/res/drawable-mdpi/ab_solid_custom_blue_inverse_holo.9.png b/res/drawable-mdpi/ab_solid_custom_blue_inverse_holo.9.png
index f3c0a90..3e9f167 100644
--- a/res/drawable-mdpi/ab_solid_custom_blue_inverse_holo.9.png
+++ b/res/drawable-mdpi/ab_solid_custom_blue_inverse_holo.9.png
Binary files differ
diff --git a/res/drawable-mdpi/account_spinner_icon.png b/res/drawable-mdpi/account_spinner_icon.png
index d9aaf02..e159d59 100644
--- a/res/drawable-mdpi/account_spinner_icon.png
+++ b/res/drawable-mdpi/account_spinner_icon.png
Binary files differ
diff --git a/res/drawable-mdpi/list_section_divider_holo_custom.9.png b/res/drawable-mdpi/list_section_divider_holo_custom.9.png
index cfc57ee..1d8fd09 100644
--- a/res/drawable-mdpi/list_section_divider_holo_custom.9.png
+++ b/res/drawable-mdpi/list_section_divider_holo_custom.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/ab_solid_custom_blue_inverse_holo.9.png b/res/drawable-xhdpi/ab_solid_custom_blue_inverse_holo.9.png
index 3c97b20..31fea59 100644
--- a/res/drawable-xhdpi/ab_solid_custom_blue_inverse_holo.9.png
+++ b/res/drawable-xhdpi/ab_solid_custom_blue_inverse_holo.9.png
Binary files differ
diff --git a/res/drawable-xhdpi/account_spinner_icon.png b/res/drawable-xhdpi/account_spinner_icon.png
index 8b888cb..d3d3cac 100644
--- a/res/drawable-xhdpi/account_spinner_icon.png
+++ b/res/drawable-xhdpi/account_spinner_icon.png
Binary files differ
diff --git a/res/drawable-xhdpi/list_section_divider_holo_custom.9.png b/res/drawable-xhdpi/list_section_divider_holo_custom.9.png
index 32e79e1..0bd8a0f 100644
--- a/res/drawable-xhdpi/list_section_divider_holo_custom.9.png
+++ b/res/drawable-xhdpi/list_section_divider_holo_custom.9.png
Binary files differ
diff --git a/res/layout-sw580dp/contact_detail_container.xml b/res/layout-sw580dp/contact_detail_container.xml
index 58a6eb3..cdb789f 100644
--- a/res/layout-sw580dp/contact_detail_container.xml
+++ b/res/layout-sw580dp/contact_detail_container.xml
@@ -17,8 +17,7 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="vertical"
- android:background="@color/background_primary">
+ android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/pager"
diff --git a/res/layout-sw580dp/group_detail_fragment.xml b/res/layout-sw580dp/group_detail_fragment.xml
index 90ca03a..438a987 100644
--- a/res/layout-sw580dp/group_detail_fragment.xml
+++ b/res/layout-sw580dp/group_detail_fragment.xml
@@ -22,8 +22,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/group_detail_border_padding"
- android:paddingRight="@dimen/group_detail_border_padding"
- android:background="@drawable/panel_content">
+ android:paddingRight="@dimen/group_detail_border_padding">
<TextView
android:id="@+id/group_title"
diff --git a/res/layout-sw580dp/people_activity.xml b/res/layout-sw580dp/people_activity.xml
index e15c079..fecb848 100644
--- a/res/layout-sw580dp/people_activity.xml
+++ b/res/layout-sw580dp/people_activity.xml
@@ -58,6 +58,7 @@
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1"
+ android:background="@color/background_primary"
ex:clipMarginLeft="0dip"
ex:clipMarginTop="3dip"
ex:clipMarginRight="3dip"
@@ -72,7 +73,10 @@
android:id="@+id/contact_detail_container"
layout="@layout/contact_detail_container"
android:layout_width="match_parent"
- android:layout_height="match_parent"/>
+ android:layout_height="match_parent"
+ android:layout_marginTop="16dip"
+ android:layout_marginLeft="16dip"
+ android:layout_marginRight="16dip"/>
<!-- This invisible worker fragment loads the contact's details -->
<fragment
diff --git a/res/layout/editor_account_header.xml b/res/layout/editor_account_header.xml
index b6b19db..ff33cf1 100644
--- a/res/layout/editor_account_header.xml
+++ b/res/layout/editor_account_header.xml
@@ -24,6 +24,7 @@
android:orientation="horizontal"
android:paddingTop="8dip"
android:paddingBottom="8dip"
+ android:gravity="center_vertical"
android:paddingLeft="@dimen/account_container_left_padding"
android:paddingRight="32dip">
diff --git a/res/layout/editor_account_header_with_dropdown.xml b/res/layout/editor_account_header_with_dropdown.xml
index 74abee9..001eaae 100644
--- a/res/layout/editor_account_header_with_dropdown.xml
+++ b/res/layout/editor_account_header_with_dropdown.xml
@@ -22,6 +22,7 @@
android:minHeight="48dip"
android:background="#EEEEEE"
android:orientation="horizontal"
+ android:gravity="center_vertical"
android:paddingLeft="@dimen/account_container_left_padding"
android:paddingRight="32dip">
diff --git a/res/layout/group_browse_list_item.xml b/res/layout/group_browse_list_item.xml
index b213754..45f444f 100644
--- a/res/layout/group_browse_list_item.xml
+++ b/res/layout/group_browse_list_item.xml
@@ -71,7 +71,6 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/list_primary_text_color"
android:ellipsize="end"
android:singleLine="true" />
@@ -80,7 +79,7 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/list_secondary_text_color"
+ android:textColor="?android:attr/textColorSecondary"
android:ellipsize="end"
android:singleLine="true" />
diff --git a/res/layout/item_read_only_field.xml b/res/layout/item_read_only_field.xml
index 03778cc..5f8367f 100644
--- a/res/layout/item_read_only_field.xml
+++ b/res/layout/item_read_only_field.xml
@@ -14,7 +14,8 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
@@ -23,13 +24,29 @@
android:id="@+id/kind_title_layout"
layout="@layout/edit_kind_title" />
- <TextView android:id="@+id/data"
- android:layout_width="wrap_content"
- android:layout_height="0px"
- android:layout_weight="1"
- android:layout_marginLeft="16dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondary"
- android:singleLine="true"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="@dimen/editor_min_line_item_height"
+ android:orientation="horizontal">
+ <TextView
+ android:id="@+id/data"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginLeft="16dip"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:textColor="?android:attr/textColorPrimary"
+ android:singleLine="true"/>
+ <TextView
+ android:id="@+id/type"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_marginLeft="8dip"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="?android:attr/textColorSecondary"
+ android:singleLine="true"/>
+ </LinearLayout>
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/res/layout/stream_item_container.xml b/res/layout/stream_item_container.xml
index 308c5f5..de4f87d 100644
--- a/res/layout/stream_item_container.xml
+++ b/res/layout/stream_item_container.xml
@@ -21,7 +21,7 @@
android:paddingLeft="@dimen/detail_update_section_side_padding"
android:paddingRight="@dimen/detail_update_section_side_padding">
- <TableLayout
+ <LinearLayout
android:id="@+id/stream_item_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -31,6 +31,7 @@
android:paddingBottom="@dimen/detail_update_section_item_vertical_padding"
android:background="?android:attr/selectableItemBackground"
android:layout_gravity="center_vertical"
+ android:orientation="vertical"
/>
<View
diff --git a/res/layout/stream_item_row_image_and_text.xml b/res/layout/stream_item_row_image_and_text.xml
index 882a23b..c5699f4 100644
--- a/res/layout/stream_item_row_image_and_text.xml
+++ b/res/layout/stream_item_row_image_and_text.xml
@@ -14,68 +14,41 @@
limitations under the License.
-->
-<TableRow
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts">
+ xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
- <view
- class="com.android.contacts.widget.ProportionalLayout"
- android:layout_width="0dip"
+ <LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginRight="@dimen/detail_update_section_between_items_horizontal_padding"
- android:layout_weight="1"
- ex:ratio="1"
- ex:direction="widthToHeight">
- <include
- android:id="@+id/stream_item_first_image"
- layout="@layout/stream_item_photo"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
- </view>
+ android:layout_marginBottom="8dip"
+ android:orientation="horizontal"
+ android:weightSum="2">
- <view
- class="com.android.contacts.widget.ProportionalLayout"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- ex:ratio="1"
- ex:direction="widthToHeight">
- <LinearLayout
- android:id="@+id/stream_item_second_text"
- android:orientation="vertical"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
+ <view
+ class="com.android.contacts.widget.ProportionalLayout"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginRight="@dimen/detail_update_section_between_items_horizontal_padding"
+ ex:ratio="1"
+ ex:direction="widthToHeight">
- <TextView android:id="@+id/stream_item_html"
+ <include
+ android:id="@+id/stream_item_first_image"
+ layout="@layout/stream_item_photo"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="16sp"
- android:textColor="?android:attr/textColorPrimary" />
+ android:layout_height="match_parent"/>
- <LinearLayout
- android:orientation="horizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:id="@+id/stream_item_attribution"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:maxLines="1"
- android:ellipsize="end"
- android:layout_weight="1" />
+ </view>
- <TextView android:id="@+id/stream_item_comments"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/detail_update_section_attribution_comments_padding"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="?android:attr/textColorSecondary"
- android:visibility="gone"
- android:maxLines="1" />
- </LinearLayout>
+ </LinearLayout>
- </LinearLayout>
- </view>
+ <include
+ android:id="@+id/stream_item_second_text"
+ layout="@layout/stream_item_row_text_only"/>
-</TableRow>
+</LinearLayout>
diff --git a/res/layout/stream_item_row_two_images.xml b/res/layout/stream_item_row_two_images.xml
index f10b7d8..3a524bf 100644
--- a/res/layout/stream_item_row_two_images.xml
+++ b/res/layout/stream_item_row_two_images.xml
@@ -14,9 +14,11 @@
limitations under the License.
-->
-<TableRow
+<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts">
+ xmlns:ex="http://schemas.android.com/apk/res/com.android.contacts"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
<view
class="com.android.contacts.widget.ProportionalLayout"
@@ -47,4 +49,4 @@
android:layout_height="match_parent"/>
</view>
-</TableRow>
+</LinearLayout>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 5e8bd70..1a8ee23 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -80,19 +80,9 @@
<!-- Color of the theme of the People app -->
<color name="people_app_theme_color">#33B5E5</color>
- <!-- Primary text color in the People app -->
- <color name="primary_text_color">#333333</color>
-
- <!-- Activated primary text color in the People app -->
- <color name="primary_text_color_activated">#FFFFFF</color>
-
- <!-- Secondary text color in the People app -->
- <color name="secondary_text_color">#777777</color>
+ <!-- Secondary text color in the Phone app -->
<color name="dialtacts_secondary_text_color">#888888</color>
- <!-- Activated secondary text color in the People app -->
- <color name="secondary_text_color_activated">#FFFFFF</color>
-
<!-- Colors in the contact browser list -->
<color name="contact_count_text_color">#AAAAAA</color>
diff --git a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
index 5d6c7d5..cd4add6 100644
--- a/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
+++ b/src/com/android/contacts/detail/ContactDetailDisplayUtils.java
@@ -237,8 +237,6 @@
if (!contactData.getStreamItems().isEmpty()) {
StreamItemEntry firstEntry = contactData.getStreamItems().get(0);
snippet = Html.fromHtml(firstEntry.getText());
- // Add quotes around the text
- snippet = context.getString(R.string.recent_updates_tab_text, snippet);
if (!firstEntry.getPhotos().isEmpty()) {
StreamItemPhotoEntry firstPhoto = firstEntry.getPhotos().get(0);
photoUri = firstPhoto.getPhotoUri();
diff --git a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
index 106ff0e..b01316b 100644
--- a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
@@ -88,7 +88,7 @@
private View mDetailFragmentView;
private View mUpdatesFragmentView;
- private final Handler mHandler = new Handler();
+ private boolean mScrollToCurrentPage = false;
public ContactDetailFragmentCarousel(Context context) {
this(context, null);
@@ -144,6 +144,28 @@
resolveSize(screenHeight, heightMeasureSpec));
}
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ if (mScrollToCurrentPage) {
+ mScrollToCurrentPage = false;
+ // Use scrollTo() instead of smoothScrollTo() to prevent a visible flicker to the user
+ scrollTo(mCurrentPage == ABOUT_PAGE ? 0 : mAllowedHorizontalScrollLength, 0);
+ updateTouchInterceptors();
+ }
+ }
+
+ /**
+ * Set the current page that should be restored when the view is first laid out.
+ */
+ public void restoreCurrentPage(int pageIndex) {
+ setCurrentPage(pageIndex);
+ // It is only possible to scroll the view after onMeasure() has been called (where the
+ // allowed horizontal scroll length is determined). Hence, set a flag that will be read
+ // in onLayout() after the children and this view have finished being laid out.
+ mScrollToCurrentPage = true;
+ }
+
/**
* Set the current page. This auto-scrolls the carousel to the current page and dims out
* the non-selected page.
@@ -183,31 +205,13 @@
mEnableSwipe = enable;
if (mUpdatesFragmentView != null) {
mUpdatesFragmentView.setVisibility(enable ? View.VISIBLE : View.GONE);
+ mScrollToCurrentPage = true;
requestLayout();
invalidate();
}
- // This method could have been called before the view has been measured (i.e.
- // immediately after a rotation), so snap to edge only after the view is ready.
- postRunnableToSnapToEdge();
}
}
- /**
- * Snap to the currently selected page only once all the view setup and measurement has
- * completed (i.e. we need to know the allowed horizontal scroll width in order to
- * snap to the correct page).
- */
- private void postRunnableToSnapToEdge() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (isAttachedToWindow() && mAboutFragment != null && mUpdatesFragment != null) {
- snapToEdge();
- }
- }
- });
- }
-
public int getCurrentPage() {
return mCurrentPage;
}
@@ -302,8 +306,4 @@
}
return false;
}
-
- private boolean isAttachedToWindow() {
- return getWindowToken() != null;
- }
}
diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java
index 6b8829e..7a7f400 100644
--- a/src/com/android/contacts/detail/ContactDetailLayoutController.java
+++ b/src/com/android/contacts/detail/ContactDetailLayoutController.java
@@ -21,6 +21,8 @@
import com.android.contacts.R;
import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
+import android.animation.Animator;
+import android.animation.Animator.AnimatorListener;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.FragmentManager;
@@ -77,6 +79,7 @@
private ContactLoader.Result mContactData;
+ private boolean mTabCarouselIsAnimating;
private boolean mContactHasUpdates;
private LayoutMode mLayoutMode;
@@ -176,6 +179,7 @@
}
mTabCarousel.setListener(mTabCarouselListener);
+ mTabCarousel.restoreCurrentTab(currentPageIndex);
mDetailFragment.setVerticalScrollListener(
new VerticalScrollListener(TAB_INDEX_DETAIL));
mUpdatesFragment.setVerticalScrollListener(
@@ -211,7 +215,7 @@
mFragmentCarousel.setFragmentViews(mDetailFragmentView, mUpdatesFragmentView);
mFragmentCarousel.setFragments(mDetailFragment, mUpdatesFragment);
- mFragmentCarousel.setCurrentPage(currentPageIndex);
+ mFragmentCarousel.restoreCurrentPage(currentPageIndex);
break;
}
}
@@ -239,6 +243,7 @@
public void showEmptyState() {
switch (mLayoutMode) {
case FRAGMENT_CAROUSEL: {
+ mFragmentCarousel.setCurrentPage(0);
mFragmentCarousel.enableSwipe(false);
mDetailFragment.showEmptyState();
break;
@@ -323,6 +328,7 @@
break;
case FRAGMENT_CAROUSEL: {
// Disable swipe so only the detail fragment shows
+ mFragmentCarousel.setCurrentPage(0);
mFragmentCarousel.enableSwipe(false);
break;
}
@@ -449,12 +455,14 @@
mTabCarousel, "y", desiredValue).setDuration(75);
mTabCarouselAnimator.setInterpolator(AnimationUtils.loadInterpolator(
mActivity, android.R.anim.accelerate_decelerate_interpolator));
+ mTabCarouselAnimator.addListener(mTabCarouselAnimatorListener);
}
private void cancelTabCarouselAnimator() {
if (mTabCarouselAnimator != null) {
mTabCarouselAnimator.cancel();
mTabCarouselAnimator = null;
+ mTabCarouselIsAnimating = false;
}
}
};
@@ -478,6 +486,34 @@
}
}
+ /**
+ * This listener keeps track of whether the tab carousel animation is currently going on or not,
+ * in order to prevent other simultaneous changes to the Y position of the tab carousel which
+ * can cause flicker.
+ */
+ private final AnimatorListener mTabCarouselAnimatorListener = new AnimatorListener() {
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mTabCarouselIsAnimating = false;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mTabCarouselIsAnimating = false;
+ }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) {
+ mTabCarouselIsAnimating = true;
+ }
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ mTabCarouselIsAnimating = true;
+ }
+ };
+
private final ContactDetailTabCarousel.Listener mTabCarouselListener =
new ContactDetailTabCarousel.Listener() {
@@ -529,10 +565,11 @@
int totalItemCount) {
int currentPageIndex = mViewPager.getCurrentItem();
// Don't move the carousel if: 1) the contact does not have social updates because then
- // tab carousel must not be visible, 2) if the view pager is still being scrolled, or
- // 3) if the current page being viewed is not this one.
+ // tab carousel must not be visible, 2) if the view pager is still being scrolled,
+ // 3) if the current page being viewed is not this one, or 4) if the tab carousel
+ // is already being animated vertically.
if (!mContactHasUpdates || mViewPagerState != ViewPager.SCROLL_STATE_IDLE ||
- mPageIndex != currentPageIndex) {
+ mPageIndex != currentPageIndex || mTabCarouselIsAnimating) {
return;
}
// If the FIRST item is not visible on the screen, then the carousel must be pinned
diff --git a/src/com/android/contacts/detail/ContactDetailTabCarousel.java b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
index 8a51d81..9300b54 100644
--- a/src/com/android/contacts/detail/ContactDetailTabCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
@@ -63,6 +63,7 @@
private int mTabDisplayLabelHeight;
+ private boolean mScrollToCurrentTab = false;
private int mLastScrollPosition;
private int mAllowedHorizontalScrollLength = Integer.MIN_VALUE;
@@ -103,12 +104,7 @@
mUpdatesTab = (CarouselTab) findViewById(R.id.tab_update);
mUpdatesTab.setLabel(mContext.getString(R.string.contactDetailUpdates));
- // TODO: We can't always assume the "about" page will be the current page.
- mAboutTab.showSelectedState();
- mAboutTab.setAlphaLayerValue(0);
mAboutTab.enableTouchInterceptor(mAboutTabTouchInterceptListener);
-
- mUpdatesTab.setAlphaLayerValue(MAX_ALPHA);
mUpdatesTab.enableTouchInterceptor(mUpdatesTabTouchInterceptListener);
// Retrieve the photo view for the "about" tab
@@ -144,6 +140,15 @@
resolveSize(tabHeight, heightMeasureSpec));
}
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ if (mScrollToCurrentTab) {
+ mScrollToCurrentTab = false;
+ scrollTo(mCurrentTab == TAB_INDEX_ABOUT ? 0 : mAllowedHorizontalScrollLength, 0);
+ }
+ }
+
private final OnClickListener mAboutTabTouchInterceptListener = new OnClickListener() {
@Override
public void onClick(View v) {
@@ -174,6 +179,17 @@
}
/**
+ * Set the current tab that should be restored when the view is first laid out.
+ */
+ public void restoreCurrentTab(int position) {
+ setCurrentTab(position);
+ // It is only possible to scroll the view after onMeasure() has been called (where the
+ // allowed horizontal scroll length is determined). Hence, set a flag that will be read
+ // in onLayout() after the children and this view have finished being laid out.
+ mScrollToCurrentTab = true;
+ }
+
+ /**
* Restore the Y position of this view to the last manually requested value. This can be done
* after the parent has been re-laid out again, where this view's position could have been
* lost if the view laid outside its parent's bounds.
@@ -225,8 +241,6 @@
* Updates the tab selection.
*/
public void setCurrentTab(int position) {
- // TODO: Handle device rotation (saving and restoring state of the selected tab)
- // This will take more work because there is no tab carousel in phone landscape
switch (position) {
case TAB_INDEX_ABOUT:
mAboutTab.showSelectedState();
@@ -270,10 +284,10 @@
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mListener.onTouchDown();
- return false;
+ return true;
case MotionEvent.ACTION_UP:
mListener.onTouchUp();
- return false;
+ return true;
}
return super.onTouchEvent(event);
}
diff --git a/src/com/android/contacts/editor/ExternalRawContactEditorView.java b/src/com/android/contacts/editor/ExternalRawContactEditorView.java
index 8a18114..0a1ae74 100644
--- a/src/com/android/contacts/editor/ExternalRawContactEditorView.java
+++ b/src/com/android/contacts/editor/ExternalRawContactEditorView.java
@@ -27,6 +27,7 @@
import android.content.ContentUris;
import android.content.Context;
+import android.content.res.Resources;
import android.net.Uri;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
@@ -132,12 +133,14 @@
mDataSet = values.getAsString(RawContacts.DATA_SET);
if (isProfile) {
- mAccountNameTextView.setVisibility(View.GONE);
if (TextUtils.isEmpty(mAccountName)) {
+ mAccountNameTextView.setVisibility(View.GONE);
mAccountTypeTextView.setText(R.string.local_profile_title);
} else {
- mAccountTypeTextView.setText(
- mContext.getString(R.string.external_profile_title, mAccountName));
+ CharSequence accountType = type.getDisplayLabel(mContext);
+ mAccountTypeTextView.setText(mContext.getString(R.string.external_profile_title,
+ accountType));
+ mAccountNameTextView.setText(mAccountName);
}
} else {
CharSequence accountType = type.getDisplayLabel(mContext);
@@ -199,35 +202,42 @@
mEditExternallyButton.setVisibility(View.VISIBLE);
}
+ final Resources res = mContext.getResources();
// Phones
ArrayList<ValuesDelta> phones = state.getMimeEntries(Phone.CONTENT_ITEM_TYPE);
if (phones != null) {
- for (ValuesDelta phone : phones) {
- View field = mInflater.inflate(
- R.layout.item_read_only_field, mGeneral, false);
- TextView v;
- v = (TextView) field.findViewById(R.id.kind_title);
- v.setText(mContext.getText(R.string.phoneLabelsGroup));
- v = (TextView) field.findViewById(R.id.data);
- v.setText(PhoneNumberUtils.formatNumber(phone.getAsString(Phone.NUMBER),
+ for (int i = 0; i < phones.size(); i++) {
+ ValuesDelta phone = phones.get(i);
+ final String phoneNumber = PhoneNumberUtils.formatNumber(
+ phone.getAsString(Phone.NUMBER),
phone.getAsString(Phone.NORMALIZED_NUMBER),
- ContactsUtils.getCurrentCountryIso(getContext())));
- mGeneral.addView(field);
+ ContactsUtils.getCurrentCountryIso(getContext()));
+ final CharSequence phoneType;
+ if (phone.containsKey(Phone.TYPE)) {
+ phoneType = Phone.getTypeLabel(
+ res, phone.getAsInteger(Phone.TYPE), phone.getAsString(Phone.LABEL));
+ } else {
+ phoneType = null;
+ }
+ bindData(mContext.getText(R.string.phoneLabelsGroup),
+ phoneNumber, phoneType, i == 0);
}
}
// Emails
ArrayList<ValuesDelta> emails = state.getMimeEntries(Email.CONTENT_ITEM_TYPE);
if (emails != null) {
- for (ValuesDelta email : emails) {
- View field = mInflater.inflate(
- R.layout.item_read_only_field, mGeneral, false);
- TextView v;
- v = (TextView) field.findViewById(R.id.kind_title);
- v.setText(mContext.getText(R.string.emailLabelsGroup));
- v = (TextView) field.findViewById(R.id.data);
- v.setText(email.getAsString(Email.DATA));
- mGeneral.addView(field);
+ for (int i = 0; i < emails.size(); i++) {
+ ValuesDelta email = emails.get(i);
+ final String emailAddress = email.getAsString(Email.DATA);
+ final CharSequence emailType;
+ if (email.containsKey(Email.TYPE)) {
+ emailType = Email.getTypeLabel(
+ res, email.getAsInteger(Email.TYPE), email.getAsString(Email.LABEL));
+ } else {
+ emailType = null;
+ }
+ bindData(mContext.getText(R.string.emailLabelsGroup), emailAddress, null, i == 0);
}
}
@@ -239,6 +249,28 @@
}
}
+ private void bindData(
+ CharSequence titleText, CharSequence data, CharSequence type, boolean isFirstEntry) {
+ final View field = mInflater.inflate(R.layout.item_read_only_field, mGeneral, false);
+ if (isFirstEntry) {
+ final TextView titleView = (TextView) field.findViewById(R.id.kind_title);
+ titleView.setText(titleText);
+ } else {
+ View titleContainer = field.findViewById(R.id.kind_title_layout);
+ titleContainer.setVisibility(View.GONE);
+ }
+ final TextView dataView = (TextView) field.findViewById(R.id.data);
+ dataView.setText(data);
+ final TextView typeView = (TextView) field.findViewById(R.id.type);
+ if (!TextUtils.isEmpty(type)) {
+ typeView.setText(type);
+ } else {
+ typeView.setVisibility(View.GONE);
+ }
+
+ mGeneral.addView(field);
+ }
+
@Override
public long getRawContactId() {
return mRawContactId;
diff --git a/src/com/android/contacts/editor/RawContactEditorView.java b/src/com/android/contacts/editor/RawContactEditorView.java
index bac6217..118ca26 100644
--- a/src/com/android/contacts/editor/RawContactEditorView.java
+++ b/src/com/android/contacts/editor/RawContactEditorView.java
@@ -178,13 +178,15 @@
// Fill in the account info
if (isProfile) {
- mAccountNameTextView.setVisibility(View.GONE);
String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
if (TextUtils.isEmpty(accountName)) {
+ mAccountNameTextView.setVisibility(View.GONE);
mAccountTypeTextView.setText(R.string.local_profile_title);
} else {
- mAccountTypeTextView.setText(
- mContext.getString(R.string.external_profile_title, accountName));
+ CharSequence accountType = type.getDisplayLabel(mContext);
+ mAccountTypeTextView.setText(mContext.getString(R.string.external_profile_title,
+ accountType));
+ mAccountNameTextView.setText(accountName);
}
} else {
String accountName = values.getAsString(RawContacts.ACCOUNT_NAME);
diff --git a/src/com/android/contacts/interactions/ImportExportDialogFragment.java b/src/com/android/contacts/interactions/ImportExportDialogFragment.java
index a6a37ef..078f63e 100644
--- a/src/com/android/contacts/interactions/ImportExportDialogFragment.java
+++ b/src/com/android/contacts/interactions/ImportExportDialogFragment.java
@@ -136,30 +136,32 @@
// TODO move the query into a loader and do this in a background thread
final Cursor cursor = getActivity().getContentResolver().query(Contacts.CONTENT_URI,
LOOKUP_PROJECTION, Contacts.IN_VISIBLE_GROUP + "!=0", null, null);
- try {
- if (!cursor.moveToFirst()) {
- Toast.makeText(getActivity(), R.string.share_error, Toast.LENGTH_SHORT).show();
- return;
- }
+ if (cursor != null) {
+ try {
+ if (!cursor.moveToFirst()) {
+ Toast.makeText(getActivity(), R.string.share_error, Toast.LENGTH_SHORT).show();
+ return;
+ }
- StringBuilder uriListBuilder = new StringBuilder();
- int index = 0;
- while (cursor.moveToNext()) {
- if (index != 0)
- uriListBuilder.append(':');
- uriListBuilder.append(cursor.getString(0));
- index++;
- }
- Uri uri = Uri.withAppendedPath(
- Contacts.CONTENT_MULTI_VCARD_URI,
- Uri.encode(uriListBuilder.toString()));
+ StringBuilder uriListBuilder = new StringBuilder();
+ int index = 0;
+ do {
+ if (index != 0)
+ uriListBuilder.append(':');
+ uriListBuilder.append(cursor.getString(0));
+ index++;
+ } while (cursor.moveToNext());
+ Uri uri = Uri.withAppendedPath(
+ Contacts.CONTENT_MULTI_VCARD_URI,
+ Uri.encode(uriListBuilder.toString()));
- final Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType(Contacts.CONTENT_VCARD_TYPE);
- intent.putExtra(Intent.EXTRA_STREAM, uri);
- getActivity().startActivity(intent);
- } finally {
- cursor.close();
+ final Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType(Contacts.CONTENT_VCARD_TYPE);
+ intent.putExtra(Intent.EXTRA_STREAM, uri);
+ getActivity().startActivity(intent);
+ } finally {
+ cursor.close();
+ }
}
}
diff --git a/src/com/android/contacts/list/ContactListItemView.java b/src/com/android/contacts/list/ContactListItemView.java
index 4b86295..7e0940f 100644
--- a/src/com/android/contacts/list/ContactListItemView.java
+++ b/src/com/android/contacts/list/ContactListItemView.java
@@ -121,7 +121,6 @@
private TextView mCountView;
private ImageView mPresenceIcon;
- private ColorStateList mPrimaryTextColor;
private ColorStateList mSecondaryTextColor;
private char[] mHighlightedPrefix;
@@ -252,8 +251,9 @@
Color.GREEN));
a.recycle();
- mPrimaryTextColor = getResources().getColorStateList(R.color.list_primary_text_color);
- mSecondaryTextColor = getResources().getColorStateList(R.color.list_secondary_text_color);
+ a = getContext().obtainStyledAttributes(android.R.styleable.Theme);
+ mSecondaryTextColor = a.getColorStateList(android.R.styleable.Theme_textColorSecondary);
+ a.recycle();
mHorizontalDividerHeight = mHorizontalDividerDrawable.getIntrinsicHeight();
@@ -766,7 +766,6 @@
mNameTextView.setSingleLine(true);
mNameTextView.setEllipsize(getTextEllipsis());
mNameTextView.setTextAppearance(mContext, android.R.style.TextAppearance_Medium);
- mNameTextView.setTextColor(mPrimaryTextColor);
// Manually call setActivated() since this view may be added after the first
// setActivated() call toward this whole item view.
mNameTextView.setActivated(isActivated());
@@ -826,7 +825,6 @@
mPhoneticNameTextView.setEllipsize(getTextEllipsis());
mPhoneticNameTextView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
mPhoneticNameTextView.setTypeface(mPhoneticNameTextView.getTypeface(), Typeface.BOLD);
- mPhoneticNameTextView.setTextColor(mPrimaryTextColor);
mPhoneticNameTextView.setActivated(isActivated());
addView(mPhoneticNameTextView);
}
@@ -873,7 +871,6 @@
mLabelView.setEllipsize(getTextEllipsis());
mLabelView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
mLabelView.setTypeface(mLabelView.getTypeface(), Typeface.BOLD);
- mLabelView.setTextColor(mPrimaryTextColor);
mLabelView.setActivated(isActivated());
addView(mLabelView);
}
@@ -905,7 +902,6 @@
mDataView.setSingleLine(true);
mDataView.setEllipsize(getTextEllipsis());
mDataView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
- mDataView.setTextColor(mPrimaryTextColor);
mDataView.setActivated(isActivated());
addView(mDataView);
}
@@ -936,7 +932,6 @@
mSnippetView.setEllipsize(getTextEllipsis());
mSnippetView.setTextAppearance(mContext, android.R.style.TextAppearance_Small);
mSnippetView.setTypeface(mSnippetView.getTypeface(), Typeface.BOLD);
- mSnippetView.setTextColor(mPrimaryTextColor);
mSnippetView.setActivated(isActivated());
addView(mSnippetView);
}
diff --git a/src/com/android/contacts/model/BaseAccountType.java b/src/com/android/contacts/model/BaseAccountType.java
index eee7241..dae09b2 100644
--- a/src/com/android/contacts/model/BaseAccountType.java
+++ b/src/com/android/contacts/model/BaseAccountType.java
@@ -65,7 +65,7 @@
public BaseAccountType() {
this.accountType = null;
this.dataSet = null;
- this.titleRes = R.string.local_profile_title;
+ this.titleRes = R.string.account_phone;
this.iconRes = R.mipmap.ic_launcher_contacts;
}
diff --git a/src/com/android/contacts/model/EntityDelta.java b/src/com/android/contacts/model/EntityDelta.java
index 97ab347..a045eb4 100644
--- a/src/com/android/contacts/model/EntityDelta.java
+++ b/src/com/android/contacts/model/EntityDelta.java
@@ -561,6 +561,11 @@
return mAfter;
}
+ public boolean containsKey(String key) {
+ return ((mAfter != null && mAfter.containsKey(key)) ||
+ (mBefore != null && mBefore.containsKey(key)));
+ }
+
public String getAsString(String key) {
if (mAfter != null && mAfter.containsKey(key)) {
return mAfter.getAsString(key);
diff --git a/src/com/android/contacts/model/FallbackAccountType.java b/src/com/android/contacts/model/FallbackAccountType.java
index a40828e..8bb3992 100644
--- a/src/com/android/contacts/model/FallbackAccountType.java
+++ b/src/com/android/contacts/model/FallbackAccountType.java
@@ -25,7 +25,7 @@
public FallbackAccountType(Context context) {
this.accountType = null;
this.dataSet = null;
- this.titleRes = R.string.local_profile_title;
+ this.titleRes = R.string.account_phone;
this.iconRes = R.mipmap.ic_launcher_contacts;
this.resPackageName = null;
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
index 80f7862..8d549a7 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackFragment.java
@@ -395,7 +395,6 @@
@Override
public void setSpeakerPhoneOn(boolean on) {
- getAudioManager().setMode(AudioManager.MODE_IN_CALL);
getAudioManager().setSpeakerphoneOn(on);
if (on) {
mPlaybackSpeakerphone.setImageResource(R.drawable.ic_sound_holo_dark);
@@ -403,6 +402,14 @@
mPlaybackSpeakerphone.setImageResource(R.drawable.ic_sound_holo_dark);
}
}
+
+ @Override
+ public void setVolumeControlStream(int streamType) {
+ Activity activity = mActivityReference.get();
+ if (activity != null) {
+ activity.setVolumeControlStream(streamType);
+ }
+ }
}
/**
diff --git a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
index 6eb541d..f8e497d 100644
--- a/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
+++ b/src/com/android/contacts/voicemail/VoicemailPlaybackPresenter.java
@@ -27,6 +27,7 @@
import android.content.Context;
import android.database.ContentObserver;
+import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
@@ -60,6 +61,9 @@
@NotThreadSafe
@VisibleForTesting
public class VoicemailPlaybackPresenter {
+ /** The stream used to playback voicemail. */
+ private static final int PLAYBACK_STREAM = AudioManager.STREAM_VOICE_CALL;
+
/** Contract describing the behaviour we need from the ui we are controlling. */
public interface PlaybackView {
Context getDataSourceContext();
@@ -89,6 +93,7 @@
void unregisterContentObserver(ContentObserver observer);
void enableProximitySensor();
void disableProximitySensor();
+ void setVolumeControlStream(int streamType);
}
/** The enumeration of {@link AsyncTask} objects we use in this class. */
@@ -179,6 +184,7 @@
}
public void onCreate(Bundle bundle) {
+ mView.setVolumeControlStream(PLAYBACK_STREAM);
checkThatWeHaveContent();
}
@@ -304,6 +310,7 @@
try {
mPlayer.reset();
mPlayer.setDataSource(mView.getDataSourceContext(), mVoicemailUri);
+ mPlayer.setAudioStreamType(PLAYBACK_STREAM);
mPlayer.prepare();
return null;
} catch (IOException e) {
@@ -428,6 +435,7 @@
try {
mPlayer.reset();
mPlayer.setDataSource(mView.getDataSourceContext(), mVoicemailUri);
+ mPlayer.setAudioStreamType(PLAYBACK_STREAM);
mPlayer.prepare();
mDuration.set(mPlayer.getDuration());
int startPosition = constrain(clipPositionInMillis, 0, mDuration.get());
diff --git a/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java b/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
index 9e481f8..d88b5d3 100644
--- a/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
+++ b/src/com/android/contacts/voicemail/VoicemailStatusHelperImpl.java
@@ -221,8 +221,13 @@
Uri actionUri = null;
if (action == Action.CALL_VOICEMAIL) {
actionUri = UriUtils.parseUriOrNull(cursor.getString(VOICEMAIL_ACCESS_URI_INDEX));
+ // Even if actionUri is null, it is still be useful to show the notification.
} else if (action == Action.CONFIGURE_VOICEMAIL) {
actionUri = UriUtils.parseUriOrNull(cursor.getString(SETTINGS_URI_INDEX));
+ // If there is no settings URI, there is no point in showing the notification.
+ if (actionUri == null) {
+ return null;
+ }
}
return new MessageStatusWithPriority(
new StatusMessage(sourcePackage, overallState.getCallLogMessageId(),