Pinned tab headers on contact card
- When vertically scrolling the contact details, move the
tab carousel vertically off the screen until just the
tabs are showing
- Make ViewPager span the entire height/width of the screen
- Make the tab carousel go on top of the ViewPager
Change-Id: I8e93fb64e8bb6d1749b371a030a36883fc57f0dd
diff --git a/res/layout/contact_detail_activity.xml b/res/layout/contact_detail_activity.xml
index 744f343..d840d6f 100644
--- a/res/layout/contact_detail_activity.xml
+++ b/res/layout/contact_detail_activity.xml
@@ -14,19 +14,24 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/contact_detail_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
+ <android.support.v4.view.ViewPager
+ android:id="@+id/pager"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
<com.android.contacts.detail.ContactDetailTabCarousel
android:id="@+id/tab_carousel"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
- <android.support.v4.view.ViewPager
- android:id="@+id/pager"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-</LinearLayout>
+</RelativeLayout>
diff --git a/res/layout/contact_detail_updates_fragment.xml b/res/layout/contact_detail_updates_fragment.xml
index 7baba42..f60be2a 100644
--- a/res/layout/contact_detail_updates_fragment.xml
+++ b/res/layout/contact_detail_updates_fragment.xml
@@ -28,6 +28,7 @@
android:textColor="?android:attr/textColorSecondary"
android:paddingLeft="10dip"
android:paddingRight="10dip"
- android:paddingTop="10dip"/>
+ android:paddingTop="@dimen/detail_tab_carousel_height"
+ android:layout_marginTop="10dip"/>
</LinearLayout>
diff --git a/res/layout/simple_contact_detail_header_view_list_item.xml b/res/layout/simple_contact_detail_header_view_list_item.xml
index 117aef1..1fd9ec5 100644
--- a/res/layout/simple_contact_detail_header_view_list_item.xml
+++ b/res/layout/simple_contact_detail_header_view_list_item.xml
@@ -24,7 +24,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:paddingTop="@dimen/detail_tab_carousel_height">
<TextView
android:id="@+id/phonetic_name"
diff --git a/src/com/android/contacts/activities/ContactDetailActivity.java b/src/com/android/contacts/activities/ContactDetailActivity.java
index 0dbc8df..1488bec 100644
--- a/src/com/android/contacts/activities/ContactDetailActivity.java
+++ b/src/com/android/contacts/activities/ContactDetailActivity.java
@@ -46,6 +46,8 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
import android.widget.Toast;
import java.util.ArrayList;
@@ -103,6 +105,7 @@
if (fragment instanceof ContactDetailAboutFragment) {
mAboutFragment = (ContactDetailAboutFragment) fragment;
mAboutFragment.setListener(mFragmentListener);
+ mAboutFragment.setVerticalScrollListener(mVerticalScrollListener);
mAboutFragment.loadUri(mUri);
} else if (fragment instanceof ContactDetailUpdatesFragment) {
mUpdatesFragment = (ContactDetailUpdatesFragment) fragment;
@@ -215,7 +218,8 @@
if (mViewPager.isFakeDragging()) {
return;
}
- int x = (int) ((position + positionOffset) * mTabCarousel.getAllowedScrollLength());
+ int x = (int) ((position + positionOffset) *
+ mTabCarousel.getAllowedHorizontalScrollLength());
mTabCarousel.scrollTo(x, 0);
}
@@ -269,6 +273,31 @@
}
};
+ private OnScrollListener mVerticalScrollListener = new OnScrollListener() {
+
+ @Override
+ public void onScroll(
+ AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
+ // Only re-position the tab carousel vertically if the FIRST item is still visible on
+ // the screen, otherwise the carousel should be in the correct place (pinned at the
+ // top).
+ if (firstVisibleItem != 0) {
+ return;
+ }
+ View topView = view.getChildAt(firstVisibleItem);
+ if (topView == null) {
+ return;
+ }
+ int amtToScroll = Math.max((int) view.getChildAt(firstVisibleItem).getY(),
+ -mTabCarousel.getAllowedVerticalScrollLength());
+ mTabCarousel.setY(amtToScroll);
+ }
+
+ @Override
+ public void onScrollStateChanged(AbsListView view, int scrollState) {}
+
+ };
+
/**
* This interface should be implemented by {@link Fragment}s within this
* activity so that the activity can determine whether the currently
diff --git a/src/com/android/contacts/detail/ContactDetailFragment.java b/src/com/android/contacts/detail/ContactDetailFragment.java
index 599a12e..74c05a5 100644
--- a/src/com/android/contacts/detail/ContactDetailFragment.java
+++ b/src/com/android/contacts/detail/ContactDetailFragment.java
@@ -94,6 +94,7 @@
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
+import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
@@ -120,6 +121,7 @@
private Context mContext;
private View mView;
+ private OnScrollListener mVerticalScrollListener;
private Uri mLookupUri;
private Listener mListener;
private NfcHandler mNfcHandler;
@@ -235,6 +237,7 @@
mListView.setScrollBarStyle(ListView.SCROLLBARS_OUTSIDE_OVERLAY);
mListView.setOnItemClickListener(this);
mListView.setOnItemLongClickListener(this);
+ mListView.setOnScrollListener(mVerticalScrollListener);
// Don't set it to mListView yet. We do so later when we bind the adapter.
mEmptyView = mView.findViewById(android.R.id.empty);
@@ -271,6 +274,10 @@
return mContactData;
}
+ public void setVerticalScrollListener(OnScrollListener listener) {
+ mVerticalScrollListener = listener;
+ }
+
public Uri getUri() {
return mLookupUri;
}
diff --git a/src/com/android/contacts/detail/ContactDetailTabCarousel.java b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
index a8803f5..dc3e126 100644
--- a/src/com/android/contacts/detail/ContactDetailTabCarousel.java
+++ b/src/com/android/contacts/detail/ContactDetailTabCarousel.java
@@ -55,7 +55,8 @@
private View[] mTabs = new View[2];
- private int mAllowedScrollLength;
+ private int mAllowedHorizontalScrollLength = Integer.MIN_VALUE;
+ private int mAllowedVerticalScrollLength = Integer.MIN_VALUE;
/**
* Interface for callbacks invoked when the user interacts with the carousel.
@@ -92,10 +93,13 @@
}
/**
- * Returns the number of pixels that this view can be scrolled.
+ * Returns the number of pixels that this view can be scrolled horizontally.
*/
- public int getAllowedScrollLength() {
- if (mAllowedScrollLength == 0) {
+ public int getAllowedHorizontalScrollLength() {
+ // We can't compute this in the constructor because the view widths are 0, so do the
+ // calculation only when this getter method is called (all the views should be created
+ // by this time).
+ if (mAllowedHorizontalScrollLength == Integer.MIN_VALUE) {
// Find the total length of two tabs side-by-side
int totalLength = 0;
for (int i=0; i < mTabs.length; i++) {
@@ -103,9 +107,27 @@
}
// Find the allowed scrolling length by subtracting the current visible screen width
// from the total length of the tabs.
- mAllowedScrollLength = totalLength - getWidth();
+ mAllowedHorizontalScrollLength = totalLength - getWidth();
}
- return mAllowedScrollLength;
+ 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() {
+ if (mAllowedVerticalScrollLength == Integer.MIN_VALUE) {
+ // Find the total height of a tab
+ View aboutView = findViewById(R.id.tab_about);
+ int totalHeight = aboutView.getHeight();
+ // Find the height of a tab label
+ TextView aboutTab = (TextView) aboutView.findViewById(R.id.label);
+ int labelHeight = aboutTab.getHeight();
+ // Find the allowed scrolling length by subtracting the two values
+ mAllowedVerticalScrollLength = totalHeight - labelHeight;
+ }
+ return mAllowedVerticalScrollLength;
}
/**