Index: chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java |
index a15c1561e9a5ebc1c0c9fb14d2527547ddaeff8c..985669d20428c4e7b5ffdd73ff49713159128e25 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java |
@@ -4,6 +4,10 @@ |
package org.chromium.chrome.browser.appmenu; |
+import android.animation.Animator; |
+import android.animation.AnimatorListenerAdapter; |
+import android.animation.AnimatorSet; |
+import android.animation.ObjectAnimator; |
import android.graphics.drawable.Drawable; |
import android.view.LayoutInflater; |
import android.view.MenuItem; |
@@ -12,10 +16,12 @@ import android.view.View.OnClickListener; |
import android.view.ViewGroup; |
import android.widget.BaseAdapter; |
import android.widget.ImageButton; |
+import android.widget.ImageView; |
import android.widget.ListView; |
import android.widget.TextView; |
import org.chromium.chrome.R; |
+import org.chromium.ui.interpolators.BakedBezierInterpolator; |
import java.util.List; |
@@ -43,11 +49,19 @@ class AppMenuAdapter extends BaseAdapter { |
*/ |
private static final int FOUR_BUTTON_MENU_ITEM = 3; |
+ /** MenuItem Animation Constants */ |
+ private static final int ENTER_ITEM_DURATION_MS = 350; |
+ private static final int ENTER_ITEM_BASE_DELAY_MS = 80; |
+ private static final int ENTER_ITEM_ADDL_DELAY_MS = 30; |
+ private static final float ENTER_STANDARD_ITEM_OFFSET_Y_DP = -10.f; |
+ private static final float ENTER_STANDARD_ITEM_OFFSET_X_DP = 10.f; |
+ |
private final AppMenu mAppMenu; |
private final LayoutInflater mInflater; |
private final List<MenuItem> mMenuItems; |
private final int mNumMenuItems; |
private final boolean mShowMenuButton; |
+ private final float mDpToPx; |
public AppMenuAdapter(AppMenu appMenu, List<MenuItem> menuItems, LayoutInflater inflater, |
boolean showMenuButton) { |
@@ -56,6 +70,7 @@ class AppMenuAdapter extends BaseAdapter { |
mInflater = inflater; |
mNumMenuItems = menuItems.size(); |
mShowMenuButton = showMenuButton; |
+ mDpToPx = inflater.getContext().getResources().getDisplayMetrics().density; |
} |
@Override |
@@ -99,6 +114,7 @@ class AppMenuAdapter extends BaseAdapter { |
@Override |
public View getView(int position, View convertView, ViewGroup parent) { |
+ final boolean hasMenuButton = mShowMenuButton && position == 0; |
final MenuItem item = getItem(position); |
switch (getItemViewType(position)) { |
case STANDARD_MENU_ITEM: { |
@@ -109,6 +125,8 @@ class AppMenuAdapter extends BaseAdapter { |
holder.text = (TextView) convertView.findViewById(R.id.menu_item_text); |
holder.image = (AppMenuItemIcon) convertView.findViewById(R.id.menu_item_icon); |
convertView.setTag(holder); |
+ convertView.setTag(R.id.menu_item_enter_anim_id, |
+ buildStandardItemEnterAnimator(convertView, position)); |
} else { |
holder = (StandardMenuItemViewHolder) convertView.getTag(); |
} |
@@ -138,21 +156,23 @@ class AppMenuAdapter extends BaseAdapter { |
if (convertView == null) { |
holder = new ThreeButtonMenuItemViewHolder(); |
convertView = mInflater.inflate(R.layout.three_button_menu_item, parent, false); |
- holder.buttonOne = (ImageButton) convertView.findViewById(R.id.button_one); |
- holder.buttonTwo = (ImageButton) convertView.findViewById(R.id.button_two); |
- holder.buttonThree = (ImageButton) convertView.findViewById(R.id.button_three); |
+ holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one); |
+ holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two); |
+ holder.buttons[2] = (ImageButton) convertView.findViewById(R.id.button_three); |
convertView.setTag(holder); |
+ convertView.setTag(R.id.menu_item_enter_anim_id, |
+ buildIconItemEnterAnimator(holder.buttons, hasMenuButton)); |
} else { |
holder = (ThreeButtonMenuItemViewHolder) convertView.getTag(); |
} |
- setupImageButton(holder.buttonOne, item.getSubMenu().getItem(0)); |
- setupImageButton(holder.buttonTwo, item.getSubMenu().getItem(1)); |
- |
- if (mShowMenuButton && position == 0) { |
- setupMenuButton(holder.buttonThree); |
+ setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0)); |
+ setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1)); |
+ if (hasMenuButton) { |
+ setupMenuButton(holder.buttons[3]); |
} else { |
- setupImageButton(holder.buttonThree, item.getSubMenu().getItem(2)); |
+ setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2)); |
} |
+ |
convertView.setFocusable(false); |
convertView.setEnabled(false); |
break; |
@@ -162,22 +182,23 @@ class AppMenuAdapter extends BaseAdapter { |
if (convertView == null) { |
holder = new FourButtonMenuItemViewHolder(); |
convertView = mInflater.inflate(R.layout.four_button_menu_item, parent, false); |
- holder.buttonOne = (ImageButton) convertView.findViewById(R.id.button_one); |
- holder.buttonTwo = (ImageButton) convertView.findViewById(R.id.button_two); |
- holder.buttonThree = (ImageButton) convertView.findViewById(R.id.button_three); |
- holder.buttonFour = (ImageButton) convertView.findViewById(R.id.button_four); |
+ holder.buttons[0] = (ImageButton) convertView.findViewById(R.id.button_one); |
+ holder.buttons[1] = (ImageButton) convertView.findViewById(R.id.button_two); |
+ holder.buttons[2] = (ImageButton) convertView.findViewById(R.id.button_three); |
+ holder.buttons[3] = (ImageButton) convertView.findViewById(R.id.button_four); |
convertView.setTag(holder); |
+ convertView.setTag(R.id.menu_item_enter_anim_id, |
+ buildIconItemEnterAnimator(holder.buttons, hasMenuButton)); |
} else { |
holder = (FourButtonMenuItemViewHolder) convertView.getTag(); |
} |
- setupImageButton(holder.buttonOne, item.getSubMenu().getItem(0)); |
- setupImageButton(holder.buttonTwo, item.getSubMenu().getItem(1)); |
- setupImageButton(holder.buttonThree, item.getSubMenu().getItem(2)); |
- |
- if (mShowMenuButton && position == 0) { |
- setupMenuButton(holder.buttonFour); |
+ setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0)); |
+ setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1)); |
+ setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2)); |
+ if (hasMenuButton) { |
+ setupMenuButton(holder.buttons[3]); |
} else { |
- setupImageButton(holder.buttonFour, item.getSubMenu().getItem(3)); |
+ setupImageButton(holder.buttons[3], item.getSubMenu().getItem(3)); |
} |
convertView.setFocusable(false); |
convertView.setEnabled(false); |
@@ -191,6 +212,8 @@ class AppMenuAdapter extends BaseAdapter { |
holder.title = (TextView) convertView.findViewById(R.id.title); |
holder.button = (ImageButton) convertView.findViewById(R.id.button); |
convertView.setTag(holder); |
+ convertView.setTag(R.id.menu_item_enter_anim_id, |
+ buildStandardItemEnterAnimator(convertView, position)); |
} else { |
holder = (TitleButtonMenuItemViewHolder) convertView.getTag(); |
} |
@@ -205,7 +228,7 @@ class AppMenuAdapter extends BaseAdapter { |
} |
}); |
- if (mShowMenuButton && position == 0) { |
+ if (hasMenuButton) { |
holder.button.setVisibility(View.VISIBLE); |
setupMenuButton(holder.button); |
} else if (item.getSubMenu().getItem(1).getIcon() != null) { |
@@ -254,22 +277,91 @@ class AppMenuAdapter extends BaseAdapter { |
}); |
} |
+ /** |
+ * This builds an {@link Animator} for the enter animation of a standard menu item. This means |
+ * it will animate the alpha from 0 to 1 and translate the view from -10dp to 0dp on the y axis. |
+ * |
+ * @param view The menu item {@link View} to be animated. |
+ * @param position The position in the menu. This impacts the start delay of the animation. |
+ * @return The {@link Animator}. |
+ */ |
+ private Animator buildStandardItemEnterAnimator(final View view, int position) { |
+ final float offsetYPx = ENTER_STANDARD_ITEM_OFFSET_Y_DP * mDpToPx; |
+ final int startDelay = ENTER_ITEM_BASE_DELAY_MS + ENTER_ITEM_ADDL_DELAY_MS * position; |
+ |
+ AnimatorSet animation = new AnimatorSet(); |
+ animation.playTogether( |
+ ObjectAnimator.ofFloat(view, View.ALPHA, 0.f, 1.f), |
+ ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, offsetYPx, 0.f)); |
+ animation.setDuration(ENTER_ITEM_DURATION_MS); |
+ animation.setStartDelay(startDelay); |
+ animation.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE); |
+ |
+ animation.addListener(new AnimatorListenerAdapter() { |
+ @Override |
+ public void onAnimationStart(Animator animation) { |
+ view.setAlpha(0.f); |
+ } |
+ }); |
+ return animation; |
+ } |
+ |
+ /** |
+ * This builds an {@link Animator} for the enter animation of icon row menu items. This means |
+ * it will animate the alpha from 0 to 1 and translate the views from 10dp to 0dp on the x axis. |
+ * |
+ * @param views The list if icons in the menu item that should be animated. |
+ * @param skipLastItem Whether or not the last item should be animated or not. |
+ * @return The {@link Animator}. |
+ */ |
+ private Animator buildIconItemEnterAnimator(final ImageView[] views, boolean skipLastItem) { |
+ final float offsetXPx = ENTER_STANDARD_ITEM_OFFSET_X_DP * mDpToPx; |
+ final int maxViewsToAnimate = views.length - (skipLastItem ? 1 : 0); |
+ |
+ AnimatorSet animation = new AnimatorSet(); |
+ AnimatorSet.Builder builder = null; |
+ for (int i = 0; i < maxViewsToAnimate; i++) { |
+ final int startDelay = ENTER_ITEM_ADDL_DELAY_MS * i; |
+ |
+ Animator alpha = ObjectAnimator.ofFloat(views[i], View.ALPHA, 0.f, 1.f); |
+ Animator translate = ObjectAnimator.ofFloat(views[i], View.TRANSLATION_X, offsetXPx, 0); |
+ alpha.setStartDelay(startDelay); |
+ translate.setStartDelay(startDelay); |
+ alpha.setDuration(ENTER_ITEM_DURATION_MS); |
+ translate.setDuration(ENTER_ITEM_DURATION_MS); |
+ |
+ if (builder == null) { |
+ builder = animation.play(alpha); |
+ } else { |
+ builder.with(alpha); |
+ } |
+ builder.with(translate); |
+ } |
+ animation.setStartDelay(ENTER_ITEM_BASE_DELAY_MS); |
+ animation.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE); |
+ |
+ animation.addListener(new AnimatorListenerAdapter() { |
+ @Override |
+ public void onAnimationStart(Animator animation) { |
+ for (int i = 0; i < maxViewsToAnimate; i++) { |
+ views[i].setAlpha(0.f); |
+ } |
+ } |
+ }); |
+ return animation; |
+ } |
+ |
static class StandardMenuItemViewHolder { |
public TextView text; |
public AppMenuItemIcon image; |
} |
static class ThreeButtonMenuItemViewHolder { |
- public ImageButton buttonOne; |
- public ImageButton buttonTwo; |
- public ImageButton buttonThree; |
+ public ImageButton[] buttons = new ImageButton[3]; |
} |
static class FourButtonMenuItemViewHolder { |
- public ImageButton buttonOne; |
- public ImageButton buttonTwo; |
- public ImageButton buttonThree; |
- public ImageButton buttonFour; |
+ public ImageButton[] buttons = new ImageButton[4]; |
} |
static class TitleButtonMenuItemViewHolder { |