Merge "Remove ContactDetailLayoutController's social code"
diff --git a/res/layout-land/contact_detail_container.xml b/res/layout-land/contact_detail_container.xml
deleted file mode 100644
index fc401b7..0000000
--- a/res/layout-land/contact_detail_container.xml
+++ /dev/null
@@ -1,26 +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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <com.android.contacts.detail.ContactDetailFragmentCarousel
- android:id="@+id/fragment_carousel"
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
-</FrameLayout>
\ No newline at end of file
diff --git a/res/layout-sw600dp-land/contact_detail_container.xml b/res/layout-sw600dp-land/contact_detail_container.xml
deleted file mode 100644
index 3597d9f..0000000
--- a/res/layout-sw600dp-land/contact_detail_container.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <com.android.contacts.detail.ContactDetailFragmentCarousel
- android:id="@+id/fragment_carousel"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_marginLeft="16dip"
- android:layout_marginStart="16dip"/>
-
-</FrameLayout>
diff --git a/res/layout-sw600dp-land/detail_header_contact_with_updates.xml b/res/layout-sw600dp-land/detail_header_contact_with_updates.xml
deleted file mode 100644
index 6476300..0000000
--- a/res/layout-sw600dp-land/detail_header_contact_with_updates.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact has social updates. The
- entry shows the contact's basic info and maintains vertical padding to ensure that the first
- contact detail is visible (and below the tab carousel). The photo is not displayed here
- because it will be shown in the tab carousel.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="8dip"
- android:orientation="horizontal">
-
- <include layout="@layout/photo_selector_view"
- android:layout_width="@dimen/detail_contact_photo_size"
- android:layout_height="@dimen/detail_contact_photo_size" />
-
- <LinearLayout
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="vertical"
- android:paddingLeft="16dip"
- android:paddingRight="4dip"
- android:paddingStart="16dip"
- android:paddingEnd="4dip">
-
- <TextView
- android:id="@+id/name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textSize="@dimen/detail_header_name_text_size" />
-
- <TextView
- android:id="@+id/company"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondary" />
-
- </LinearLayout>
-
- <include
- layout="@layout/favorites_star" />
-
-</LinearLayout>
diff --git a/res/layout-sw600dp/contact_detail_container.xml b/res/layout-sw600dp/contact_detail_container.xml
deleted file mode 100644
index d7accaf..0000000
--- a/res/layout-sw600dp/contact_detail_container.xml
+++ /dev/null
@@ -1,39 +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.
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <android.support.v4.view.ViewPager
- android:id="@+id/pager"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- <include
- android:id="@+id/tab_carousel"
- layout="@layout/contact_detail_tab_carousel"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"/>
-
-</RelativeLayout>
\ No newline at end of file
diff --git a/res/layout-sw600dp/detail_header_contact_with_updates.xml b/res/layout-sw600dp/detail_header_contact_with_updates.xml
deleted file mode 100644
index 06b82dd..0000000
--- a/res/layout-sw600dp/detail_header_contact_with_updates.xml
+++ /dev/null
@@ -1,77 +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.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact has social updates. The
- entry shows the contact's basic info and maintains vertical padding to ensure that the first
- contact detail is visible (and below the tab carousel). The photo is not displayed here
- because it will be shown in the tab carousel.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:layout_marginTop="30dip"
- android:paddingBottom="16dip">
-
- <!-- Add a first item that gives us enough space to show the carousel -->
- <view
- class="com.android.contacts.common.widget.ProportionalLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- ex:ratio="0.6667"
- ex:direction="widthToHeight">
-
- <!-- Put a dummy view here because the ProportionalLayout requires one -->
- <View
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- </view>
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingTop="8dip"
- android:paddingEnd="8dip" >
-
- <TextView
- android:id="@+id/name"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:paddingStart="8dip"
- android:paddingEnd="24dip"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textSize="@dimen/detail_header_name_text_size" />
-
- <include
- layout="@layout/favorites_star" />
-
- </LinearLayout>
-
- <TextView
- android:id="@+id/company"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="8dip"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondary" />
-
-</LinearLayout>
diff --git a/res/layout-sw600dp/updates_header_contact.xml b/res/layout-sw600dp/updates_header_contact.xml
deleted file mode 100644
index e95f1dd..0000000
--- a/res/layout-sw600dp/updates_header_contact.xml
+++ /dev/null
@@ -1,58 +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.
--->
-
-<!--
- This is a header entry in the contact updates list.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <!-- This blank view pushes the other content down because of the tab carousel -->
- <view
- class="com.android.contacts.common.widget.ProportionalLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="8dip"
- ex:ratio="0.6667"
- ex:direction="widthToHeight">
-
- <!-- Put a dummy view here because the ProportionalLayout requires one -->
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- </view>
-
- <!-- "Recent updates" header text -->
- <TextView
- style="?android:attr/listSeparatorTextViewStyle"
- android:layout_height="32dip"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
- android:paddingStart="8dip"
- android:paddingEnd="8dip"
- android:background="@drawable/list_section_divider_holo_custom"
- android:text="@string/recent"
- android:textColor="@color/people_app_theme_color"
- android:textAllCaps="true"
- android:singleLine="true"
- android:ellipsize="end" />
-
-</LinearLayout>
diff --git a/res/layout-sw720dp-land/contact_detail_container.xml b/res/layout-sw720dp-land/contact_detail_container.xml
deleted file mode 100644
index 8180e92..0000000
--- a/res/layout-sw720dp-land/contact_detail_container.xml
+++ /dev/null
@@ -1,60 +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.
--->
-
-<!--
- Two-column layout for a contact with social updates. If the contact does not
- have social updates, then the second fragment container will just be hidden.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scrollbars="none"
- android:orientation="horizontal"
- android:baselineAligned="false">
-
- <!--
- Container for the "About" fragment on the contact card for a contact
- with social updates. This view ID must match with a view ID in the layout
- that is used after an orientation change.
- -->
- <FrameLayout
- android:id="@+id/about_fragment_container"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="3" />
-
- <!-- Vertical divider -->
- <View
- android:layout_width="2dip"
- android:layout_height="match_parent"
- android:background="?android:attr/listDivider"
- />
-
- <!--
- Container for the "Updates" fragment on the contact card for a contact
- with social updates. This view ID must match with a view ID in the layout
- that is used after an orientation change.
- -->
- <FrameLayout
- android:id="@+id/updates_fragment_container"
- android:layout_width="0dip"
- android:layout_weight="2"
- android:layout_height="match_parent"
- android:visibility="gone" />
-
-</LinearLayout>
diff --git a/res/layout-sw720dp-land/detail_header_contact_with_updates.xml b/res/layout-sw720dp-land/detail_header_contact_with_updates.xml
deleted file mode 100644
index 268b51a..0000000
--- a/res/layout-sw720dp-land/detail_header_contact_with_updates.xml
+++ /dev/null
@@ -1,63 +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.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact has social updates. The
- entry shows the contact's basic info and maintains vertical padding to ensure that the first
- contact detail is visible (and below the tab carousel). The photo is not displayed here
- because it will be shown in the tab carousel.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingBottom="8dip"
- android:orientation="horizontal">
-
- <include layout="@layout/photo_selector_view"
- android:layout_width="@dimen/detail_contact_photo_size"
- android:layout_height="@dimen/detail_contact_photo_size" />
-
- <LinearLayout
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="vertical"
- android:paddingStart="16dip"
- android:paddingEnd="4dip">
-
- <TextView
- android:id="@+id/name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textSize="@dimen/detail_header_name_text_size" />
-
- <TextView
- android:id="@+id/company"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="?android:attr/textColorSecondary" />
-
- </LinearLayout>
-
- <include
- layout="@layout/favorites_star" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/carousel_about_tab.xml b/res/layout/carousel_about_tab.xml
deleted file mode 100644
index 8026f37..0000000
--- a/res/layout/carousel_about_tab.xml
+++ /dev/null
@@ -1,80 +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.
--->
-
-<view
- xmlns:android="http://schemas.android.com/apk/res/android"
- class="com.android.contacts.detail.CarouselTab"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1">
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <ImageView android:id="@+id/photo"
- android:scaleType="centerCrop"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"/>
-
- <View android:id="@+id/photo_overlay"
- android:background="?android:attr/selectableItemBackground"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"/>
-
- <!-- Transparent view to overlay on the contact's photo
- (to allow white text to appear over a white photo). -->
- <View android:id="@+id/label_background"
- android:layout_width="match_parent"
- android:layout_height="@dimen/detail_tab_carousel_tab_label_height"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentBottom="true"
- android:background="#7F000000" />
-
- <View
- android:id="@+id/alpha_overlay"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:layout_marginBottom="@dimen/detail_tab_carousel_tab_label_height"/>
-
- <TextView
- android:id="@+id/label"
- android:layout_width="match_parent"
- android:layout_height="@dimen/detail_tab_carousel_tab_label_height"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentBottom="true"
- android:paddingLeft="@dimen/detail_tab_carousel_tab_label_indent"
- android:paddingStart="@dimen/detail_tab_carousel_tab_label_indent"
- android:singleLine="true"
- android:gravity="left|center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/detail_tab_carousel_tab_label_color"
- style="@android:style/Widget.Holo.ActionBar.TabView" />
-
- </RelativeLayout>
-
-</view>
diff --git a/res/layout/carousel_updates_tab.xml b/res/layout/carousel_updates_tab.xml
deleted file mode 100644
index 0bd5cbd..0000000
--- a/res/layout/carousel_updates_tab.xml
+++ /dev/null
@@ -1,98 +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.
--->
-
-<!--
- TODO: Collapse carousel_about_tab with carousel_updates_tab into 1 XML that
- handles all cases when updates fragment is more finalized.
--->
-<view
- xmlns:android="http://schemas.android.com/apk/res/android"
- class="com.android.contacts.detail.CarouselTab"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:background="@drawable/bg_people_updates_holo">
-
- <RelativeLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
-
- <ImageView android:id="@+id/status_photo"
- android:scaleType="centerCrop"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:visibility="gone" />
-
- <!-- Transparent view to overlay on the update photo
- (to allow white text to appear over a white photo). -->
- <View android:id="@+id/label_background"
- android:layout_width="match_parent"
- android:layout_height="@dimen/detail_tab_carousel_tab_label_height"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentBottom="true"
- android:layout_above="@id/status_photo"
- android:background="#7F000000" />
-
- <TextView android:id="@+id/status"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_above="@id/label"
- android:gravity="center_vertical"
- android:paddingLeft="@dimen/detail_update_tab_side_padding"
- android:paddingRight="@dimen/detail_update_tab_side_padding"
- android:paddingStart="@dimen/detail_update_tab_side_padding"
- android:paddingEnd="@dimen/detail_update_tab_side_padding"
- android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="@color/detail_update_tab_text_color"
- android:textStyle="bold"
- android:maxLines="@integer/updates_tab_snippet_max_lines"
- android:ellipsize="end" />
-
- <View
- android:id="@+id/alpha_overlay"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentTop="true"
- android:layout_marginBottom="@dimen/detail_tab_carousel_tab_label_height"/>
-
- <TextView
- android:id="@+id/label"
- android:layout_width="match_parent"
- android:layout_height="@dimen/detail_tab_carousel_tab_label_height"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_alignParentBottom="true"
- android:layout_above="@id/status_photo"
- android:paddingLeft="@dimen/detail_tab_carousel_tab_label_indent"
- android:paddingStart="@dimen/detail_tab_carousel_tab_label_indent"
- android:singleLine="true"
- android:gravity="start|center_vertical"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textColor="@color/detail_tab_carousel_tab_label_color"
- style="@android:style/Widget.Holo.ActionBar.TabView" />
-
- </RelativeLayout>
-
-</view>
diff --git a/res/layout/contact_detail_container.xml b/res/layout/contact_detail_container.xml
index f6b3438..910d684 100644
--- a/res/layout/contact_detail_container.xml
+++ b/res/layout/contact_detail_container.xml
@@ -14,35 +14,12 @@
limitations under the License.
-->
-<!--
- Layout for the contact card page. If the contact has social updates, then
- the ViewPager and ContactDetailTabCarousel are shown together. If there
- aren't any social updates, then just the ContactDetailFragment will be
- shown. We include all 3 views even though they are never shown
- simultaneously because this layout is reused but set with different data
- each time (i.e. on a tablet).
--->
-
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<!-- Layout for the contact card page. -->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
-
- <android.support.v4.view.ViewPager
- android:id="@+id/pager"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
- <include
- android:id="@+id/tab_carousel"
- layout="@layout/contact_detail_tab_carousel"
- android:layout_alignParentTop="true"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"/>
-
-</RelativeLayout>
\ No newline at end of file
+ <fragment android:name="com.android.contacts.detail.ContactDetailFragment"
+ android:id="@+id/contact_detail_about_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/contact_detail_fragment_carousel.xml b/res/layout/contact_detail_fragment_carousel.xml
deleted file mode 100644
index 0695511..0000000
--- a/res/layout/contact_detail_fragment_carousel.xml
+++ /dev/null
@@ -1,54 +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.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scrollbars="none"
- android:orientation="horizontal"
- android:baselineAligned="false">
-
- <!--
- Container for the "About" page fragment on the contact card for a contact
- with social updates. This view ID must match with a view ID in the layout
- that is used after an orientation change.
- -->
- <view
- class="com.android.contacts.widget.FrameLayoutWithOverlay"
- android:id="@+id/about_fragment_container"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:focusable="true"
- android:focusableInTouchMode="true" />
-
- <!--
- Container for the "Updates" page fragment on the contact card for a contact
- with social updates. This view ID must match with a view ID in the layout
- that is used after an orientation change.
- -->
- <view
- class="com.android.contacts.widget.FrameLayoutWithOverlay"
- android:id="@+id/updates_fragment_container"
- android:layout_width="0dip"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:visibility="gone" />
-
-</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/contact_detail_tab_carousel.xml b/res/layout/contact_detail_tab_carousel.xml
deleted file mode 100644
index 711a6c3..0000000
--- a/res/layout/contact_detail_tab_carousel.xml
+++ /dev/null
@@ -1,71 +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.
--->
-
-<view
- xmlns:android="http://schemas.android.com/apk/res/android"
- class="com.android.contacts.detail.ContactDetailTabCarousel"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:scrollbars="none"
- android:fadingEdge="none">
-
- <LinearLayout
- android:id="@+id/tab_and_shadow_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
-
- <LinearLayout
- android:id="@+id/tab_container"
- android:layout_width="match_parent"
- android:layout_height="0dip"
- android:layout_weight="1"
- android:orientation="horizontal"
- android:baselineAligned="false">
-
- <!-- "About" tab -->
- <include
- android:id="@+id/tab_about"
- layout="@layout/carousel_about_tab" />
-
- <!-- Vertical divider -->
- <View
- android:id="@+id/tab_divider"
- android:layout_width="1dip"
- android:layout_height="match_parent"
- android:background="@android:color/white"/>
-
- <!-- "Updates" tab -->
- <include
- android:id="@+id/tab_update"
- layout="@layout/carousel_updates_tab" />
-
- </LinearLayout>
-
- <!--
- Shadow below the carousel. The ContactDetailTabCarousel increases its height to
- account for this shadow, and the class assumes the height of this shadow to be
- @dimen/detail_contact_photo_shadow_height.
- -->
- <View
- android:id="@+id/shadow"
- android:layout_width="match_parent"
- android:layout_height="@dimen/detail_contact_photo_shadow_height"
- android:background="?android:attr/windowContentOverlay"/>
-
- </LinearLayout>
-
-</view>
diff --git a/res/layout/detail_header_contact_with_updates.xml b/res/layout/detail_header_contact_with_updates.xml
deleted file mode 100644
index dc4cf8b..0000000
--- a/res/layout/detail_header_contact_with_updates.xml
+++ /dev/null
@@ -1,39 +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.
--->
-
-<!--
- This is a header entry in the contact details list for when the contact has social updates. The
- entry maintains vertical padding to ensure that the first contact detail is visible (and below
- the tab carousel). No information has to be displayed in this header.
- The FrameLayout is used to apply additional padding which is needed for the shadow
--->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <view
- class="com.android.contacts.common.widget.ProportionalLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/detail_contact_photo_shadow_height"
- ex:ratio="0.5"
- ex:direction="widthToHeight">
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
- </view>
-</FrameLayout>
diff --git a/res/layout/updates_header_contact.xml b/res/layout/updates_header_contact.xml
deleted file mode 100644
index 66cdac4..0000000
--- a/res/layout/updates_header_contact.xml
+++ /dev/null
@@ -1,68 +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.
--->
-
-<!--
- This is a header entry in the contact updates list.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:ex="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
-
- <!-- This blank view pushes the other content down because of the tab carousel -->
- <view
- class="com.android.contacts.common.widget.ProportionalLayout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginBottom="@dimen/detail_contact_photo_shadow_height"
- ex:ratio="0.5"
- ex:direction="widthToHeight">
-
- <!-- Put a dummy view here because the ProportionalLayout requires one -->
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"/>
-
- </view>
-
- <!-- "Recent" header text -->
- <FrameLayout
- android:layout_width="match_parent"
- android:layout_height="32dip"
- android:paddingLeft="16dip"
- android:paddingRight="16dip"
- android:paddingStart="16dip"
- android:paddingEnd="16dip"
- android:focusable="false">
-
- <TextView
- style="?android:attr/listSeparatorTextViewStyle"
- android:paddingLeft="8dip"
- android:paddingRight="8dip"
- android:paddingStart="8dip"
- android:paddingEnd="8dip"
- android:background="@drawable/list_section_divider_holo_custom"
- android:text="@string/recent"
- android:textColor="@color/people_app_theme_color"
- android:textAllCaps="true"
- android:singleLine="true"
- android:ellipsize="end" />
-
- </FrameLayout>
-
-</LinearLayout>
diff --git a/res/values-sw600dp/donottranslate_config.xml b/res/values-sw600dp/donottranslate_config.xml
index a8d428c..bbf37c1 100644
--- a/res/values-sw600dp/donottranslate_config.xml
+++ b/res/values-sw600dp/donottranslate_config.xml
@@ -23,6 +23,4 @@
<bool name="show_home_icon">true</bool>
<bool name="config_browse_list_show_images">false</bool>
<bool name="config_browse_list_reverse_images">false</bool>
- <item name="tab_width_screen_width_percentage" type="fraction">66.67%</item>
- <item name="tab_height_screen_width_percentage" type="fraction">66.67%</item>
</resources>
diff --git a/res/values/donottranslate_config.xml b/res/values/donottranslate_config.xml
index b74d8ce..dcf3039 100644
--- a/res/values/donottranslate_config.xml
+++ b/res/values/donottranslate_config.xml
@@ -47,14 +47,6 @@
-->
<bool name="config_show_group_action_in_action_bar">false</bool>
- <!-- Width of a tab in the tab carousel as a percentage of the current screen width on the
- contact detail page -->
- <item name="tab_width_screen_width_percentage" type="fraction">75%</item>
-
- <!-- Height of the tab carousel as a percentage of the current screen width on the
- contact detail page -->
- <item name="tab_height_screen_width_percentage" type="fraction">50%</item>
-
<!-- Help URL pointing to main TOC for People. This is intentionally empty because
the overlay will fill this in during build time. -->
<string name="help_url_people_main"></string>
diff --git a/src/com/android/contacts/activities/PeopleActivity.java b/src/com/android/contacts/activities/PeopleActivity.java
index aa4cdf7..a117f5e 100644
--- a/src/com/android/contacts/activities/PeopleActivity.java
+++ b/src/com/android/contacts/activities/PeopleActivity.java
@@ -55,7 +55,6 @@
import com.android.contacts.activities.ActionBarAdapter.TabState;
import com.android.contacts.detail.ContactDetailFragment;
import com.android.contacts.detail.ContactDetailLayoutController;
-import com.android.contacts.detail.ContactDetailUpdatesFragment;
import com.android.contacts.detail.ContactLoaderFragment;
import com.android.contacts.detail.ContactLoaderFragment.ContactLoaderFragmentListener;
import com.android.contacts.common.ContactsUtils;
@@ -239,7 +238,7 @@
* However, there are special fragments which may not be in the layout, so we have to do the
* initialization here.
* The target fragments are:
- * - {@link ContactDetailFragment} and {@link ContactDetailUpdatesFragment}: They may not be
+ * - {@link ContactDetailFragment}: This may not be available
* in the layout depending on the configuration. (i.e. portrait)
* - {@link ContactsUnavailableFragment}: We always create it at runtime.
*/
diff --git a/src/com/android/contacts/detail/CarouselTab.java b/src/com/android/contacts/detail/CarouselTab.java
deleted file mode 100644
index 09e097a..0000000
--- a/src/com/android/contacts/detail/CarouselTab.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.detail;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewPropertyAnimator;
-import android.widget.TextView;
-
-import com.android.contacts.R;
-import com.android.contacts.widget.FrameLayoutWithOverlay;
-
-/**
- * This is a tab in the {@link ContactDetailTabCarousel}.
- */
-public class CarouselTab extends FrameLayoutWithOverlay {
-
- private static final String TAG = CarouselTab.class.getSimpleName();
-
- private static final long FADE_TRANSITION_TIME = 150;
-
- private TextView mLabelView;
- private View mLabelBackgroundView;
-
- /**
- * This view adds an alpha layer over the entire tab (except for the label).
- */
- private View mAlphaLayer;
-
- public CarouselTab(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
-
- mLabelView = (TextView) findViewById(R.id.label);
- mLabelBackgroundView = findViewById(R.id.label_background);
- mAlphaLayer = findViewById(R.id.alpha_overlay);
- setAlphaLayer(mAlphaLayer);
- }
-
- public void setLabel(String label) {
- mLabelView.setText(label);
- }
-
- public void showSelectedState() {
- mLabelView.setSelected(true);
- }
-
- public void showDeselectedState() {
- mLabelView.setSelected(false);
- }
-
- public void fadeInLabelViewAnimator(int startDelay, boolean fadeBackground) {
- final ViewPropertyAnimator labelAnimator = mLabelView.animate();
- mLabelView.setAlpha(0.0f);
- labelAnimator.alpha(1.0f);
- labelAnimator.setStartDelay(startDelay);
- labelAnimator.setDuration(FADE_TRANSITION_TIME);
-
- if (fadeBackground) {
- final ViewPropertyAnimator backgroundAnimator = mLabelBackgroundView.animate();
- mLabelBackgroundView.setAlpha(0.0f);
- backgroundAnimator.alpha(1.0f);
- backgroundAnimator.setStartDelay(startDelay);
- backgroundAnimator.setDuration(FADE_TRANSITION_TIME);
- }
- }
-}
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 629e36b..6573fa2 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -161,7 +161,6 @@
private Button mQuickFixButton;
private QuickFix mQuickFix;
- private boolean mContactHasSocialUpdates;
private boolean mShowStaticPhoto = true;
private final QuickFix[] mPotentialQuickFixes = new QuickFix[] {
diff --git a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java b/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
deleted file mode 100644
index 434d8f5..0000000
--- a/src/com/android/contacts/detail/ContactDetailFragmentCarousel.java
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * 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.detail;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.view.ViewPropertyAnimator;
-import android.widget.HorizontalScrollView;
-
-import com.android.contacts.R;
-import com.android.contacts.widget.FrameLayoutWithOverlay;
-
-/**
- * This is a horizontally scrolling carousel with 2 fragments: one to see info about the contact and
- * one to see updates from the contact. Depending on the scroll position and user selection of which
- * fragment to currently view, the touch interceptors over each fragment are configured accordingly.
- */
-public class ContactDetailFragmentCarousel extends HorizontalScrollView implements OnTouchListener {
-
- private static final String TAG = ContactDetailFragmentCarousel.class.getSimpleName();
-
- /**
- * Number of pixels that this view can be scrolled horizontally.
- */
- private int mAllowedHorizontalScrollLength = Integer.MIN_VALUE;
-
- /**
- * Minimum X scroll position that must be surpassed (if the user is on the "about" page of the
- * contact card), in order for this view to automatically snap to the "updates" page.
- */
- private int mLowerThreshold = Integer.MIN_VALUE;
-
- /**
- * Maximum X scroll position (if the user is on the "updates" page of the contact card), below
- * which this view will automatically snap to the "about" page.
- */
- private int mUpperThreshold = Integer.MIN_VALUE;
-
- /**
- * Minimum width of a fragment (if there is more than 1 fragment in the carousel, then this is
- * the width of one of the fragments).
- */
- private int mMinFragmentWidth = Integer.MIN_VALUE;
-
- /**
- * Fragment width (if there are 1+ fragments in the carousel) as defined as a fraction of the
- * screen width.
- */
- private static final float FRAGMENT_WIDTH_SCREEN_WIDTH_FRACTION = 0.85f;
-
- private static final int ABOUT_PAGE = 0;
- private static final int UPDATES_PAGE = 1;
-
- private static final int MAX_FRAGMENT_VIEW_COUNT = 2;
-
- private boolean mEnableSwipe;
-
- private int mCurrentPage = ABOUT_PAGE;
- private int mLastScrollPosition;
-
- private FrameLayoutWithOverlay mAboutFragment;
- private FrameLayoutWithOverlay mUpdatesFragment;
-
- public ContactDetailFragmentCarousel(Context context) {
- this(context, null);
- }
-
- public ContactDetailFragmentCarousel(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public ContactDetailFragmentCarousel(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
-
- final LayoutInflater inflater =
- (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- inflater.inflate(R.layout.contact_detail_fragment_carousel, this);
-
- setOnTouchListener(this);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int screenWidth = MeasureSpec.getSize(widthMeasureSpec);
- int screenHeight = MeasureSpec.getSize(heightMeasureSpec);
-
- // Take the width of this view as the width of the screen and compute necessary thresholds.
- // Only do this computation 1x.
- if (mAllowedHorizontalScrollLength == Integer.MIN_VALUE) {
- mMinFragmentWidth = (int) (FRAGMENT_WIDTH_SCREEN_WIDTH_FRACTION * screenWidth);
- mAllowedHorizontalScrollLength = (MAX_FRAGMENT_VIEW_COUNT * mMinFragmentWidth) -
- screenWidth;
- mLowerThreshold = (screenWidth - mMinFragmentWidth) / MAX_FRAGMENT_VIEW_COUNT;
- mUpperThreshold = mAllowedHorizontalScrollLength - mLowerThreshold;
- }
-
- if (getChildCount() > 0) {
- View child = getChildAt(0);
- // If we enable swipe, then the {@link LinearLayout} child width must be the sum of the
- // width of all its children fragments.
- // Or the current page may already be set to something other than the first. If so,
- // it also means there are multiple child fragments.
- if (mEnableSwipe || mCurrentPage == 1 ||
- (mCurrentPage == 0 && getLayoutDirection() == View.LAYOUT_DIRECTION_RTL)) {
- child.measure(MeasureSpec.makeMeasureSpec(
- mMinFragmentWidth * MAX_FRAGMENT_VIEW_COUNT, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(screenHeight, MeasureSpec.EXACTLY));
- } else {
- // Otherwise, the {@link LinearLayout} child width will just be the screen width
- // because it will only have 1 child fragment.
- child.measure(MeasureSpec.makeMeasureSpec(screenWidth, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(screenHeight, MeasureSpec.EXACTLY));
- }
- }
-
- setMeasuredDimension(
- resolveSize(screenWidth, widthMeasureSpec),
- resolveSize(screenHeight, heightMeasureSpec));
- }
-
- /**
- * Set the current page. This dims out the non-selected page but doesn't do any scrolling of
- * the carousel.
- */
- public void setCurrentPage(int pageIndex) {
- mCurrentPage = pageIndex;
-
- updateTouchInterceptors();
- }
-
- /**
- * Set the view containers for the detail and updates fragment.
- */
- public void setFragmentViews(FrameLayoutWithOverlay about, FrameLayoutWithOverlay updates) {
- mAboutFragment = about;
- mUpdatesFragment = updates;
-
- mAboutFragment.setOverlayOnClickListener(mAboutFragTouchInterceptListener);
- mUpdatesFragment.setOverlayOnClickListener(mUpdatesFragTouchInterceptListener);
- }
-
- /**
- * Enable swiping if the detail and update fragments should be showing. Otherwise disable
- * swiping if only the detail fragment should be showing.
- */
- public void enableSwipe(boolean enable) {
- if (mEnableSwipe != enable) {
- mEnableSwipe = enable;
- if (mUpdatesFragment != null) {
- mUpdatesFragment.setVisibility(enable ? View.VISIBLE : View.GONE);
- snapToEdge();
- updateTouchInterceptors();
- }
- }
- }
-
- /**
- * Reset the fragment carousel to show the about page.
- */
- public void reset() {
- if (mCurrentPage != ABOUT_PAGE) {
- mCurrentPage = ABOUT_PAGE;
- snapToEdgeSmooth();
- }
- }
-
- public int getCurrentPage() {
- return mCurrentPage;
- }
-
- private final OnClickListener mAboutFragTouchInterceptListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCurrentPage = ABOUT_PAGE;
- snapToEdgeSmooth();
- }
- };
-
- private final OnClickListener mUpdatesFragTouchInterceptListener = new OnClickListener() {
- @Override
- public void onClick(View v) {
- mCurrentPage = UPDATES_PAGE;
- snapToEdgeSmooth();
- }
- };
-
- private void updateTouchInterceptors() {
- // Disable the touch-interceptor on the selected page, and enable it on the other.
- if (mAboutFragment != null) {
- mAboutFragment.setOverlayClickable(mCurrentPage != ABOUT_PAGE);
- }
- if (mUpdatesFragment != null) {
- mUpdatesFragment.setOverlayClickable(mCurrentPage != UPDATES_PAGE);
- }
- }
-
- @Override
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- super.onScrollChanged(l, t, oldl, oldt);
- if (!mEnableSwipe) {
- return;
- }
- mLastScrollPosition = l;
- }
-
- /**
- * Used to set initial scroll offset. Not smooth.
- */
- private void snapToEdge() {
- setScrollX(calculateHorizontalOffset());
- updateTouchInterceptors();
- }
-
- /**
- * Smooth version of snapToEdge().
- */
- private void snapToEdgeSmooth() {
- smoothScrollTo(calculateHorizontalOffset(), 0);
- updateTouchInterceptors();
- }
-
- private int calculateHorizontalOffset() {
- int offset;
- if (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- offset = (mCurrentPage == ABOUT_PAGE) ? mAllowedHorizontalScrollLength : 0;
- } else {
- offset = (mCurrentPage == ABOUT_PAGE) ? 0 : mAllowedHorizontalScrollLength;
- }
- return offset;
- }
-
- /**
- * Returns the desired page we should scroll to based on the current X scroll position and the
- * current page.
- */
- private int getDesiredPage() {
- switch (mCurrentPage) {
- case ABOUT_PAGE:
- if (getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
- // If the user is on the "about" page, and the scroll position exceeds the lower
- // threshold, then we should switch to the "updates" page.
- return (mLastScrollPosition > mLowerThreshold) ? UPDATES_PAGE : ABOUT_PAGE;
- } else {
- return (mLastScrollPosition < mUpperThreshold) ? UPDATES_PAGE : ABOUT_PAGE;
- }
- case UPDATES_PAGE:
- if (getLayoutDirection() == View.LAYOUT_DIRECTION_LTR) {
- // If the user is on the "updates" page, and the scroll position goes below the
- // upper threshold, then we should switch to the "about" page.
- return (mLastScrollPosition < mUpperThreshold) ? ABOUT_PAGE : UPDATES_PAGE;
- } else {
- return (mLastScrollPosition > mLowerThreshold) ? ABOUT_PAGE : UPDATES_PAGE;
- }
- }
- throw new IllegalStateException("Invalid current page " + mCurrentPage);
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- if (!mEnableSwipe) {
- return false;
- }
- if (event.getAction() == MotionEvent.ACTION_UP) {
- mCurrentPage = getDesiredPage();
- snapToEdgeSmooth();
- return true;
- }
- return false;
- }
-
- /**
- * Starts an "appear" animation by moving in the "Updates" from the right.
- */
- public void animateAppear() {
- final int x = Math.round((1.0f - FRAGMENT_WIDTH_SCREEN_WIDTH_FRACTION) * getWidth());
- mUpdatesFragment.setTranslationX(x);
- final ViewPropertyAnimator animator = mUpdatesFragment.animate();
- animator.translationX(0.0f);
- }
-}
diff --git a/src/com/android/contacts/detail/ContactDetailLayoutController.java b/src/com/android/contacts/detail/ContactDetailLayoutController.java
index 1ee31a5..7e412e0 100644
--- a/src/com/android/contacts/detail/ContactDetailLayoutController.java
+++ b/src/com/android/contacts/detail/ContactDetailLayoutController.java
@@ -16,101 +16,44 @@
package com.android.contacts.detail;
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.FragmentManager;
-import android.app.FragmentTransaction;
-import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
-import android.support.v4.view.ViewPager;
-import android.support.v4.view.ViewPager.OnPageChangeListener;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewPropertyAnimator;
-import android.view.animation.AnimationUtils;
-import android.widget.AbsListView;
-import android.widget.AbsListView.OnScrollListener;
import com.android.contacts.NfcHandler;
-import com.android.contacts.R;
+import com.android.contacts.R.id;
import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
import com.android.contacts.common.model.Contact;
import com.android.contacts.util.PhoneCapabilityTester;
import com.android.contacts.common.util.UriUtils;
-import com.android.contacts.widget.FrameLayoutWithOverlay;
import com.android.contacts.widget.TransitionAnimationView;
/**
- * Determines the layout of the contact card.
+ * Sets ContactDetailFragment data and performs animations when data changes.
+ *
+ * TODO: rename, move some of this logic into ContactDetailFragment and/or delete this class. This
+ * class used to have more responsibility: the ContactDetailFragment was used beside social update
+ * Fragments.
*/
public class ContactDetailLayoutController {
private static final String KEY_CONTACT_URI = "contactUri";
- private static final String KEY_CONTACT_HAS_UPDATES = "contactHasUpdates";
- private static final String KEY_CURRENT_PAGE_INDEX = "currentPageIndex";
-
- private static final int TAB_INDEX_DETAIL = 0;
- private static final int TAB_INDEX_UPDATES = 1;
private final int SINGLE_PANE_FADE_IN_DURATION = 275;
- /**
- * There are 4 possible layouts for the contact detail screen: TWO_COLUMN,
- * VIEW_PAGER_AND_TAB_CAROUSEL, FRAGMENT_CAROUSEL, and TWO_COLUMN_FRAGMENT_CAROUSEL.
- */
- private interface LayoutMode {
- /**
- * Tall and wide screen with details and updates shown side-by-side.
- */
- static final int TWO_COLUMN = 0;
- /**
- * Tall and narrow screen to allow swipe between the details and updates.
- */
- static final int VIEW_PAGER_AND_TAB_CAROUSEL = 1;
- /**
- * Short and wide screen to allow part of the other page to show.
- */
- static final int FRAGMENT_CAROUSEL = 2;
- /**
- * Same as FRAGMENT_CAROUSEL (allowing part of the other page to show) except the details
- * layout is similar to the details layout in TWO_COLUMN mode.
- */
- static final int TWO_COLUMN_FRAGMENT_CAROUSEL = 3;
- }
-
private final Activity mActivity;
- private final LayoutInflater mLayoutInflater;
private final FragmentManager mFragmentManager;
-
- private final View mViewContainer;
- private final TransitionAnimationView mTransitionAnimationView;
- private ContactDetailFragment mDetailFragment;
- private ContactDetailUpdatesFragment mUpdatesFragment;
-
- private View mDetailFragmentView;
- private View mUpdatesFragmentView;
-
- private final ViewPager mViewPager;
- private ContactDetailViewPagerAdapter mViewPagerAdapter;
- private int mViewPagerState;
-
- private final ContactDetailTabCarousel mTabCarousel;
- private final ContactDetailFragmentCarousel mFragmentCarousel;
-
private final ContactDetailFragment.Listener mContactDetailFragmentListener;
+ private final TransitionAnimationView mTransitionAnimationView;
+ private final View mViewContainer;
+ private ContactDetailFragment mDetailFragment;
private Contact mContactData;
private Uri mContactUri;
- private boolean mTabCarouselIsAnimating;
-
- private boolean mContactHasUpdates;
-
- private int mLayoutMode;
-
public ContactDetailLayoutController(Activity activity, Bundle savedState,
FragmentManager fragmentManager, TransitionAnimationView animationView,
View viewContainer, ContactDetailFragment.Listener contactDetailFragmentListener) {
@@ -121,165 +64,36 @@
}
mActivity = activity;
- mLayoutInflater = (LayoutInflater) activity.getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
mFragmentManager = fragmentManager;
mContactDetailFragmentListener = contactDetailFragmentListener;
-
mTransitionAnimationView = animationView;
-
- // Retrieve views in case this is view pager and carousel mode
mViewContainer = viewContainer;
- mViewPager = (ViewPager) viewContainer.findViewById(R.id.pager);
- mTabCarousel = (ContactDetailTabCarousel) viewContainer.findViewById(R.id.tab_carousel);
-
- // Retrieve view in case this is in fragment carousel mode
- mFragmentCarousel = (ContactDetailFragmentCarousel) viewContainer.findViewById(
- R.id.fragment_carousel);
-
- // Retrieve container views in case they are already in the XML layout
- mDetailFragmentView = viewContainer.findViewById(R.id.about_fragment_container);
- mUpdatesFragmentView = viewContainer.findViewById(R.id.updates_fragment_container);
-
- // Determine the layout mode based on the presence of certain views in the layout XML.
- if (mViewPager != null) {
- mLayoutMode = LayoutMode.VIEW_PAGER_AND_TAB_CAROUSEL;
- } else if (mFragmentCarousel != null) {
- if (PhoneCapabilityTester.isUsingTwoPanes(mActivity)) {
- mLayoutMode = LayoutMode.TWO_COLUMN_FRAGMENT_CAROUSEL;
- } else {
- mLayoutMode = LayoutMode.FRAGMENT_CAROUSEL;
- }
- } else {
- mLayoutMode = LayoutMode.TWO_COLUMN;
- }
-
initialize(savedState);
}
private void initialize(Bundle savedState) {
- boolean fragmentsAddedToFragmentManager = true;
- mDetailFragment = (ContactDetailFragment) mFragmentManager.findFragmentByTag(
- ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
- mUpdatesFragment = (ContactDetailUpdatesFragment) mFragmentManager.findFragmentByTag(
- ContactDetailViewPagerAdapter.UPDATES_FRAGMENT_TAG);
-
- // If the detail fragment was found in the {@link FragmentManager} then we don't need to add
- // it again. Otherwise, create the fragments dynamically and remember to add them to the
- // {@link FragmentManager}.
- if (mDetailFragment == null) {
- mDetailFragment = new ContactDetailFragment();
- mUpdatesFragment = new ContactDetailUpdatesFragment();
- fragmentsAddedToFragmentManager = false;
- }
+ mDetailFragment = (ContactDetailFragment) mFragmentManager
+ .findFragmentById(id.contact_detail_about_fragment);
mDetailFragment.setListener(mContactDetailFragmentListener);
NfcHandler.register(mActivity, mDetailFragment);
- // Read from savedState if possible
- int currentPageIndex = 0;
if (savedState != null) {
mContactUri = savedState.getParcelable(KEY_CONTACT_URI);
- mContactHasUpdates = savedState.getBoolean(KEY_CONTACT_HAS_UPDATES);
- currentPageIndex = savedState.getInt(KEY_CURRENT_PAGE_INDEX, 0);
- }
- switch (mLayoutMode) {
- case LayoutMode.VIEW_PAGER_AND_TAB_CAROUSEL: {
- // Inflate 2 view containers to pass in as children to the {@link ViewPager},
- // which will in turn be the parents to the mDetailFragment and mUpdatesFragment
- // since the fragments must have the same parent view IDs in both landscape and
- // portrait layouts.
- mDetailFragmentView = mLayoutInflater.inflate(
- R.layout.contact_detail_about_fragment_container, mViewPager, false);
- mUpdatesFragmentView = mLayoutInflater.inflate(
- R.layout.contact_detail_updates_fragment_container, mViewPager, false);
-
- mViewPagerAdapter = new ContactDetailViewPagerAdapter();
- mViewPagerAdapter.setAboutFragmentView(mDetailFragmentView);
- mViewPagerAdapter.setUpdatesFragmentView(mUpdatesFragmentView);
-
- mViewPager.addView(mDetailFragmentView);
- mViewPager.addView(mUpdatesFragmentView);
- mViewPager.setAdapter(mViewPagerAdapter);
- mViewPager.setOnPageChangeListener(mOnPageChangeListener);
-
- if (!fragmentsAddedToFragmentManager) {
- FragmentTransaction transaction = mFragmentManager.beginTransaction();
- transaction.add(R.id.about_fragment_container, mDetailFragment,
- ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
- transaction.add(R.id.updates_fragment_container, mUpdatesFragment,
- ContactDetailViewPagerAdapter.UPDATES_FRAGMENT_TAG);
- transaction.commitAllowingStateLoss();
- mFragmentManager.executePendingTransactions();
- }
-
- mTabCarousel.setListener(mTabCarouselListener);
- mTabCarousel.restoreCurrentTab(currentPageIndex);
- mDetailFragment.setVerticalScrollListener(
- new VerticalScrollListener(TAB_INDEX_DETAIL));
- mUpdatesFragment.setVerticalScrollListener(
- new VerticalScrollListener(TAB_INDEX_UPDATES));
- mViewPager.setCurrentItem(currentPageIndex);
- break;
- }
- case LayoutMode.TWO_COLUMN: {
- if (!fragmentsAddedToFragmentManager) {
- FragmentTransaction transaction = mFragmentManager.beginTransaction();
- transaction.add(R.id.about_fragment_container, mDetailFragment,
- ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
- transaction.add(R.id.updates_fragment_container, mUpdatesFragment,
- ContactDetailViewPagerAdapter.UPDATES_FRAGMENT_TAG);
- transaction.commitAllowingStateLoss();
- mFragmentManager.executePendingTransactions();
- }
- break;
- }
- case LayoutMode.FRAGMENT_CAROUSEL:
- case LayoutMode.TWO_COLUMN_FRAGMENT_CAROUSEL: {
- // Add the fragments to the fragment containers in the carousel using a
- // {@link FragmentTransaction} if they haven't already been added to the
- // {@link FragmentManager}.
- if (!fragmentsAddedToFragmentManager) {
- FragmentTransaction transaction = mFragmentManager.beginTransaction();
- transaction.add(R.id.about_fragment_container, mDetailFragment,
- ContactDetailViewPagerAdapter.ABOUT_FRAGMENT_TAG);
- transaction.add(R.id.updates_fragment_container, mUpdatesFragment,
- ContactDetailViewPagerAdapter.UPDATES_FRAGMENT_TAG);
- transaction.commitAllowingStateLoss();
- mFragmentManager.executePendingTransactions();
- }
-
- mFragmentCarousel.setFragmentViews(
- (FrameLayoutWithOverlay) mDetailFragmentView,
- (FrameLayoutWithOverlay) mUpdatesFragmentView);
- mFragmentCarousel.setCurrentPage(currentPageIndex);
-
- break;
- }
- }
-
- // Setup the layout if we already have a saved state
- if (savedState != null) {
- if (mContactHasUpdates) {
- showContactWithUpdates(false);
- } else {
- showContactWithoutUpdates();
- }
+ // Immediately setup layout since we have saved state
+ showContact();
}
}
public void setContactData(Contact data) {
final boolean contactWasLoaded;
- final boolean contactHadUpdates;
final boolean isDifferentContact;
if (mContactData == null) {
- contactHadUpdates = false;
contactWasLoaded = false;
isDifferentContact = true;
} else {
- contactHadUpdates = mContactHasUpdates;
contactWasLoaded = true;
isDifferentContact =
!UriUtils.areEqual(mContactData.getLookupUri(), data.getLookupUri());
@@ -301,50 +115,15 @@
}
}
- showContactWithoutUpdates();
+ showContact();
}
public void showEmptyState() {
- switch (mLayoutMode) {
- case LayoutMode.FRAGMENT_CAROUSEL: {
- mFragmentCarousel.setCurrentPage(0);
- mFragmentCarousel.enableSwipe(false);
- mDetailFragment.showEmptyState();
- break;
- }
- case LayoutMode.TWO_COLUMN: {
- mDetailFragment.setShowStaticPhoto(false);
- mUpdatesFragmentView.setVisibility(View.GONE);
- mDetailFragment.showEmptyState();
- break;
- }
- case LayoutMode.TWO_COLUMN_FRAGMENT_CAROUSEL: {
- mFragmentCarousel.setCurrentPage(0);
- mFragmentCarousel.enableSwipe(false);
- mDetailFragment.setShowStaticPhoto(false);
- mUpdatesFragmentView.setVisibility(View.GONE);
- mDetailFragment.showEmptyState();
- break;
- }
- case LayoutMode.VIEW_PAGER_AND_TAB_CAROUSEL: {
- mDetailFragment.setShowStaticPhoto(false);
- mDetailFragment.showEmptyState();
- mTabCarousel.loadData(null);
- mTabCarousel.setVisibility(View.GONE);
- mViewPagerAdapter.enableSwipe(false);
- mViewPager.setCurrentItem(0);
- break;
- }
- default:
- throw new IllegalStateException("Invalid LayoutMode " + mLayoutMode);
- }
+ mDetailFragment.setShowStaticPhoto(false);
+ mDetailFragment.showEmptyState();
}
- /**
- * Setup the layout for the contact with updates.
- * TODO: Clean up this method so it's easier to understand.
- */
- private void showContactWithUpdates(boolean animateStateChange) {
+ private void showContact() {
if (mContactData == null) {
return;
}
@@ -353,390 +132,20 @@
mContactUri = mContactData.getLookupUri();
boolean isDifferentContact = !UriUtils.areEqual(previousContactUri, mContactUri);
- switch (mLayoutMode) {
- case LayoutMode.TWO_COLUMN: {
- if (!isDifferentContact && animateStateChange) {
- // This is screen is very hard to animate properly, because there is such a hard
- // cut from the regular version. A proper animation would have to reflow text
- // and move things around. Doing a simple cross-fade instead.
- mTransitionAnimationView.startMaskTransition(false, -1);
- }
-
- // Set the contact data (hide the static photo because the photo will already be in
- // the header that scrolls with contact details).
- mDetailFragment.setShowStaticPhoto(false);
- // Show the updates fragment
- mUpdatesFragmentView.setVisibility(View.VISIBLE);
- break;
- }
- case LayoutMode.VIEW_PAGER_AND_TAB_CAROUSEL: {
- // Update and show the tab carousel (also restore its last saved position)
- mTabCarousel.loadData(mContactData);
- mTabCarousel.restoreYCoordinate();
- mTabCarousel.setVisibility(View.VISIBLE);
- // Update ViewPager to allow swipe between all the fragments (to see updates)
- mViewPagerAdapter.enableSwipe(true);
- // If this is a different contact than before, then reset some views.
- if (isDifferentContact) {
- resetViewPager();
- resetTabCarousel();
- }
- if (!isDifferentContact && animateStateChange) {
- mTabCarousel.animateAppear(mViewContainer.getWidth(),
- mDetailFragment.getFirstListItemOffset());
- }
- break;
- }
- case LayoutMode.FRAGMENT_CAROUSEL: {
- // Allow swiping between all fragments
- mFragmentCarousel.enableSwipe(true);
- if (!isDifferentContact && animateStateChange) {
- mFragmentCarousel.animateAppear();
- }
- break;
- }
- case LayoutMode.TWO_COLUMN_FRAGMENT_CAROUSEL: {
- // Allow swiping between all fragments
- mFragmentCarousel.enableSwipe(true);
- if (isDifferentContact) {
- mFragmentCarousel.reset();
- }
- if (!isDifferentContact && animateStateChange) {
- mFragmentCarousel.animateAppear();
- }
- mDetailFragment.setShowStaticPhoto(false);
- break;
- }
- default:
- throw new IllegalStateException("Invalid LayoutMode " + mLayoutMode);
- }
+ mDetailFragment.setShowStaticPhoto(true);
if (isDifferentContact) {
- resetFragments();
+ mDetailFragment.resetAdapter();
}
mDetailFragment.setData(mContactUri, mContactData);
- mUpdatesFragment.setData(mContactUri, mContactData);
- }
-
- /**
- * Setup the layout for the contact without updates.
- * TODO: Clean up this method so it's easier to understand.
- */
- private void showContactWithoutUpdates() {
- if (mContactData == null) {
- return;
- }
-
- Uri previousContactUri = mContactUri;
- mContactUri = mContactData.getLookupUri();
- boolean isDifferentContact = !UriUtils.areEqual(previousContactUri, mContactUri);
-
- switch (mLayoutMode) {
- case LayoutMode.TWO_COLUMN:
- // Show the static photo which is next to the list of scrolling contact details
- mDetailFragment.setShowStaticPhoto(true);
- // Hide the updates fragment
- mUpdatesFragmentView.setVisibility(View.GONE);
- break;
- case LayoutMode.VIEW_PAGER_AND_TAB_CAROUSEL:
- // Hide the tab carousel
- mTabCarousel.setVisibility(View.GONE);
- // Update ViewPager to disable swipe so that it only shows the detail fragment
- // and switch to the detail fragment
- mViewPagerAdapter.enableSwipe(false);
- mViewPager.setCurrentItem(0, false /* smooth transition */);
- break;
- case LayoutMode.FRAGMENT_CAROUSEL:
- // Disable swipe so only the detail fragment shows
- mFragmentCarousel.setCurrentPage(0);
- mFragmentCarousel.enableSwipe(false);
- break;
- case LayoutMode.TWO_COLUMN_FRAGMENT_CAROUSEL:
- mFragmentCarousel.setCurrentPage(0);
- mFragmentCarousel.enableSwipe(false);
- mDetailFragment.setShowStaticPhoto(true);
- break;
- default:
- throw new IllegalStateException("Invalid LayoutMode " + mLayoutMode);
- }
-
- if (isDifferentContact) {
- resetFragments();
- }
-
- mDetailFragment.setData(mContactUri, mContactData);
- }
-
- private void resetTabCarousel() {
- mTabCarousel.reset();
- }
-
- private void resetViewPager() {
- mViewPager.setCurrentItem(0, false /* smooth transition */);
- }
-
- private void resetFragments() {
- mDetailFragment.resetAdapter();
- mUpdatesFragment.resetAdapter();
}
public FragmentKeyListener getCurrentPage() {
- switch (getCurrentPageIndex()) {
- case 0:
- return mDetailFragment;
- case 1:
- return mUpdatesFragment;
- default:
- throw new IllegalStateException("Invalid current item for ViewPager");
- }
- }
-
- private int getCurrentPageIndex() {
- // If the contact has social updates, then retrieve the current page based on the
- // {@link ViewPager} or fragment carousel.
- if (mContactHasUpdates) {
- if (mViewPager != null) {
- return mViewPager.getCurrentItem();
- } else if (mFragmentCarousel != null) {
- return mFragmentCarousel.getCurrentPage();
- }
- }
- // Otherwise return the default page (detail fragment).
- return 0;
+ return mDetailFragment;
}
public void onSaveInstanceState(Bundle outState) {
outState.putParcelable(KEY_CONTACT_URI, mContactUri);
- outState.putBoolean(KEY_CONTACT_HAS_UPDATES, mContactHasUpdates);
- outState.putInt(KEY_CURRENT_PAGE_INDEX, getCurrentPageIndex());
- }
-
- private final OnPageChangeListener mOnPageChangeListener = new OnPageChangeListener() {
-
- private ObjectAnimator mTabCarouselAnimator;
-
- @Override
- public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
- // The user is horizontally dragging the {@link ViewPager}, so send
- // these scroll changes to the tab carousel. Ignore these events though if the carousel
- // is actually controlling the {@link ViewPager} scrolls because it will already be
- // in the correct position.
- if (mViewPager.isFakeDragging()) return;
-
- int x = (int) ((position + positionOffset) *
- mTabCarousel.getAllowedHorizontalScrollLength());
- mTabCarousel.scrollTo(x, 0);
- }
-
- @Override
- public void onPageSelected(int position) {
- // Since the {@link ViewPager} has committed to a new page now (but may not have
- // finished scrolling yet), update the tab selection in the carousel.
- mTabCarousel.setCurrentTab(position);
- }
-
- @Override
- public void onPageScrollStateChanged(int state) {
- if (mViewPagerState == ViewPager.SCROLL_STATE_IDLE) {
-
- // If we are leaving the IDLE state, we are starting a swipe.
- // First cancel any pending animations on the tab carousel.
- cancelTabCarouselAnimator();
-
- // Sync the two lists because the list on the other page will start to show as
- // we swipe over more.
- syncScrollStateBetweenLists(mViewPager.getCurrentItem());
-
- } else if (state == ViewPager.SCROLL_STATE_IDLE) {
-
- // Otherwise if the {@link ViewPager} is idle now, a page has been selected and
- // scrolled into place. Perform an animation of the tab carousel is needed.
- int currentPageIndex = mViewPager.getCurrentItem();
- int tabCarouselOffset = (int) mTabCarousel.getY();
- boolean shouldAnimateTabCarousel;
-
- // Find the offset position of the first item in the list of the current page.
- int listOffset = getOffsetOfFirstItemInList(currentPageIndex);
-
- // If the list was able to successfully offset by the tab carousel amount, then
- // log this as the new Y coordinate for that page, and no animation is needed.
- if (listOffset == tabCarouselOffset) {
- mTabCarousel.storeYCoordinate(currentPageIndex, tabCarouselOffset);
- shouldAnimateTabCarousel = false;
- } else if (listOffset == Integer.MIN_VALUE) {
- // If the offset of the first item in the list is unknown (i.e. the item
- // is no longer visible on screen) then just animate the tab carousel to the
- // previously logged position.
- shouldAnimateTabCarousel = true;
- } else if (Math.abs(listOffset) < Math.abs(tabCarouselOffset)) {
- // If the list could not offset the full amount of the tab carousel offset (i.e.
- // the list can only be scrolled a tiny amount), then animate the carousel down
- // to compensate.
- mTabCarousel.storeYCoordinate(currentPageIndex, listOffset);
- shouldAnimateTabCarousel = true;
- } else {
- // By default, animate back to the Y coordinate of the tab carousel the last
- // time the other page was selected.
- shouldAnimateTabCarousel = true;
- }
-
- if (shouldAnimateTabCarousel) {
- float desiredOffset = mTabCarousel.getStoredYCoordinateForTab(currentPageIndex);
- if (desiredOffset != tabCarouselOffset) {
- createTabCarouselAnimator(desiredOffset);
- mTabCarouselAnimator.start();
- }
- }
- }
- mViewPagerState = state;
- }
-
- private void createTabCarouselAnimator(float desiredValue) {
- mTabCarouselAnimator = ObjectAnimator.ofFloat(
- 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;
- }
- }
- };
-
- private void syncScrollStateBetweenLists(int currentPageIndex) {
- // Since the user interacted with the currently visible page, we need to sync the
- // list on the other page (i.e. if the updates page is the current page, modify the
- // list in the details page).
- if (currentPageIndex == TAB_INDEX_UPDATES) {
- mDetailFragment.requestToMoveToOffset((int) mTabCarousel.getY());
- } else {
- mUpdatesFragment.requestToMoveToOffset((int) mTabCarousel.getY());
- }
- }
-
- private int getOffsetOfFirstItemInList(int currentPageIndex) {
- if (currentPageIndex == TAB_INDEX_DETAIL) {
- return mDetailFragment.getFirstListItemOffset();
- } else {
- return mUpdatesFragment.getFirstListItemOffset();
- }
- }
-
- /**
- * 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() {
-
- @Override
- public void onTouchDown() {
- // The user just started scrolling the carousel, so begin
- // "fake dragging" the {@link ViewPager} if it's not already
- // doing so.
- if (!mViewPager.isFakeDragging()) mViewPager.beginFakeDrag();
- }
-
- @Override
- public void onTouchUp() {
- // The user just stopped scrolling the carousel, so stop
- // "fake dragging" the {@link ViewPager} if it was doing so
- // before.
- if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag();
- }
-
- @Override
- public void onScrollChanged(int l, int t, int oldl, int oldt) {
- // The user is scrolling the carousel, so send the scroll
- // deltas to the {@link ViewPager} so it can move in sync.
- if (mViewPager.isFakeDragging()) {
- mViewPager.fakeDragBy(oldl - l);
- }
- }
-
- @Override
- public void onTabSelected(int position) {
- // The user selected a tab, so update the {@link ViewPager}
- mViewPager.setCurrentItem(position);
- }
- };
-
- private final class VerticalScrollListener implements OnScrollListener {
-
- private final int mPageIndex;
-
- public VerticalScrollListener(int pageIndex) {
- mPageIndex = pageIndex;
- }
-
- @Override
- public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount,
- 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,
- // 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 || mTabCarouselIsAnimating) {
- return;
- }
- // If the FIRST item is not visible on the screen, then the carousel must be pinned
- // at the top of the screen.
- if (firstVisibleItem != 0) {
- mTabCarousel.moveToYCoordinate(mPageIndex,
- -mTabCarousel.getAllowedVerticalScrollLength());
- return;
- }
- View topView = view.getChildAt(firstVisibleItem);
- if (topView == null) {
- return;
- }
- int amtToScroll = Math.max((int) view.getChildAt(firstVisibleItem).getY(),
- -mTabCarousel.getAllowedVerticalScrollLength());
- mTabCarousel.moveToYCoordinate(mPageIndex, amtToScroll);
- }
-
- @Override
- public void onScrollStateChanged(AbsListView view, int scrollState) {
- // Once the list has become IDLE, check if we need to sync the scroll position of
- // the other list now. This will make swiping faster by doing the re-layout now
- // (instead of at the start of a swipe). However, there will still be another check
- // when we start swiping if the scroll positions are correct (to catch the edge case
- // where the user flings and immediately starts a swipe so we never get the idle state).
- if (scrollState == SCROLL_STATE_IDLE) {
- syncScrollStateBetweenLists(mPageIndex);
- }
- }
}
}
diff --git a/src/com/android/contacts/detail/ContactDetailTabCarousel.java b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
deleted file mode 100644
index 25bcac6..0000000
--- a/src/com/android/contacts/detail/ContactDetailTabCarousel.java
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * 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.detail;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.OnTouchListener;
-import android.view.ViewPropertyAnimator;
-import android.widget.HorizontalScrollView;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.contacts.R;
-import com.android.contacts.common.model.Contact;
-import com.android.contacts.util.MoreMath;
-import com.android.contacts.util.SchedulingUtils;
-
-/**
- * This is a horizontally scrolling carousel with 2 tabs: one to see info about the contact and
- * one to see updates from the contact.
- */
-public class ContactDetailTabCarousel extends HorizontalScrollView implements OnTouchListener {
-
- private static final String TAG = ContactDetailTabCarousel.class.getSimpleName();
-
- private static final int TRANSITION_TIME = 200;
- private static final int TRANSITION_MOVE_IN_TIME = 150;
-
- private static final int TAB_INDEX_ABOUT = 0;
- private static final int TAB_INDEX_UPDATES = 1;
- private static final int TAB_COUNT = 2;
-
- /** Tab width as defined as a fraction of the screen width */
- private float mTabWidthScreenWidthFraction;
-
- /** Tab height as defined as a fraction of the screen width */
- private float mTabHeightScreenWidthFraction;
-
- /** Height in pixels of the shadow under the tab carousel */
- private int mTabShadowHeight;
-
- private ImageView mPhotoView;
- private View mPhotoViewOverlay;
- private TextView mStatusView;
- private ImageView mStatusPhotoView;
- private final ContactDetailPhotoSetter mPhotoSetter = new ContactDetailPhotoSetter();
-
- private Listener mListener;
-
- private int mCurrentTab = TAB_INDEX_ABOUT;
-
- private View mTabAndShadowContainer;
- private View mShadow;
- private CarouselTab mAboutTab;
- private View mTabDivider;
- private CarouselTab mUpdatesTab;
-
- /** Last Y coordinate of the carousel when the tab at the given index was selected */
- private final float[] mYCoordinateArray = new float[TAB_COUNT];
-
- private int mTabDisplayLabelHeight;
-
- private boolean mScrollToCurrentTab = false;
- private int mLastScrollPosition = Integer.MIN_VALUE;
- private int mAllowedHorizontalScrollLength = Integer.MIN_VALUE;
- private int mAllowedVerticalScrollLength = Integer.MIN_VALUE;
-
- /** Factor to scale scroll-amount sent to listeners. */
- private float mScrollScaleFactor = 1.0f;
-
- private static final float MAX_ALPHA = 0.5f;
-
- /**
- * Interface for callbacks invoked when the user interacts with the carousel.
- */
- public interface Listener {
- public void onTouchDown();
- public void onTouchUp();
-
- public void onScrollChanged(int l, int t, int oldl, int oldt);
- public void onTabSelected(int position);
- }
-
- public ContactDetailTabCarousel(Context context, AttributeSet attrs) {
- super(context, attrs);
-
- setOnTouchListener(this);
-
- Resources resources = mContext.getResources();
- mTabDisplayLabelHeight = resources.getDimensionPixelSize(
- R.dimen.detail_tab_carousel_tab_label_height);
- mTabShadowHeight = resources.getDimensionPixelSize(
- R.dimen.detail_contact_photo_shadow_height);
- mTabWidthScreenWidthFraction = resources.getFraction(
- R.fraction.tab_width_screen_width_percentage, 1, 1);
- mTabHeightScreenWidthFraction = resources.getFraction(
- R.fraction.tab_height_screen_width_percentage, 1, 1);
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mTabAndShadowContainer = findViewById(R.id.tab_and_shadow_container);
- mAboutTab = (CarouselTab) findViewById(R.id.tab_about);
- mAboutTab.setLabel(mContext.getString(R.string.contactDetailAbout));
- mAboutTab.setOverlayOnClickListener(mAboutTabTouchInterceptListener);
-
- mTabDivider = findViewById(R.id.tab_divider);
-
- mUpdatesTab = (CarouselTab) findViewById(R.id.tab_update);
- mUpdatesTab.setLabel(mContext.getString(R.string.contactDetailUpdates));
- mUpdatesTab.setOverlayOnClickListener(mUpdatesTabTouchInterceptListener);
-
- mShadow = findViewById(R.id.shadow);
-
- // Retrieve the photo view for the "about" tab
- // TODO: This should be moved down to mAboutTab, so that it hosts its own controls
- mPhotoView = (ImageView) mAboutTab.findViewById(R.id.photo);
- mPhotoViewOverlay = mAboutTab.findViewById(R.id.photo_overlay);
-
- // Retrieve the social update views for the "updates" tab
- // TODO: This should be moved down to mUpdatesTab, so that it hosts its own controls
- mStatusView = (TextView) mUpdatesTab.findViewById(R.id.status);
- mStatusPhotoView = (ImageView) mUpdatesTab.findViewById(R.id.status_photo);
-
- // Workaround for framework issue... it shouldn't be necessary to have a
- // clickable object in the hierarchy, but if not the horizontal scroll
- // behavior doesn't work. Note: the "About" tab doesn't need this
- // because we set a real click-handler elsewhere.
- mStatusView.setClickable(true);
- mStatusPhotoView.setClickable(true);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int screenWidth = MeasureSpec.getSize(widthMeasureSpec);
- // Compute the width of a tab as a fraction of the screen width
- int tabWidth = Math.round(mTabWidthScreenWidthFraction * screenWidth);
-
- // Find the allowed scrolling length by subtracting the current visible screen width
- // from the total length of the tabs.
- mAllowedHorizontalScrollLength = tabWidth * TAB_COUNT - screenWidth;
-
- // Scrolling by mAllowedHorizontalScrollLength causes listeners to
- // scroll by the entire screen amount; compute the scale-factor
- // necessary to make this so.
- if (mAllowedHorizontalScrollLength == 0) {
- // Guard against divide-by-zero.
- // Note: this hard-coded value prevents a crash, but won't result in the
- // desired scrolling behavior. We rely on the framework calling onMeasure()
- // again with a non-zero screen width.
- mScrollScaleFactor = 1.0f;
- Log.w(TAG, "set scale-factor to 1.0 to avoid divide-by-zero");
- } else {
- mScrollScaleFactor = screenWidth / mAllowedHorizontalScrollLength;
- }
-
- int tabHeight = Math.round(screenWidth * mTabHeightScreenWidthFraction) + mTabShadowHeight;
- // Set the child {@link LinearLayout} to be TAB_COUNT * the computed tab width so that the
- // {@link LinearLayout}'s children (which are the tabs) will evenly split that width.
- if (getChildCount() > 0) {
- View child = getChildAt(0);
-
- // add 1 dip of separation between the tabs
- final int seperatorPixels =
- (int)(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
- getResources().getDisplayMetrics()) + 0.5f);
-
- child.measure(
- MeasureSpec.makeMeasureSpec(
- TAB_COUNT * tabWidth +
- (TAB_COUNT - 1) * seperatorPixels, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(tabHeight, MeasureSpec.EXACTLY));
- }
-
- mAllowedVerticalScrollLength = tabHeight - mTabDisplayLabelHeight - mTabShadowHeight;
- setMeasuredDimension(
- resolveSize(screenWidth, widthMeasureSpec),
- resolveSize(tabHeight, heightMeasureSpec));
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
-
- // Defer this stuff until after the layout has finished. This is because
- // updateAlphaLayers() ultimately results in another layout request, and
- // the framework currently can't handle this safely.
- if (!mScrollToCurrentTab) return;
- mScrollToCurrentTab = false;
- SchedulingUtils.doAfterLayout(this, new Runnable() {
- @Override
- public void run() {
- scrollTo(mCurrentTab == TAB_INDEX_ABOUT ? 0 : mAllowedHorizontalScrollLength, 0);
- updateAlphaLayers();
- }
- });
- }
-
- /** When clicked, selects the corresponding tab. */
- private class TabClickListener implements OnClickListener {
- private final int mTab;
-
- public TabClickListener(int tab) {
- super();
- mTab = tab;
- }
-
- @Override
- public void onClick(View v) {
- mListener.onTabSelected(mTab);
- }
- }
-
- private final TabClickListener mAboutTabTouchInterceptListener =
- new TabClickListener(TAB_INDEX_ABOUT);
-
- private final TabClickListener mUpdatesTabTouchInterceptListener =
- new TabClickListener(TAB_INDEX_UPDATES);
-
- /**
- * Does in "appear" animation to allow a seamless transition from
- * the "No updates" mode.
- * @param width Width of the container. As we haven't been layed out yet, we can't know
- * @param scrollOffset The offset by how far we scrolled, where 0=not scrolled, -x=scrolled by
- * x pixels, Integer.MIN_VALUE=scrolled so far that the image is not visible in "no updates"
- * mode of this screen
- */
- public void animateAppear(int width, int scrollOffset) {
- final float photoHeight = mTabHeightScreenWidthFraction * width;
- final boolean animateZoomAndFade;
- int pixelsToScrollVertically = 0;
-
- // Depending on how far we are scrolled down, there is one of three animations:
- // - Zoom and fade the picture (if it is still visible)
- // - Scroll, zoom and fade (if the picture is mostly invisible and we now have a
- // bigger visible region due to the pinning)
- // - Just scroll if the picture is completely invisible. This time, no zoom is needed
- if (scrollOffset == Integer.MIN_VALUE) {
- // animate in completely by scrolling. no need for zooming here
- pixelsToScrollVertically = mTabDisplayLabelHeight;
- animateZoomAndFade = false;
- } else {
- final int pixelsOfPhotoLeft = Math.round(photoHeight) + scrollOffset;
- if (pixelsOfPhotoLeft > mTabDisplayLabelHeight) {
- // nothing to scroll
- pixelsToScrollVertically = 0;
- } else {
- pixelsToScrollVertically = mTabDisplayLabelHeight - pixelsOfPhotoLeft;
- }
- animateZoomAndFade = true;
- }
-
- if (pixelsToScrollVertically != 0) {
- // We can't animate ourselves here, because our own translation is needed for the user's
- // scrolling. Instead, we use our only child. As we are transparent, that is just as
- // good
- mTabAndShadowContainer.setTranslationY(-pixelsToScrollVertically);
- final ViewPropertyAnimator animator = mTabAndShadowContainer.animate();
- animator.translationY(0.0f);
- animator.setDuration(TRANSITION_MOVE_IN_TIME);
- }
-
- if (animateZoomAndFade) {
- // Hack: We have two types of possible layouts:
- // If the picture is square, it is square in both "with updates" and "without updates"
- // --> no need for scale animation here
- // example: 10inch tablet portrait
- // If the picture is non-square, it is full-width in "without updates" and something
- // arbitrary in "with updates"
- // --> do animation with container
- // example: 4.6inch phone portrait
- final boolean squarePicture =
- mTabWidthScreenWidthFraction == mTabHeightScreenWidthFraction;
- final int firstTransitionTime;
- if (squarePicture) {
- firstTransitionTime = 0;
- } else {
- // For x, we need to scale our container so we'll animate the whole tab
- // (unfortunately, we need to have the text invisible during this transition as it
- // would also be stretched)
- float revScale = 1.0f/mTabWidthScreenWidthFraction;
- mAboutTab.setScaleX(revScale);
- mAboutTab.setPivotX(0.0f);
- final ViewPropertyAnimator aboutAnimator = mAboutTab.animate();
- aboutAnimator.setDuration(TRANSITION_TIME);
- aboutAnimator.scaleX(1.0f);
-
- // For y, we need to scale only the picture itself because we want it to be cropped
- mPhotoView.setScaleY(revScale);
- mPhotoView.setPivotY(photoHeight * 0.5f);
- final ViewPropertyAnimator photoAnimator = mPhotoView.animate();
- photoAnimator.setDuration(TRANSITION_TIME);
- photoAnimator.scaleY(1.0f);
- firstTransitionTime = TRANSITION_TIME;
- }
-
- // Animate in the labels after the above transition is finished
- mAboutTab.fadeInLabelViewAnimator(firstTransitionTime, true);
- mUpdatesTab.fadeInLabelViewAnimator(firstTransitionTime, false);
-
- final float pixelsToTranslate = (1.0f - mTabWidthScreenWidthFraction) * width;
- // Views to translate
- for (View view : new View[] { mUpdatesTab, mTabDivider }) {
- view.setTranslationX(pixelsToTranslate);
- final ViewPropertyAnimator translateAnimator = view.animate();
- translateAnimator.translationX(0.0f);
- translateAnimator.setDuration(TRANSITION_TIME);
- }
-
- // Another hack: If the picture is square, there is no shadow in "Without updates"
- // --> fade it in after the translations are done
- if (squarePicture) {
- mShadow.setAlpha(0.0f);
- mShadow.animate().setStartDelay(TRANSITION_TIME).alpha(1.0f);
- }
- }
- }
-
- private void updateAlphaLayers() {
- float alpha = mLastScrollPosition * MAX_ALPHA / mAllowedHorizontalScrollLength;
- alpha = MoreMath.clamp(alpha, 0.0f, 1.0f);
- mAboutTab.setAlphaLayerValue(alpha);
- mUpdatesTab.setAlphaLayerValue(MAX_ALPHA - alpha);
- }
-
- @Override
- protected void onScrollChanged(int x, int y, int oldX, int oldY) {
- super.onScrollChanged(x, y, oldX, oldY);
-
- // Guard against framework issue where onScrollChanged() is called twice
- // for each touch-move event. This wreaked havoc on the tab-carousel: the
- // view-pager moved twice as fast as it should because we called fakeDragBy()
- // twice with the same value.
- if (mLastScrollPosition == x) return;
-
- // Since we never completely scroll the about/updates tabs off-screen,
- // the draggable range is less than the width of the carousel. Our
- // listeners don't care about this... if we scroll 75% percent of our
- // draggable range, they want to scroll 75% of the entire carousel
- // width, not the same number of pixels that we scrolled.
- int scaledL = (int) (x * mScrollScaleFactor);
- int oldScaledL = (int) (oldX * mScrollScaleFactor);
- mListener.onScrollChanged(scaledL, y, oldScaledL, oldY);
-
- mLastScrollPosition = x;
- updateAlphaLayers();
- }
-
- /**
- * Reset the carousel to the start position (i.e. because new data will be loaded in for a
- * different contact).
- */
- public void reset() {
- scrollTo(0, 0);
- setCurrentTab(0);
- moveToYCoordinate(0, 0);
- }
-
- /**
- * 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.
- */
- public void restoreYCoordinate() {
- setY(getStoredYCoordinateForTab(mCurrentTab));
- }
-
- /**
- * Request that the view move to the given Y coordinate. Also store the Y coordinate as the
- * last requested Y coordinate for the given tabIndex.
- */
- public void moveToYCoordinate(int tabIndex, float y) {
- setY(y);
- storeYCoordinate(tabIndex, y);
- }
-
- /**
- * Store this information as the last requested Y coordinate for the given tabIndex.
- */
- public void storeYCoordinate(int tabIndex, float y) {
- mYCoordinateArray[tabIndex] = y;
- }
-
- /**
- * Returns the stored Y coordinate of this view the last time the user was on the selected
- * tab given by tabIndex.
- */
- public float getStoredYCoordinateForTab(int tabIndex) {
- return mYCoordinateArray[tabIndex];
- }
-
- /**
- * Returns the number of pixels that this view can be scrolled horizontally.
- */
- public int getAllowedHorizontalScrollLength() {
- return mAllowedHorizontalScrollLength;
- }
-
- /**
- * Returns the number of pixels that this view can be scrolled vertically while still allowing
- * the tab labels to still show.
- */
- public int getAllowedVerticalScrollLength() {
- return mAllowedVerticalScrollLength;
- }
-
- /**
- * Updates the tab selection.
- */
- public void setCurrentTab(int position) {
- final CarouselTab selected, deselected;
-
- switch (position) {
- case TAB_INDEX_ABOUT:
- selected = mAboutTab;
- deselected = mUpdatesTab;
- break;
- case TAB_INDEX_UPDATES:
- selected = mUpdatesTab;
- deselected = mAboutTab;
- break;
- default:
- throw new IllegalStateException("Invalid tab position " + position);
- }
- selected.showSelectedState();
- selected.setOverlayClickable(false);
- deselected.showDeselectedState();
- deselected.setOverlayClickable(true);
- mCurrentTab = position;
- }
-
- /**
- * Loads the data from the Loader-Result. This is the only function that has to be called
- * from the outside to fully setup the View
- */
- public void loadData(Contact contactData) {
- if (contactData == null) return;
-
- // TODO: Move this into the {@link CarouselTab} class when the updates
- // fragment code is more finalized.
- final boolean expandOnClick = contactData.getPhotoUri() != null;
- final OnClickListener listener = mPhotoSetter.setupContactPhotoForClick(
- mContext, contactData, mPhotoView, expandOnClick);
-
- if (expandOnClick || contactData.isWritableContact(mContext)) {
- mPhotoViewOverlay.setOnClickListener(listener);
- } else {
- // Work around framework issue... if we instead use
- // setClickable(false), then we can't swipe horizontally.
- mPhotoViewOverlay.setOnClickListener(null);
- }
-
- ContactDetailDisplayUtils.setSocialSnippet(
- mContext, contactData, mStatusView, mStatusPhotoView);
- }
-
- /**
- * Set the given {@link Listener} to handle carousel events.
- */
- public void setListener(Listener listener) {
- mListener = listener;
- }
-
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- switch (event.getAction()) {
- case MotionEvent.ACTION_DOWN:
- mListener.onTouchDown();
- return true;
- case MotionEvent.ACTION_UP:
- mListener.onTouchUp();
- return true;
- }
- return super.onTouchEvent(event);
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- boolean interceptTouch = super.onInterceptTouchEvent(ev);
- if (interceptTouch) {
- mListener.onTouchDown();
- }
- return interceptTouch;
- }
-}
diff --git a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java b/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
deleted file mode 100644
index 71186fe..0000000
--- a/src/com/android/contacts/detail/ContactDetailUpdatesFragment.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.detail;
-
-import android.app.ListFragment;
-import android.content.ContentUris;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.ContactsContract.StreamItems;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView.OnScrollListener;
-import android.widget.ListView;
-
-import com.android.contacts.R;
-import com.android.contacts.activities.ContactDetailActivity.FragmentKeyListener;
-import com.android.contacts.detail.ContactDetailDisplayUtils.StreamPhotoTag;
-import com.android.contacts.util.StreamItemEntry;
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.Contact;
-import com.android.contacts.common.model.account.AccountType;
-
-public class ContactDetailUpdatesFragment extends ListFragment implements FragmentKeyListener {
-
- private static final String TAG = "ContactDetailUpdatesFragment";
-
- private Contact mContactData;
- private Uri mLookupUri;
-
- private LayoutInflater mInflater;
- private StreamItemAdapter mStreamItemAdapter;
-
- private OnScrollListener mVerticalScrollListener;
-
- /**
- * Listener on clicks on a stream item.
- * <p>
- * It assumes the view has a tag of type {@link StreamItemEntry} associated with it.
- */
- private final View.OnClickListener mStreamItemClickListener = new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- StreamItemEntry streamItemEntry = (StreamItemEntry) view.getTag();
- if (streamItemEntry == null) {
- // Ignore if this item does not have a stream item associated with it.
- return;
- }
- final AccountType accountType = getAccountTypeForStreamItemEntry(streamItemEntry);
-
- final Uri uri = ContentUris.withAppendedId(StreamItems.CONTENT_URI,
- streamItemEntry.getId());
- final Intent intent = new Intent(Intent.ACTION_VIEW, uri);
- intent.setClassName(accountType.syncAdapterPackageName,
- accountType.getViewStreamItemActivity());
- startActivity(intent);
- }
- };
-
- private final View.OnClickListener mStreamItemPhotoItemClickListener
- = new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- StreamPhotoTag tag = (StreamPhotoTag) view.getTag();
- if (tag == null) {
- return;
- }
- final AccountType accountType = getAccountTypeForStreamItemEntry(tag.streamItem);
-
- final Intent intent = new Intent(Intent.ACTION_VIEW, tag.getStreamItemPhotoUri());
- intent.setClassName(accountType.syncAdapterPackageName,
- accountType.getViewStreamItemPhotoActivity());
- startActivity(intent);
- }
- };
-
- private AccountType getAccountTypeForStreamItemEntry(StreamItemEntry streamItemEntry) {
- return AccountTypeManager.getInstance(getActivity()).getAccountType(
- streamItemEntry.getAccountType(), streamItemEntry.getDataSet());
- }
-
- public ContactDetailUpdatesFragment() {
- // Explicit constructor for inflation
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
- mInflater = inflater;
- return mInflater.inflate(R.layout.contact_detail_updates_fragment, container, false);
- }
-
- @Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- mStreamItemAdapter = new StreamItemAdapter(getActivity(), mStreamItemClickListener,
- mStreamItemPhotoItemClickListener);
- setListAdapter(mStreamItemAdapter);
- getListView().setOnScrollListener(mVerticalScrollListener);
- }
-
- public void setData(Uri lookupUri, Contact result) {
- if (result == null) {
- return;
- }
- mLookupUri = lookupUri;
- mContactData = result;
- }
-
- /**
- * Reset the list adapter in this {@link Fragment} to get rid of any saved scroll position
- * from a previous contact.
- */
- public void resetAdapter() {
- setListAdapter(mStreamItemAdapter);
- }
-
- @Override
- public boolean handleKeyDown(int keyCode) {
- return false;
- }
-
- public void setVerticalScrollListener(OnScrollListener listener) {
- mVerticalScrollListener = listener;
- }
-
- /**
- * Returns the top coordinate of the first item in the {@link ListView}. If the first item
- * in the {@link ListView} is not visible or there are no children in the list, then return
- * Integer.MIN_VALUE. Note that the returned value will be <= 0 because the first item in the
- * list cannot have a positive offset.
- */
- public int getFirstListItemOffset() {
- return ContactDetailDisplayUtils.getFirstListItemOffset(getListView());
- }
-
- /**
- * Tries to scroll the first item to the given offset (this can be a no-op if the list is
- * already in the correct position).
- * @param offset which should be <= 0
- */
- public void requestToMoveToOffset(int offset) {
- ContactDetailDisplayUtils.requestToMoveToOffset(getListView(), offset);
- }
-}
diff --git a/src/com/android/contacts/detail/ContactDetailViewPagerAdapter.java b/src/com/android/contacts/detail/ContactDetailViewPagerAdapter.java
deleted file mode 100644
index 4213490..0000000
--- a/src/com/android/contacts/detail/ContactDetailViewPagerAdapter.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * 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.detail;
-
-import android.os.Parcelable;
-import android.support.v4.view.PagerAdapter;
-import android.support.v4.view.ViewPager;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Adapter for the {@link ViewPager} for the contact detail page for a contact in 2 cases:
- * 1) without social updates, and 2) with social updates. The default initial case is for
- * the contact with social updates which uses all possible pages.
- */
-public class ContactDetailViewPagerAdapter extends PagerAdapter {
-
- public static final String ABOUT_FRAGMENT_TAG = "view-pager-about-fragment";
- public static final String UPDATES_FRAGMENT_TAG = "view-pager-updates-fragment";
-
- private static final int INDEX_ABOUT_FRAGMENT = 0;
- private static final int INDEX_UPDATES_FRAGMENT = 1;
-
- private static final int MAX_FRAGMENT_VIEW_COUNT = 2;
-
- /**
- * The initial value for the view count needs to be MAX_FRAGMENT_VIEW_COUNT,
- * otherwise anything smaller would break screen rotation functionality for a user viewing
- * a contact with social updates (i.e. the user was viewing the second page, rotates the
- * device, the view pager requires the second page to exist immediately on launch).
- */
- private int mFragmentViewCount = MAX_FRAGMENT_VIEW_COUNT;
-
- private View mAboutFragmentView;
- private View mUpdatesFragmentView;
-
- public ContactDetailViewPagerAdapter() {
- }
-
- public void setAboutFragmentView(View view) {
- mAboutFragmentView = view;
- }
-
- public void setUpdatesFragmentView(View view) {
- mUpdatesFragmentView = view;
- }
-
- /**
- * Enable swiping if the detail and update fragments should be showing. Otherwise diable
- * swiping if only the detail fragment should be showing.
- */
- public void enableSwipe(boolean enable) {
- mFragmentViewCount = enable ? MAX_FRAGMENT_VIEW_COUNT : 1;
- notifyDataSetChanged();
- }
-
- @Override
- public int getCount() {
- return mFragmentViewCount;
- }
-
- /** Gets called when the number of items changes. */
- @Override
- public int getItemPosition(Object object) {
- // Always return a valid index for the about fragment view because it's always shown
- // whether the contact has social updates or not.
- if (object == mAboutFragmentView) {
- return INDEX_ABOUT_FRAGMENT;
- }
- // Only return a valid index for the updates fragment view if our view count > 1.
- if (object == mUpdatesFragmentView && mFragmentViewCount > 1) {
- return INDEX_UPDATES_FRAGMENT;
- }
- // Otherwise the view should have no position.
- return POSITION_NONE;
- }
-
- @Override
- public void startUpdate(ViewGroup container) {
- }
-
- @Override
- public Object instantiateItem(ViewGroup container, int position) {
- switch (position) {
- case INDEX_ABOUT_FRAGMENT:
- mAboutFragmentView.setVisibility(View.VISIBLE);
- return mAboutFragmentView;
- case INDEX_UPDATES_FRAGMENT:
- mUpdatesFragmentView.setVisibility(View.VISIBLE);
- return mUpdatesFragmentView;
- }
- throw new IllegalArgumentException("Invalid position: " + position);
- }
-
- @Override
- public void destroyItem(ViewGroup container, int position, Object object) {
- ((View) object).setVisibility(View.GONE);
- }
-
- @Override
- public void finishUpdate(ViewGroup container) {
- }
-
- @Override
- public boolean isViewFromObject(View view, Object object) {
- return ((View) object) == view;
- }
-
- @Override
- public Parcelable saveState() {
- return null;
- }
-
- @Override
- public void restoreState(Parcelable state, ClassLoader loader) {
- }
-}
diff --git a/src/com/android/contacts/detail/StreamItemAdapter.java b/src/com/android/contacts/detail/StreamItemAdapter.java
deleted file mode 100644
index 6e1adc5..0000000
--- a/src/com/android/contacts/detail/StreamItemAdapter.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * 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.detail;
-
-import android.content.Context;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-
-import com.android.contacts.R;
-import com.android.contacts.common.model.AccountTypeManager;
-import com.android.contacts.common.model.account.AccountType;
-import com.android.contacts.util.StreamItemEntry;
-
-import com.google.common.collect.Lists;
-
-import java.util.List;
-
-/**
- * List adapter for stream items of a given contact.
- */
-public class StreamItemAdapter extends BaseAdapter {
- /** The header view, hidden under the tab carousel, if present. */
- private static final int ITEM_VIEW_TYPE_HEADER = 0;
- /** The updates in the list. */
- private static final int ITEM_VIEW_TYPE_STREAM_ITEM = 1;
-
- private final Context mContext;
- private final View.OnClickListener mItemClickListener;
- private final View.OnClickListener mPhotoClickListener;
- private final LayoutInflater mInflater;
-
- private List<StreamItemEntry> mStreamItems;
-
- public StreamItemAdapter(Context context, View.OnClickListener itemClickListener,
- View.OnClickListener photoClickListener) {
- mContext = context;
- mItemClickListener = itemClickListener;
- mPhotoClickListener = photoClickListener;
- mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mStreamItems = Lists.newArrayList();
- }
-
- @Override
- public int getCount() {
- // The header should only be included as items in the list if there are other
- // stream items.
- int count = mStreamItems.size();
- return (count == 0) ? 0 : (count + 1);
- }
-
- @Override
- public Object getItem(int position) {
- if (position == 0) {
- return null;
- }
- return mStreamItems.get(position - 1);
- }
-
- @Override
- public long getItemId(int position) {
- if (position == 0) {
- return -1;
- }
- return position - 1;
- }
-
- @Override
- public boolean isEnabled(int position) {
- // Make all list items disabled, so they're not clickable.
- // We make child views clickable in getvView() if the account type supports
- // viewStreamItemActivity or viewStreamItemPhotoActivity.
- return false;
- }
-
- @Override
- public boolean areAllItemsEnabled() {
- // See isEnabled().
- return false;
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- if (position == 0) {
- return mInflater.inflate(R.layout.updates_header_contact, null);
- }
- final StreamItemEntry streamItem = (StreamItemEntry) getItem(position);
- final AccountTypeManager manager = AccountTypeManager.getInstance(mContext);
- final AccountType accountType =
- manager.getAccountType(streamItem.getAccountType(), streamItem.getDataSet());
-
- final View view = ContactDetailDisplayUtils.createStreamItemView(
- mInflater, mContext, convertView, streamItem,
- // Only pass the photo click listener if the account type has the photo
- // view activity.
- (accountType.getViewStreamItemPhotoActivity() == null) ? null : mPhotoClickListener
- );
- final View contentView = view.findViewById(R.id.stream_item_content);
-
- // If the account type has the stream item view activity, make the stream container
- // clickable.
- if (accountType.getViewStreamItemActivity() != null) {
- contentView.setTag(streamItem);
- contentView.setFocusable(true);
- contentView.setOnClickListener(mItemClickListener);
- contentView.setEnabled(true);
- } else {
- contentView.setTag(null);
- contentView.setFocusable(false);
- contentView.setOnClickListener(null);
- // setOnClickListener makes it clickable, so we need to overwrite it.
- contentView.setClickable(false);
- contentView.setEnabled(false);
- }
- return view;
- }
-
- @Override
- public int getViewTypeCount() {
- // ITEM_VIEW_TYPE_HEADER and ITEM_VIEW_TYPE_STREAM_ITEM
- return 2;
- }
-
- @Override
- public int getItemViewType(int position) {
- if (position == 0) {
- return ITEM_VIEW_TYPE_HEADER;
- }
- return ITEM_VIEW_TYPE_STREAM_ITEM;
- }
-
- public void setStreamItems(List<StreamItemEntry> streamItems) {
- mStreamItems = streamItems;
- notifyDataSetChanged();
- }
-}
diff --git a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java b/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
deleted file mode 100644
index abd4680..0000000
--- a/tests/src/com/android/contacts/detail/StreamItemAdapterTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * 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.detail;
-
-import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.View;
-
-import com.android.contacts.util.StreamItemEntry;
-import com.android.contacts.util.StreamItemEntryBuilder;
-
-import com.google.common.collect.Lists;
-
-import java.util.ArrayList;
-
-// TODO: We should have tests for action, but that requires a mock sync-adapter that specifies
-// an action or doesn't
-
-// TODO Add test for photo click
-
-/**
- * Unit tests for {@link StreamItemAdapter}.
- */
-@SmallTest
-public class StreamItemAdapterTest extends AndroidTestCase {
- private StreamItemAdapter mAdapter;
- private FakeOnClickListener mListener;
- private FakeOnClickListener mPhotoListener;
- private View mView;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- mListener = new FakeOnClickListener();
- mAdapter = new StreamItemAdapter(getContext(), mListener, mPhotoListener);
- }
-
- @Override
- protected void tearDown() throws Exception {
- mAdapter = null;
- mListener = null;
- super.tearDown();
- }
-
- public void testGetCount_Empty() {
- mAdapter.setStreamItems(createStreamItemList(0));
- // The header and title are gone when there are no stream items.
- assertEquals(0, mAdapter.getCount());
- }
-
- public void testGetCount_NonEmpty() {
- mAdapter.setStreamItems(createStreamItemList(3));
- // There is one extra view: the header.
- assertEquals(4, mAdapter.getCount());
- }
-
- public void testGetView_Header() {
- // Just check that we can inflate it correctly.
- mView = mAdapter.getView(0, null, null);
- }
-
- /** Counter used by {@link #createStreamItemEntryBuilder()} to create unique builders. */
- private int mCreateStreamItemEntryBuilderCounter = 0;
-
- /** Returns a stream item builder with basic information in it. */
- private StreamItemEntryBuilder createStreamItemEntryBuilder() {
- return new StreamItemEntryBuilder().setText(
- "text #" + mCreateStreamItemEntryBuilderCounter++);
- }
-
- /** Creates a list containing the given number of {@link StreamItemEntry}s. */
- private ArrayList<StreamItemEntry> createStreamItemList(int count) {
- ArrayList<StreamItemEntry> list = Lists.newArrayList();
- for (int index = 0; index < count; ++index) {
- list.add(createStreamItemEntryBuilder().build(getContext()));
- }
- return list;
- }
-
- /** Checks that the stream item view has a click listener. */
- private void assertStreamItemViewHasOnClickListener() {
- assertFalse("listener should have not been invoked yet", mListener.clicked);
- mView.performClick();
- assertTrue("listener should have been invoked", mListener.clicked);
- }
-
- /** Checks that the stream item view does not have a click listener. */
- private void assertStreamItemViewHasNoOnClickListener() {
- assertFalse("listener should have not been invoked yet", mListener.clicked);
- mView.performClick();
- assertFalse("listener should have not been invoked", mListener.clicked);
- }
-
- /** Checks that the stream item view is clickable. */
- private void assertStreamItemViewFocusable() {
- assertNotNull("should have a stream item", mView);
- assertTrue("should be focusable", mView.isFocusable());
- }
-
- /** Asserts that there is a stream item but it is not clickable. */
- private void assertStreamItemViewNotFocusable() {
- assertNotNull("should have a stream item", mView);
- assertFalse("should not be focusable", mView.isFocusable());
- }
-
- /** Checks that the stream item view has the given stream item as its tag. */
- private void assertStreamItemViewHasTag(StreamItemEntry streamItem) {
- Object tag = mView.getTag();
- assertNotNull("should have a tag", tag);
- assertTrue("should be a StreamItemEntry", tag instanceof StreamItemEntry);
- StreamItemEntry streamItemTag = (StreamItemEntry) tag;
- // The streamItem itself should be in the tag.
- assertSame(streamItem, streamItemTag);
- }
-
- /** Checks that the stream item view has the given stream item as its tag. */
- private void assertStreamItemViewHasNoTag() {
- Object tag = mView.getTag();
- assertNull("should not have a tag", tag);
- }
-
- /**
- * Simple fake implementation of {@link View.OnClickListener} which sets a member variable to
- * true when clicked.
- */
- private final class FakeOnClickListener implements View.OnClickListener {
- public boolean clicked = false;
-
- @Override
- public void onClick(View view) {
- clicked = true;
- }
- }
-}