summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--res/layout/lists_fragment.xml36
-rw-r--r--res/layout/phone_favorites_fragment.xml1
-rw-r--r--res/layout/phone_favorites_menu.xml6
-rw-r--r--res/values/strings.xml22
-rw-r--r--src/com/android/dialer/DialtactsActivity.java113
-rw-r--r--src/com/android/dialer/list/ListsFragment.java100
-rw-r--r--src/com/android/dialer/list/PhoneFavoriteFragment.java27
-rw-r--r--src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java3
-rw-r--r--src/com/android/dialer/list/ViewPagerTabs.java169
9 files changed, 399 insertions, 78 deletions
diff --git a/res/layout/lists_fragment.xml b/res/layout/lists_fragment.xml
new file mode 100644
index 000000000..d4995e0f2
--- /dev/null
+++ b/res/layout/lists_fragment.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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:paddingTop="?android:attr/actionBarSize"
+ android:orientation="vertical"
+ android:id="@+id/lists_frame">
+ <com.android.dialer.list.ViewPagerTabs
+ android:id="@+id/lists_pager_header"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/actionBarSize"
+ android:textAllCaps="true"
+ android:orientation="horizontal"
+ android:layout_gravity="top"/>
+ <android.support.v4.view.ViewPager
+ android:id="@+id/lists_pager"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
+ </android.support.v4.view.ViewPager>
+</LinearLayout>
diff --git a/res/layout/phone_favorites_fragment.xml b/res/layout/phone_favorites_fragment.xml
index 91acb9058..7a1f05ae6 100644
--- a/res/layout/phone_favorites_fragment.xml
+++ b/res/layout/phone_favorites_fragment.xml
@@ -35,7 +35,6 @@
android:id="@+id/contact_tile_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="?android:attr/actionBarSize"
android:clipToPadding="false"
android:fadingEdge="none"
android:divider="@null" />
diff --git a/res/layout/phone_favorites_menu.xml b/res/layout/phone_favorites_menu.xml
index 387ea5b3f..0f7aa219e 100644
--- a/res/layout/phone_favorites_menu.xml
+++ b/res/layout/phone_favorites_menu.xml
@@ -16,11 +16,13 @@
-->
<!-- The phone favorites menu appears on the main dialer screen above the favorite callers area,
- and provides access to the All Contacts list. -->
+ and provides access to the All Contacts list. This is 1dp tall as a temporary hack to hide
+ it because it is no longer being used. It should be removed from its parent adapter entirely
+ eventually. -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/phone_favorites_menu"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="1dp"
android:paddingLeft="@dimen/favorites_menu_padding_horizontal"
android:paddingRight="@dimen/favorites_menu_padding_horizontal"
android:paddingTop="@dimen/favorites_menu_padding_top"
diff --git a/res/values/strings.xml b/res/values/strings.xml
index c608273ff..d67c788da 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -624,14 +624,6 @@
[CHAR LIMIT=30] -->
<string name="dialer_hint_find_contact">Type a name or phone number</string>
- <!-- Title for the call log tab containing the list of all voicemails and calls
- [CHAR LIMIT=15] -->
- <string name="call_log_all_title">All</string>
-
- <!-- Title for the call log tab containing the list of all missed calls only
- [CHAR LIMIT=15] -->
- <string name="call_log_missed_title">Missed</string>
-
<!-- String resource for the font-family to use for the call log activity's title
Do not translate. -->
<string name="call_log_activity_title_font_family">sans-serif-light</string>
@@ -705,6 +697,20 @@
<!-- Do not translate. -->
<string name="dialpad_pound_letters"></string>
+ <!-- Title for the call log tab containing the list of all voicemails and calls
+ [CHAR LIMIT=15] -->
+ <string name="call_log_all_title">All</string>
+
+ <!-- Title for the call log tab containing the list of all missed calls only
+ [CHAR LIMIT=15] -->
+ <string name="call_log_missed_title">Missed</string>
+
+ <string name="tab_speed_dial">Speed Dial</string>
+
+ <string name="tab_recents">Recents</string>
+
+ <string name="tab_all_contacts">Contacts</string>
+
<!-- Title of fragment that displays all contacts -->
<string name="show_all_contacts_title">All contacts</string>
<!-- Title of show all contacts button -->
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index c59db95dc..8b9b71ada 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -71,6 +71,7 @@ import com.android.dialer.dialpad.SmartDialPrefix;
import com.android.dialer.interactions.PhoneNumberInteraction;
import com.android.dialer.list.AllContactsActivity;
import com.android.dialer.list.DragDropController;
+import com.android.dialer.list.ListsFragment;
import com.android.dialer.list.OnDragDropListener;
import com.android.dialer.list.OnListFragmentScrolledListener;
import com.android.dialer.list.PhoneFavoriteFragment;
@@ -94,7 +95,8 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
DialpadFragment.HostInterface,
PhoneFavoriteFragment.OnShowAllContactsListener,
PhoneFavoriteFragment.HostInterface,
- OnDragDropListener, View.OnLongClickListener {
+ OnDragDropListener, View.OnLongClickListener,
+ OnPhoneNumberPickerActionListener {
private static final String TAG = "DialtactsActivity";
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -129,11 +131,6 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
private static final int ANIMATION_DURATION = 250;
/**
- * The main fragment displaying the user's favorites and frequent contacts
- */
- private PhoneFavoriteFragment mPhoneFavoriteFragment;
-
- /**
* Fragment containing the dialpad that slides into view
*/
private DialpadFragment mDialpadFragment;
@@ -148,6 +145,11 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
*/
private SmartDialSearchFragment mSmartDialSearchFragment;
+ /**
+ * Fragment containing the speed dial list, recents list, and all contacts list.
+ */
+ private ListsFragment mListsFragment;
+
private View mFakeActionBar;
private View mMenuButton;
private View mCallHistoryButton;
@@ -188,6 +190,21 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
private DialerDatabaseHelper mDialerDatabaseHelper;
+ private class OverflowPopupMenu extends PopupMenu {
+ public OverflowPopupMenu(Context context, View anchor) {
+ super(context, anchor);
+ }
+
+ @Override
+ public void show() {
+ final Menu menu = getMenu();
+ final MenuItem clearFrequents = menu.findItem(R.id.menu_clear_frequents);
+ // TODO: Check mPhoneFavoriteFragment.hasFrequents()
+ clearFrequents.setVisible(true);
+ super.show();
+ }
+ }
+
/**
* Listener used when one of phone numbers in search UI is selected. This will initiate a
* phone call using the phone number.
@@ -287,7 +304,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
// is null. Otherwise the fragment manager takes care of recreating these fragments.
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
- .add(R.id.dialtacts_frame, new PhoneFavoriteFragment(), TAG_FAVORITES_FRAGMENT)
+ .add(R.id.dialtacts_frame, new ListsFragment(), TAG_FAVORITES_FRAGMENT)
.add(R.id.dialtacts_container, new DialpadFragment(), TAG_DIALPAD_FRAGMENT)
.commit();
} else {
@@ -369,12 +386,8 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
if (mFragmentsFrame != null) {
mFragmentsFrame.setAlpha(1.0f);
}
- } else if (fragment instanceof PhoneFavoriteFragment) {
- mPhoneFavoriteFragment = (PhoneFavoriteFragment) fragment;
- mPhoneFavoriteFragment.setListener(mPhoneFavoriteListener);
- if (mFragmentsFrame != null) {
- mFragmentsFrame.setAlpha(1.0f);
- }
+ } else if (fragment instanceof ListsFragment) {
+ mListsFragment = (ListsFragment) fragment;
}
}
@@ -582,7 +595,7 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
.setInterpolator(hideActionBarInterpolator).setDuration(ANIMATION_DURATION);
}
- if (mPhoneFavoriteFragment != null && mPhoneFavoriteFragment.isVisible()) {
+ if (mListsFragment != null && mListsFragment.isVisible()) {
// If the favorites fragment is showing, fade to blank.
mFragmentsFrame.animate().alpha(0.0f);
}
@@ -608,12 +621,20 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
.setInterpolator(showActionBarInterpolator).setDuration(ANIMATION_DURATION);
}
- if (mPhoneFavoriteFragment != null && mPhoneFavoriteFragment.isVisible()) {
+ if (mListsFragment != null && mListsFragment.isVisible()) {
mFragmentsFrame.animate().alpha(1.0f);
}
getActionBar().show();
}
+ private void hideInputMethod(View view) {
+ final InputMethodManager imm = (InputMethodManager) getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ if (imm != null && view != null) {
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+ }
+ }
+
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if (DEBUG) {
@@ -711,29 +732,6 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
return !isDialIntent(getIntent()) ? CALL_ORIGIN_DIALTACTS : null;
}
- private final PhoneFavoriteFragment.Listener mPhoneFavoriteListener =
- new PhoneFavoriteFragment.Listener() {
- @Override
- public void onContactSelected(Uri contactUri) {
- PhoneNumberInteraction.startInteractionForPhoneCall(
- DialtactsActivity.this, contactUri, getCallOrigin());
- }
-
- @Override
- public void onCallNumberDirectly(String phoneNumber) {
- Intent intent = CallUtil.getCallIntent(phoneNumber, getCallOrigin());
- startActivity(intent);
- }
- };
-
- private void hideInputMethod(View view) {
- final InputMethodManager imm = (InputMethodManager) getSystemService(
- Context.INPUT_METHOD_SERVICE);
- if (imm != null && view != null) {
- imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
- }
- }
-
/**
* Shows the search fragment
*/
@@ -752,12 +750,10 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
final FragmentTransaction transaction = getFragmentManager().beginTransaction();
SearchFragment fragment;
- if (mInDialpadSearch) {
+ if (mInDialpadSearch && mSmartDialSearchFragment != null) {
transaction.remove(mSmartDialSearchFragment);
- } else if (mInRegularSearch) {
+ } else if (mInRegularSearch && mRegularSearchFragment != null) {
transaction.remove(mRegularSearchFragment);
- } else {
- transaction.remove(mPhoneFavoriteFragment);
}
final String tag;
@@ -860,19 +856,10 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
@Override
public void onListFragmentScroll(int firstVisibleItem, int visibleItemCount,
int totalItemCount) {
-
- // Hide the action bar when scrolling down in the speed dial list, and show it again when
- // scrolling back up.
- if (firstVisibleItem > mPreviousFirstVisibleItem) {
- getActionBar().hide();
- } else if (firstVisibleItem < mPreviousFirstVisibleItem) {
- getActionBar().show();
- }
- mPreviousFirstVisibleItem = firstVisibleItem;
+ // TODO: No-op for now. This should eventually show/hide the actionBar based on
+ // interactions with the ListsFragments.
}
- private int mPreviousFirstVisibleItem = 0;
-
@Override
public void setDialButtonEnabled(boolean enabled) {
if (mDialButton != null) {
@@ -943,4 +930,24 @@ public class DialtactsActivity extends TransactionSafeActivity implements View.O
public void setDragDropController(DragDropController dragController) {
mRemoveViewContainer.setDragDropController(dragController);
}
+
+ @Override
+ public void onPickPhoneNumberAction(Uri dataUri) {
+ mPhoneNumberPickerActionListener.onPickPhoneNumberAction(dataUri);
+ }
+
+ @Override
+ public void onCallNumberDirectly(String phoneNumber) {
+ mPhoneNumberPickerActionListener.onCallNumberDirectly(phoneNumber);
+ }
+
+ @Override
+ public void onShortcutIntentCreated(Intent intent) {
+ mPhoneNumberPickerActionListener.onShortcutIntentCreated(intent);
+ }
+
+ @Override
+ public void onHomeInActionBarSelected() {
+ mPhoneNumberPickerActionListener.onHomeInActionBarSelected();
+ }
}
diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java
new file mode 100644
index 000000000..768d3601e
--- /dev/null
+++ b/src/com/android/dialer/list/ListsFragment.java
@@ -0,0 +1,100 @@
+package com.android.dialer.list;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.os.Bundle;
+import android.support.v13.app.FragmentPagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
+import com.android.dialer.R;
+
+/**
+ * Fragment that is used as the main screen of the Dialer.
+ *
+ * Contains a ViewPager that contains various contact lists like the Speed Dial list and the
+ * All Contacts list. This will also eventually contain the logic that allows sliding the
+ * ViewPager containing the lists up above the shortcut cards and pin it against the top of the
+ * screen.
+ */
+public class ListsFragment extends Fragment {
+
+ private ViewPager mViewPager;
+ private ViewPagerAdapter mViewPagerAdapter;
+ private PhoneFavoriteFragment mSpeedDialFragment;
+ private AllContactsFragment mAllContactsFragment;
+
+ private OnPhoneNumberPickerActionListener mNumberPickerListener;
+
+ private static final int TAB_INDEX_SPEED_DIAL = 0;
+ private static final int TAB_INDEX_ALL_CONTACTS = 1;
+
+ private String[] mTabTitles;
+
+ private static final int TAB_INDEX_COUNT = 2;
+
+ public class ViewPagerAdapter extends FragmentPagerAdapter {
+ public ViewPagerAdapter(FragmentManager fm) {
+ super(fm);
+ }
+
+ @Override
+ public Fragment getItem(int position) {
+ switch (position) {
+ case TAB_INDEX_SPEED_DIAL:
+ mSpeedDialFragment = new PhoneFavoriteFragment();
+ return mSpeedDialFragment;
+ case TAB_INDEX_ALL_CONTACTS:
+ mAllContactsFragment = new AllContactsFragment();
+ mAllContactsFragment.setOnPhoneNumberPickerActionListener(
+ mNumberPickerListener);
+ return mAllContactsFragment;
+ }
+ throw new IllegalStateException("No fragment at position " + position);
+ }
+
+ @Override
+ public int getCount() {
+ return TAB_INDEX_COUNT;
+ }
+
+ @Override
+ public CharSequence getPageTitle(int position) {
+ return mTabTitles[position];
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ final View parentView = inflater.inflate(R.layout.lists_fragment, container, false);
+ mViewPager = (ViewPager) parentView.findViewById(R.id.lists_pager);
+ mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
+ mViewPager.setAdapter(mViewPagerAdapter);
+ mViewPager.setOffscreenPageLimit(1);
+
+ mTabTitles = new String[TAB_INDEX_COUNT];
+ mTabTitles[TAB_INDEX_SPEED_DIAL] = getResources().getString(R.string.tab_speed_dial);
+ mTabTitles[TAB_INDEX_ALL_CONTACTS] = getResources().getString(R.string.tab_all_contacts);
+
+ ViewPagerTabs tabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header);
+ tabs.setViewPager(mViewPager);
+ return parentView;
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+
+ try {
+ mNumberPickerListener = (OnPhoneNumberPickerActionListener) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString()
+ + " must implement OnPhoneNumberPickerActionListener");
+ }
+ }
+}
diff --git a/src/com/android/dialer/list/PhoneFavoriteFragment.java b/src/com/android/dialer/list/PhoneFavoriteFragment.java
index a56c3c546..c0dbd8ca5 100644
--- a/src/com/android/dialer/list/PhoneFavoriteFragment.java
+++ b/src/com/android/dialer/list/PhoneFavoriteFragment.java
@@ -51,6 +51,7 @@ import com.android.contacts.common.GeoUtil;
import com.android.contacts.common.list.ContactEntry;
import com.android.contacts.common.list.ContactListItemView;
import com.android.contacts.common.list.ContactTileView;
+import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
import com.android.dialer.DialtactsActivity;
import com.android.dialer.R;
import com.android.dialer.calllog.CallLogAdapter;
@@ -102,11 +103,6 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
public void onShowAllContacts();
}
- public interface Listener {
- public void onContactSelected(Uri contactUri);
- public void onCallNumberDirectly(String phoneNumber);
- }
-
public interface HostInterface {
public void setDragDropController(DragDropController controller);
}
@@ -155,15 +151,15 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
private class ContactTileAdapterListener implements ContactTileView.Listener {
@Override
public void onContactSelected(Uri contactUri, Rect targetRect) {
- if (mListener != null) {
- mListener.onContactSelected(contactUri);
+ if (mPhoneNumberPickerActionListener != null) {
+ mPhoneNumberPickerActionListener.onPickPhoneNumberAction(contactUri);
}
}
@Override
public void onCallNumberDirectly(String phoneNumber) {
- if (mListener != null) {
- mListener.onCallNumberDirectly(phoneNumber);
+ if (mPhoneNumberPickerActionListener != null) {
+ mPhoneNumberPickerActionListener.onCallNumberDirectly(phoneNumber);
}
}
@@ -189,7 +185,7 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
}
}
- private Listener mListener;
+ private OnPhoneNumberPickerActionListener mPhoneNumberPickerActionListener;
private OnListFragmentScrolledListener mActivityScrollListener;
private OnShowAllContactsListener mShowAllContactsListener;
@@ -362,6 +358,13 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
+ " must implement OnDragDropListener and HostInterface");
}
+ try {
+ mPhoneNumberPickerActionListener = (OnPhoneNumberPickerActionListener) activity;
+ } catch (ClassCastException e) {
+ throw new ClassCastException(activity.toString()
+ + " must implement PhoneFavoritesFragment.listener");
+ }
+
// Use initLoader() instead of restartLoader() to refraining unnecessary reload.
// This method call implicitly assures ContactTileLoaderListener's onLoadFinished() will
// be called, on which we'll check if "all" contacts should be reloaded again or not.
@@ -391,10 +394,6 @@ public class PhoneFavoriteFragment extends Fragment implements OnItemClickListen
mShowAllContactsListener.onShowAllContacts();
}
- public void setListener(Listener listener) {
- mListener = listener;
- }
-
@Override
public void onVoicemailStatusFetched(Cursor statusCursor) {
// no-op
diff --git a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java
index 81d682b8b..849d6514a 100644
--- a/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java
+++ b/src/com/android/dialer/list/PhoneFavoriteMergedAdapter.java
@@ -115,6 +115,9 @@ public class PhoneFavoriteMergedAdapter extends BaseAdapter {
mCallLogAdapter.registerDataSetObserver(mObserver);
mContactTileAdapter.registerDataSetObserver(mObserver);
mPhoneFavoritesMenu = phoneFavoritesMenu;
+ // Temporary hack to hide the favorites menu because it is not being used.
+ // It should be removed from this adapter entirely eventually.
+ mPhoneFavoritesMenu.setVisibility(View.GONE);
mTileInteractionTeaserView = tileInteractionTeaserView;
mCallLogQueryHandler = new CallLogQueryHandler(mContext.getContentResolver(),
mCallLogQueryHandlerListener);
diff --git a/src/com/android/dialer/list/ViewPagerTabs.java b/src/com/android/dialer/list/ViewPagerTabs.java
new file mode 100644
index 000000000..45f468ddd
--- /dev/null
+++ b/src/com/android/dialer/list/ViewPagerTabs.java
@@ -0,0 +1,169 @@
+package com.android.dialer.list;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.content.res.TypedArray;
+import android.support.v4.view.PagerAdapter;
+import android.support.v4.view.ViewPager;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.HorizontalScrollView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.dialer.R;
+
+/**
+ * Lightweight implementation of ViewPager tabs. This looks similar to traditional actionBar tabs,
+ * but allows for the view containing the tabs to be placed anywhere on screen. Text-related
+ * attributes can also be assigned in XML - these will get propogated to the child TextViews
+ * automatically.
+ */
+public class ViewPagerTabs extends HorizontalScrollView implements ViewPager.OnPageChangeListener {
+
+ ViewPager mPager;
+ /**
+ * Linearlayout that will contain the TextViews serving as tabs. This is the only child
+ * of the parent HorizontalScrollView.
+ */
+ LinearLayout mChild;
+ final ColorStateList mTextColor;
+ final int mTextSize;
+ final boolean mTextAllCaps;
+ int mPrevSelected = -1;
+ int mSidePadding;
+
+ private static final int TAB_SIDE_PADDING_IN_DPS = 10;
+
+ private static final int[] ATTRS = new int[] {
+ android.R.attr.textAppearance,
+ android.R.attr.textSize,
+ android.R.attr.textColor,
+ android.R.attr.textAllCaps
+ };
+
+ /**
+ * Simulates actionbar tab behavior by showing a toast with the tab title when long clicked.
+ */
+ private class OnTabLongClickListener implements OnLongClickListener {
+ final int mPosition;
+
+ public OnTabLongClickListener(int position) {
+ mPosition = position;
+ }
+
+ @Override
+ public boolean onLongClick(View v) {
+ final int[] screenPos = new int[2];
+ getLocationOnScreen(screenPos);
+
+ final Context context = getContext();
+ final int width = getWidth();
+ final int height = getHeight();
+ final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
+
+ Toast toast = Toast.makeText(context, mPager.getAdapter().getPageTitle(mPosition),
+ Toast.LENGTH_SHORT);
+
+ // Show the toast under the tab
+ toast.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL,
+ (screenPos[0] + width / 2) - screenWidth / 2, screenPos[1] + height);
+
+ toast.show();
+ return true;
+ }
+ }
+
+ public ViewPagerTabs(Context context) {
+ this(context, null);
+ }
+
+ public ViewPagerTabs(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ViewPagerTabs(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ setFillViewport(true);
+
+ mSidePadding = (int) (getResources().getDisplayMetrics().density * TAB_SIDE_PADDING_IN_DPS);
+
+ final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
+ mTextSize = a.getDimensionPixelSize(1, 0);
+ mTextColor = a.getColorStateList(2);
+ mTextAllCaps = a.getBoolean(3, false);
+
+ mChild = new LinearLayout(context);
+ addView(mChild,
+ new FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT));
+ }
+
+ public void setViewPager(ViewPager viewPager) {
+ mPager = viewPager;
+ mPager.setOnPageChangeListener(this);
+ addTabs(mPager.getAdapter());
+ }
+
+ private void addTabs(PagerAdapter adapter) {
+ final int count = adapter.getCount();
+ for (int i = 0; i < count; i++) {
+ addTab(adapter.getPageTitle(i), i);
+ }
+ }
+
+ private void addTab(CharSequence tabTitle, final int position) {
+ final TextView textView = new TextView(getContext());
+ textView.setText(tabTitle);
+ textView.setBackgroundResource(R.drawable.action_bar_tab);
+ textView.setGravity(Gravity.CENTER);
+ textView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPager.setCurrentItem(position);
+ }
+ });
+
+ textView.setOnLongClickListener(new OnTabLongClickListener(position));
+
+ // Assign various text appearance related attributes to child views.
+ if (mTextSize > 0) {
+ textView.setTextSize(mTextSize);
+ }
+ if (mTextColor != null) {
+ textView.setTextColor(mTextColor);
+ }
+ textView.setAllCaps(mTextAllCaps);
+ textView.setPadding(mSidePadding, 0, mSidePadding, 0);
+ mChild.addView(textView, new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.MATCH_PARENT, 1));
+ // Default to the first child being selected
+ if (position == 0) {
+ mPrevSelected = 0;
+ textView.setSelected(true);
+ }
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ if (mPrevSelected >= 0) {
+ mChild.getChildAt(mPrevSelected).setSelected(false);
+ }
+ final View selectedChild = mChild.getChildAt(position);
+ selectedChild.setSelected(true);
+ // Update scroll position
+ final int scrollPos = selectedChild.getLeft() - (getWidth() - selectedChild.getWidth()) / 2;
+ smoothScrollTo(scrollPos, 0);
+ mPrevSelected = position;
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
+} \ No newline at end of file