Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(159)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java

Issue 388803006: Add per-item animations to the menu (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.chrome.browser.appmenu; 5 package org.chromium.chrome.browser.appmenu;
6 6
7 import android.animation.Animator;
8 import android.animation.AnimatorListenerAdapter;
9 import android.animation.AnimatorSet;
10 import android.animation.ObjectAnimator;
7 import android.graphics.drawable.Drawable; 11 import android.graphics.drawable.Drawable;
8 import android.view.LayoutInflater; 12 import android.view.LayoutInflater;
9 import android.view.MenuItem; 13 import android.view.MenuItem;
10 import android.view.View; 14 import android.view.View;
11 import android.view.View.OnClickListener; 15 import android.view.View.OnClickListener;
12 import android.view.ViewGroup; 16 import android.view.ViewGroup;
17 import android.view.animation.DecelerateInterpolator;
13 import android.widget.BaseAdapter; 18 import android.widget.BaseAdapter;
14 import android.widget.ImageButton; 19 import android.widget.ImageButton;
20 import android.widget.ImageView;
15 import android.widget.ListView; 21 import android.widget.ListView;
16 import android.widget.TextView; 22 import android.widget.TextView;
17 23
18 import org.chromium.chrome.R; 24 import org.chromium.chrome.R;
19 25
20 import java.util.List; 26 import java.util.List;
21 27
22 /** 28 /**
23 * ListAdapter to customize the view of items in the list. 29 * ListAdapter to customize the view of items in the list.
24 */ 30 */
(...skipping 11 matching lines...) Expand all
36 private static final int TITLE_BUTTON_MENU_ITEM = 1; 42 private static final int TITLE_BUTTON_MENU_ITEM = 1;
37 /** 43 /**
38 * Menu item that has three buttons. Every one of these buttons is displayed as an icon. 44 * Menu item that has three buttons. Every one of these buttons is displayed as an icon.
39 */ 45 */
40 private static final int THREE_BUTTON_MENU_ITEM = 2; 46 private static final int THREE_BUTTON_MENU_ITEM = 2;
41 /** 47 /**
42 * Menu item that has four buttons. Every one of these buttons is displayed as an icon. 48 * Menu item that has four buttons. Every one of these buttons is displayed as an icon.
43 */ 49 */
44 private static final int FOUR_BUTTON_MENU_ITEM = 3; 50 private static final int FOUR_BUTTON_MENU_ITEM = 3;
45 51
52 /** MenuItem Animation Constants */
53 private static final int ENTER_ITEM_DURATION_MS = 500;
54 private static final int ENTER_ITEM_BASE_DELAY_MS = 100;
55 private static final int ENTER_ITEM_ADDL_DELAY_MS = 70;
56 private static final float ENTER_STANDARD_ITEM_OFFSET_Y_DP = -10.f;
57 private static final float ENTER_STANDARD_ITEM_OFFSET_X_DP = 10.f;
58
46 private final AppMenu mAppMenu; 59 private final AppMenu mAppMenu;
47 private final LayoutInflater mInflater; 60 private final LayoutInflater mInflater;
48 private final List<MenuItem> mMenuItems; 61 private final List<MenuItem> mMenuItems;
49 private final int mNumMenuItems; 62 private final int mNumMenuItems;
63 private final float mDpToPx;
50 64
51 public AppMenuAdapter(AppMenu appMenu, List<MenuItem> menuItems, LayoutInfla ter inflater) { 65 public AppMenuAdapter(AppMenu appMenu, List<MenuItem> menuItems, LayoutInfla ter inflater) {
52 mAppMenu = appMenu; 66 mAppMenu = appMenu;
53 mMenuItems = menuItems; 67 mMenuItems = menuItems;
54 mInflater = inflater; 68 mInflater = inflater;
55 mNumMenuItems = menuItems.size(); 69 mNumMenuItems = menuItems.size();
70 mDpToPx = inflater.getContext().getResources().getDisplayMetrics().densi ty;
56 } 71 }
57 72
58 @Override 73 @Override
59 public int getCount() { 74 public int getCount() {
60 return mNumMenuItems; 75 return mNumMenuItems;
61 } 76 }
62 77
63 @Override 78 @Override
64 public int getViewTypeCount() { 79 public int getViewTypeCount() {
65 return VIEW_TYPE_COUNT; 80 return VIEW_TYPE_COUNT;
(...skipping 30 matching lines...) Expand all
96 public View getView(int position, View convertView, ViewGroup parent) { 111 public View getView(int position, View convertView, ViewGroup parent) {
97 final MenuItem item = getItem(position); 112 final MenuItem item = getItem(position);
98 switch (getItemViewType(position)) { 113 switch (getItemViewType(position)) {
99 case STANDARD_MENU_ITEM: { 114 case STANDARD_MENU_ITEM: {
100 StandardMenuItemViewHolder holder = null; 115 StandardMenuItemViewHolder holder = null;
101 if (convertView == null) { 116 if (convertView == null) {
102 holder = new StandardMenuItemViewHolder(); 117 holder = new StandardMenuItemViewHolder();
103 convertView = mInflater.inflate(R.layout.menu_item, parent, false); 118 convertView = mInflater.inflate(R.layout.menu_item, parent, false);
104 holder.text = (TextView) convertView.findViewById(R.id.menu_ item_text); 119 holder.text = (TextView) convertView.findViewById(R.id.menu_ item_text);
105 holder.image = (AppMenuItemIcon) convertView.findViewById(R. id.menu_item_icon); 120 holder.image = (AppMenuItemIcon) convertView.findViewById(R. id.menu_item_icon);
106 convertView.setTag(holder); 121 convertView.setTag(holder);
aurimas (slooooooooow) 2014/07/15 01:37:25 Should we set a key for this tag? I am not sure ho
David Trainor- moved to gerrit 2014/07/15 20:53:38 We don't need one. getTag()/setTag(Object) store
aurimas (slooooooooow) 2014/07/16 17:03:42 Acknowledged.
122 convertView.setTag(R.id.menu_item_enter_anim_id,
123 buildStandardItemEnterAnimator(convertView, position ));
124 convertView.setTag(R.id.menu_item_exit_anim_id,
125 buildItemExitAnimator(convertView));
107 } else { 126 } else {
108 holder = (StandardMenuItemViewHolder) convertView.getTag(); 127 holder = (StandardMenuItemViewHolder) convertView.getTag();
109 } 128 }
110 129
111 convertView.setOnClickListener(new OnClickListener() { 130 convertView.setOnClickListener(new OnClickListener() {
112 @Override 131 @Override
113 public void onClick(View v) { 132 public void onClick(View v) {
114 mAppMenu.onItemClick(item); 133 mAppMenu.onItemClick(item);
115 } 134 }
116 }); 135 });
117 // Set up the icon. 136 // Set up the icon.
118 Drawable icon = item.getIcon(); 137 Drawable icon = item.getIcon();
119 holder.image.setImageDrawable(icon); 138 holder.image.setImageDrawable(icon);
120 holder.image.setVisibility(icon == null ? View.GONE : View.VISIB LE); 139 holder.image.setVisibility(icon == null ? View.GONE : View.VISIB LE);
121 holder.image.setChecked(item.isChecked()); 140 holder.image.setChecked(item.isChecked());
122 141
123 holder.text.setText(item.getTitle()); 142 holder.text.setText(item.getTitle());
124 boolean isEnabled = item.isEnabled(); 143 boolean isEnabled = item.isEnabled();
125 // Set the text color (using a color state list). 144 // Set the text color (using a color state list).
126 holder.text.setEnabled(isEnabled); 145 holder.text.setEnabled(isEnabled);
127 // This will ensure that the item is not highlighted when select ed. 146 // This will ensure that the item is not highlighted when select ed.
128 convertView.setEnabled(isEnabled); 147 convertView.setEnabled(isEnabled);
129 break; 148 break;
130 } 149 }
131 case THREE_BUTTON_MENU_ITEM: { 150 case THREE_BUTTON_MENU_ITEM: {
132 ThreeButtonMenuItemViewHolder holder = null; 151 ThreeButtonMenuItemViewHolder holder = null;
133 if (convertView == null) { 152 if (convertView == null) {
134 holder = new ThreeButtonMenuItemViewHolder(); 153 holder = new ThreeButtonMenuItemViewHolder();
135 convertView = mInflater.inflate(R.layout.three_button_menu_i tem, parent, false); 154 convertView = mInflater.inflate(R.layout.three_button_menu_i tem, parent, false);
136 holder.buttonOne = (ImageButton) convertView.findViewById(R. id.button_one); 155 holder.buttons[0] = (ImageButton) convertView.findViewById(R .id.button_one);
137 holder.buttonTwo = (ImageButton) convertView.findViewById(R. id.button_two); 156 holder.buttons[1] = (ImageButton) convertView.findViewById(R .id.button_two);
138 holder.buttonThree = (ImageButton) convertView.findViewById( R.id.button_three); 157 holder.buttons[2] = (ImageButton) convertView.findViewById(R .id.button_three);
139 convertView.setTag(holder); 158 convertView.setTag(holder);
159 convertView.setTag(R.id.menu_item_enter_anim_id,
160 buildIconItemEnterAnimator(holder.buttons, false));
161 convertView.setTag(R.id.menu_item_exit_anim_id,
162 buildItemExitAnimator(convertView));
140 } else { 163 } else {
141 holder = (ThreeButtonMenuItemViewHolder) convertView.getTag( ); 164 holder = (ThreeButtonMenuItemViewHolder) convertView.getTag( );
142 } 165 }
143 setupImageButton(holder.buttonOne, item.getSubMenu().getItem(0)) ; 166 setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0) );
144 setupImageButton(holder.buttonTwo, item.getSubMenu().getItem(1)) ; 167 setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1) );
145 setupImageButton(holder.buttonThree, item.getSubMenu().getItem(2 )); 168 setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2) );
146 convertView.setFocusable(false); 169 convertView.setFocusable(false);
147 convertView.setEnabled(false); 170 convertView.setEnabled(false);
148 break; 171 break;
149 } 172 }
150 case FOUR_BUTTON_MENU_ITEM: { 173 case FOUR_BUTTON_MENU_ITEM: {
151 FourButtonMenuItemViewHolder holder = null; 174 FourButtonMenuItemViewHolder holder = null;
152 if (convertView == null) { 175 if (convertView == null) {
153 holder = new FourButtonMenuItemViewHolder(); 176 holder = new FourButtonMenuItemViewHolder();
154 convertView = mInflater.inflate(R.layout.four_button_menu_it em, parent, false); 177 convertView = mInflater.inflate(R.layout.four_button_menu_it em, parent, false);
155 holder.buttonOne = (ImageButton) convertView.findViewById(R. id.button_one); 178 holder.buttons[0] = (ImageButton) convertView.findViewById(R .id.button_one);
156 holder.buttonTwo = (ImageButton) convertView.findViewById(R. id.button_two); 179 holder.buttons[1] = (ImageButton) convertView.findViewById(R .id.button_two);
157 holder.buttonThree = (ImageButton) convertView.findViewById( R.id.button_three); 180 holder.buttons[2] = (ImageButton) convertView.findViewById(R .id.button_three);
158 holder.buttonFour = (ImageButton) convertView.findViewById(R .id.button_four); 181 holder.buttons[3] = (ImageButton) convertView.findViewById(R .id.button_four);
159 convertView.setTag(holder); 182 convertView.setTag(holder);
183 convertView.setTag(R.id.menu_item_enter_anim_id,
184 buildIconItemEnterAnimator(holder.buttons, false));
185 convertView.setTag(R.id.menu_item_exit_anim_id,
186 buildItemExitAnimator(convertView));
160 } else { 187 } else {
161 holder = (FourButtonMenuItemViewHolder) convertView.getTag() ; 188 holder = (FourButtonMenuItemViewHolder) convertView.getTag() ;
162 } 189 }
163 setupImageButton(holder.buttonOne, item.getSubMenu().getItem(0)) ; 190 setupImageButton(holder.buttons[0], item.getSubMenu().getItem(0) );
164 setupImageButton(holder.buttonTwo, item.getSubMenu().getItem(1)) ; 191 setupImageButton(holder.buttons[1], item.getSubMenu().getItem(1) );
165 setupImageButton(holder.buttonThree, item.getSubMenu().getItem(2 )); 192 setupImageButton(holder.buttons[2], item.getSubMenu().getItem(2) );
166 setupImageButton(holder.buttonFour, item.getSubMenu().getItem(3) ); 193 setupImageButton(holder.buttons[3], item.getSubMenu().getItem(3) );
167 convertView.setFocusable(false); 194 convertView.setFocusable(false);
168 convertView.setEnabled(false); 195 convertView.setEnabled(false);
169 break; 196 break;
170 } 197 }
171 case TITLE_BUTTON_MENU_ITEM: { 198 case TITLE_BUTTON_MENU_ITEM: {
172 TitleButtonMenuItemViewHolder holder = null; 199 TitleButtonMenuItemViewHolder holder = null;
173 if (convertView == null) { 200 if (convertView == null) {
174 holder = new TitleButtonMenuItemViewHolder(); 201 holder = new TitleButtonMenuItemViewHolder();
175 convertView = mInflater.inflate(R.layout.title_button_menu_i tem, parent, false); 202 convertView = mInflater.inflate(R.layout.title_button_menu_i tem, parent, false);
176 holder.title = (TextView) convertView.findViewById(R.id.titl e); 203 holder.title = (TextView) convertView.findViewById(R.id.titl e);
177 holder.button = (ImageButton) convertView.findViewById(R.id. button); 204 holder.button = (ImageButton) convertView.findViewById(R.id. button);
178 convertView.setTag(holder); 205 convertView.setTag(holder);
206 convertView.setTag(R.id.menu_item_enter_anim_id,
207 buildStandardItemEnterAnimator(convertView, position ));
208 convertView.setTag(R.id.menu_item_exit_anim_id,
209 buildItemExitAnimator(convertView));
179 } else { 210 } else {
180 holder = (TitleButtonMenuItemViewHolder) convertView.getTag( ); 211 holder = (TitleButtonMenuItemViewHolder) convertView.getTag( );
181 } 212 }
182 final MenuItem titleItem = item.getSubMenu().getItem(0); 213 final MenuItem titleItem = item.getSubMenu().getItem(0);
183 holder.title.setText(titleItem.getTitle()); 214 holder.title.setText(titleItem.getTitle());
184 holder.title.setEnabled(titleItem.isEnabled()); 215 holder.title.setEnabled(titleItem.isEnabled());
185 holder.title.setFocusable(titleItem.isEnabled()); 216 holder.title.setFocusable(titleItem.isEnabled());
186 holder.title.setOnClickListener(new OnClickListener() { 217 holder.title.setOnClickListener(new OnClickListener() {
187 @Override 218 @Override
188 public void onClick(View v) { 219 public void onClick(View v) {
(...skipping 26 matching lines...) Expand all
215 button.setEnabled(item.isEnabled()); 246 button.setEnabled(item.isEnabled());
216 button.setFocusable(item.isEnabled()); 247 button.setFocusable(item.isEnabled());
217 button.setOnClickListener(new OnClickListener() { 248 button.setOnClickListener(new OnClickListener() {
218 @Override 249 @Override
219 public void onClick(View v) { 250 public void onClick(View v) {
220 mAppMenu.onItemClick(item); 251 mAppMenu.onItemClick(item);
221 } 252 }
222 }); 253 });
223 } 254 }
224 255
256 private Animator buildStandardItemEnterAnimator(final View view, int positio n) {
aurimas (slooooooooow) 2014/07/15 01:37:26 Please add some comments to these animator constru
David Trainor- moved to gerrit 2014/07/15 20:53:38 Will do.
257 final float offsetYPx = ENTER_STANDARD_ITEM_OFFSET_Y_DP * mDpToPx;
258 final int startDelay = ENTER_ITEM_BASE_DELAY_MS + ENTER_ITEM_ADDL_DELAY_ MS * position;
259
260 AnimatorSet animation = new AnimatorSet();
261 animation.playTogether(
262 ObjectAnimator.ofFloat(view, View.ALPHA, 0.f, 1.f),
263 ObjectAnimator.ofFloat(view, View.TRANSLATION_Y, offsetYPx, 0.f) );
264 animation.setDuration(ENTER_ITEM_DURATION_MS);
265 animation.setStartDelay(startDelay);
266 // TODO(dtrainor): Update to material interpolators.
267 animation.setInterpolator(new DecelerateInterpolator());
268
269 animation.addListener(new AnimatorListenerAdapter() {
270 @Override
271 public void onAnimationStart(Animator animation) {
272 view.setAlpha(0.f);
273 }
274 });
275 return animation;
276 }
277
278 private Animator buildIconItemEnterAnimator(final ImageView[] views, boolean skipLastItem) {
279 final float offsetXPx = ENTER_STANDARD_ITEM_OFFSET_X_DP * mDpToPx;
280 final int maxViewsToAnimate = views.length - (skipLastItem ? 1 : 0);
281
282 AnimatorSet animation = new AnimatorSet();
283 AnimatorSet.Builder builder = null;
284 for (int i = 0; i < maxViewsToAnimate; i++) {
285 final int startDelay = ENTER_ITEM_ADDL_DELAY_MS * i;
286
287 Animator alpha = ObjectAnimator.ofFloat(views[i], View.ALPHA, 0.f, 1 .f);
288 Animator translate = ObjectAnimator.ofFloat(views[i], View.TRANSLATI ON_X, offsetXPx, 0);
289 alpha.setStartDelay(startDelay);
290 translate.setStartDelay(startDelay);
291 alpha.setDuration(ENTER_ITEM_DURATION_MS);
292 translate.setDuration(ENTER_ITEM_DURATION_MS);
293
294 if (builder == null) {
295 builder = animation.play(alpha);
296 } else {
297 builder.with(alpha);
298 }
299 builder.with(translate);
300 }
301 animation.setStartDelay(ENTER_ITEM_BASE_DELAY_MS);
302 // TODO(dtrainor): Update to material interpolators.
303 animation.setInterpolator(new DecelerateInterpolator());
304
305 animation.addListener(new AnimatorListenerAdapter() {
306 @Override
307 public void onAnimationStart(Animator animation) {
308 for (int i = 0; i < maxViewsToAnimate; i++) {
309 views[i].setAlpha(0.f);
310 }
311 }
312 });
313 return animation;
314 }
315
316 private Animator buildItemExitAnimator(View view) {
317 return ObjectAnimator.ofFloat(view, View.ALPHA, 1.f, 0.f).setDuration(0) ;
aurimas (slooooooooow) 2014/07/15 01:37:26 What does it mean to have an animation of length 0
David Trainor- moved to gerrit 2014/07/15 20:53:38 It means right now they just hide immediately. Bu
aurimas (slooooooooow) 2014/07/16 17:03:42 Acknowledged.
318 }
319
225 static class StandardMenuItemViewHolder { 320 static class StandardMenuItemViewHolder {
226 public TextView text; 321 public TextView text;
227 public AppMenuItemIcon image; 322 public AppMenuItemIcon image;
228 } 323 }
229 324
230 static class ThreeButtonMenuItemViewHolder { 325 static class ThreeButtonMenuItemViewHolder {
231 public ImageButton buttonOne; 326 public ImageButton[] buttons = new ImageButton[3];
232 public ImageButton buttonTwo;
233 public ImageButton buttonThree;
234 } 327 }
235 328
236 static class FourButtonMenuItemViewHolder { 329 static class FourButtonMenuItemViewHolder {
237 public ImageButton buttonOne; 330 public ImageButton[] buttons = new ImageButton[4];
238 public ImageButton buttonTwo;
239 public ImageButton buttonThree;
240 public ImageButton buttonFour;
241 } 331 }
242 332
243 static class TitleButtonMenuItemViewHolder { 333 static class TitleButtonMenuItemViewHolder {
244 public TextView title; 334 public TextView title;
245 public ImageButton button; 335 public ImageButton button;
246 } 336 }
247 } 337 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698