Animate floating action button
DialtactsActivity now implements ViewPager.OnPageChangeListener,
so that it can animate the floating action button in response
to page changed events in ListsFragments. Because ViewPagerTabs
also needs to listen to page changed events and ViewPager only
supports one OnPageChangeListener, ListsFragments is now in charge
of listening to page changed events from ViewPager and firing off
the same events to multiple OnpageChangedListeners
Bug: 14281810
Change-Id: Ic9b7ca8669d3a9cc0a997a84afe6788d6fd51bb9
diff --git a/res/layout/dialtacts_activity.xml b/res/layout/dialtacts_activity.xml
index 50049af..172b110 100644
--- a/res/layout/dialtacts_activity.xml
+++ b/res/layout/dialtacts_activity.xml
@@ -22,6 +22,7 @@
android:focusable="true"
android:focusableInTouchMode="true"
android:clipChildren="false"
+ android:animateLayoutChanges="true"
android:background="@color/background_dialer_light"
>
<RelativeLayout
@@ -119,6 +120,7 @@
<FrameLayout
android:layout_height="@dimen/floating_action_button_height"
android:layout_width="@dimen/floating_action_button_width"
+ android:layout_marginRight="@dimen/floating_action_button_margin_right"
android:layout_marginBottom="@dimen/floating_action_button_margin_bottom"
android:id="@+id/floating_action_button"
android:background="@color/actionbar_background_color"
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 2fe7677..66b36a7 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -65,6 +65,8 @@
<!-- Match call_button_height to Phone's dimens/in_call_end_button_height -->
<dimen name="call_button_height">74dp</dimen>
+ <!-- Right margin of the floating action button -->
+ <dimen name="floating_action_button_margin_right">10dp</dimen>
<!-- Bottom margin of the floating action button -->
<dimen name="floating_action_button_margin_bottom">10dp</dimen>
diff --git a/src/com/android/dialer/DialtactsActivity.java b/src/com/android/dialer/DialtactsActivity.java
index 3603696..1b4002c 100644
--- a/src/com/android/dialer/DialtactsActivity.java
+++ b/src/com/android/dialer/DialtactsActivity.java
@@ -17,6 +17,7 @@
package com.android.dialer;
import android.animation.Animator;
+import android.animation.LayoutTransition;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
@@ -38,9 +39,11 @@
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents;
import android.speech.RecognizerIntent;
+import android.support.v4.view.ViewPager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
+import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
@@ -54,8 +57,10 @@
import android.view.animation.Interpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.AbsListView.OnScrollListener;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
+import android.widget.RelativeLayout;
import android.widget.SearchView;
import android.widget.SearchView.OnQueryTextListener;
import android.widget.Toast;
@@ -99,7 +104,8 @@
ListsFragment.HostInterface,
SpeedDialFragment.HostInterface,
OnDragDropListener, View.OnLongClickListener,
- OnPhoneNumberPickerActionListener {
+ OnPhoneNumberPickerActionListener,
+ ViewPager.OnPageChangeListener {
private static final String TAG = "DialtactsActivity";
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -166,6 +172,11 @@
private boolean mClearSearchOnPause;
/**
+ * The position of the currently selected tab in the attached {@link ListsFragment}.
+ */
+ private int mCurrentTabPosition = 0;
+
+ /**
* True if the dialpad is only temporarily showing due to being in call
*/
private boolean mInCallDialpadUp;
@@ -327,6 +338,9 @@
mFirstLaunch = savedInstanceState.getBoolean(KEY_FIRST_LAUNCH);
}
+ RelativeLayout parent = (RelativeLayout) findViewById(R.id.dialtacts_mainlayout);
+ parent.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
+
mFragmentsFrame = findViewById(R.id.dialtacts_frame);
mFloatingActionButton = findViewById(R.id.floating_action_button);
@@ -398,6 +412,7 @@
}
} else if (fragment instanceof ListsFragment) {
mListsFragment = (ListsFragment) fragment;
+ mListsFragment.addOnPageChangeListener(this);
}
}
@@ -590,6 +605,7 @@
mFragmentsFrame.animate().alpha(0.0f);
}
getActionBar().hide();
+ alignFloatingActionButtonMiddle();
}
/**
@@ -614,6 +630,7 @@
mFragmentsFrame.animate().alpha(1.0f);
}
getActionBar().show();
+ alignFloatingActionButtonByTab(mCurrentTabPosition);
}
private void hideInputMethod(View view) {
@@ -953,4 +970,43 @@
public int getActionBarHeight() {
return mActionBarHeight;
}
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ mCurrentTabPosition = position;
+ alignFloatingActionButtonByTab(mCurrentTabPosition);
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ }
+
+ private void alignFloatingActionButtonByTab(int position) {
+ if (position == ListsFragment.TAB_INDEX_SPEED_DIAL) {
+ alignFloatingActionButtonMiddle();
+ } else {
+ alignFloatingActionButtonRight();
+ }
+ }
+
+ private void alignFloatingActionButtonRight() {
+ final RelativeLayout.LayoutParams params =
+ (RelativeLayout.LayoutParams) mFloatingActionButton.getLayoutParams();
+ params.removeRule(RelativeLayout.CENTER_HORIZONTAL);
+ params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ mFloatingActionButton.setLayoutParams(params);
+ }
+
+ private void alignFloatingActionButtonMiddle() {
+ final RelativeLayout.LayoutParams params =
+ (RelativeLayout.LayoutParams) mFloatingActionButton.getLayoutParams();
+ params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
+ params.addRule(RelativeLayout.CENTER_HORIZONTAL);
+ mFloatingActionButton.setLayoutParams(params);
+ }
}
diff --git a/src/com/android/dialer/list/ListsFragment.java b/src/com/android/dialer/list/ListsFragment.java
index 676b3b0..a61d8a5 100644
--- a/src/com/android/dialer/list/ListsFragment.java
+++ b/src/com/android/dialer/list/ListsFragment.java
@@ -14,6 +14,7 @@
import android.provider.CallLog;
import android.support.v13.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
+import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -22,6 +23,7 @@
import com.android.contacts.common.GeoUtil;
import com.android.dialer.DialtactsActivity;
+
import android.view.View.OnClickListener;
import com.android.dialer.R;
@@ -32,6 +34,8 @@
import com.android.dialer.calllog.ContactInfoHelper;
import com.android.dialerbind.ObjectFactory;
+import java.util.ArrayList;
+
/**
* Fragment that is used as the main screen of the Dialer.
*
@@ -41,11 +45,11 @@
* screen.
*/
public class ListsFragment extends Fragment implements CallLogQueryHandler.Listener,
- CallLogAdapter.CallFetcher {
+ CallLogAdapter.CallFetcher, ViewPager.OnPageChangeListener {
- private static final int TAB_INDEX_SPEED_DIAL = 0;
- private static final int TAB_INDEX_RECENTS = 1;
- private static final int TAB_INDEX_ALL_CONTACTS = 2;
+ public static final int TAB_INDEX_SPEED_DIAL = 0;
+ public static final int TAB_INDEX_RECENTS = 1;
+ public static final int TAB_INDEX_ALL_CONTACTS = 2;
private static final int TAB_INDEX_COUNT = 3;
@@ -64,10 +68,13 @@
}
private ViewPager mViewPager;
+ private ViewPagerTabs mViewPagerTabs;
private ViewPagerAdapter mViewPagerAdapter;
private SpeedDialFragment mSpeedDialFragment;
private CallLogFragment mRecentsFragment;
private AllContactsFragment mAllContactsFragment;
+ private ArrayList<OnPageChangeListener> mOnPageChangeListeners =
+ new ArrayList<OnPageChangeListener>();
private String[] mTabTitles;
@@ -204,14 +211,16 @@
mViewPagerAdapter = new ViewPagerAdapter(getChildFragmentManager());
mViewPager.setAdapter(mViewPagerAdapter);
mViewPager.setOffscreenPageLimit(2);
+ mViewPager.setOnPageChangeListener(this);
mTabTitles = new String[TAB_INDEX_COUNT];
mTabTitles[TAB_INDEX_SPEED_DIAL] = getResources().getString(R.string.tab_speed_dial);
mTabTitles[TAB_INDEX_RECENTS] = getResources().getString(R.string.tab_recents);
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);
+ mViewPagerTabs = (ViewPagerTabs) parentView.findViewById(R.id.lists_pager_header);
+ mViewPagerTabs.setViewPager(mViewPager);
+ addOnPageChangeListener(mViewPagerTabs);
final ListView shortcutCardsListView =
(ListView) parentView.findViewById(R.id.shortcut_card_list);
@@ -255,4 +264,35 @@
.apply();
fetchCalls();
}
+
+ public void addOnPageChangeListener(OnPageChangeListener onPageChangeListener) {
+ if (!mOnPageChangeListeners.contains(onPageChangeListener)) {
+ mOnPageChangeListeners.add(onPageChangeListener);
+ }
+ }
+
+ @Override
+ public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+ final int count = mOnPageChangeListeners.size();
+ for (int i = 0; i < count; i++) {
+ mOnPageChangeListeners.get(i).onPageScrolled(position, positionOffset,
+ positionOffsetPixels);
+ }
+ }
+
+ @Override
+ public void onPageSelected(int position) {
+ final int count = mOnPageChangeListeners.size();
+ for (int i = 0; i < count; i++) {
+ mOnPageChangeListeners.get(i).onPageSelected(position);
+ }
+ }
+
+ @Override
+ public void onPageScrollStateChanged(int state) {
+ final int count = mOnPageChangeListeners.size();
+ for (int i = 0; i < count; i++) {
+ mOnPageChangeListeners.get(i).onPageScrollStateChanged(state);
+ }
+ }
}
diff --git a/src/com/android/dialer/list/ViewPagerTabs.java b/src/com/android/dialer/list/ViewPagerTabs.java
index a538d09..b545802 100644
--- a/src/com/android/dialer/list/ViewPagerTabs.java
+++ b/src/com/android/dialer/list/ViewPagerTabs.java
@@ -108,7 +108,6 @@
public void setViewPager(ViewPager viewPager) {
mPager = viewPager;
- mPager.setOnPageChangeListener(this);
addTabs(mPager.getAdapter());
}