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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillDialogView.java

Issue 14886012: Implement layout transition animations for the Autofill dialog (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Got rid of TABs Created 7 years, 7 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 (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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.autofill; 5 package org.chromium.chrome.browser.autofill;
6 6
7 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.NUM_S ECTIONS;
8 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_BILLING;
9 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_CC;
10 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_CC_BILLING;
11 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_EMAIL;
12 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_SHIPPING;
13
14 import android.animation.Animator;
15 import android.animation.AnimatorListenerAdapter;
16 import android.animation.ObjectAnimator;
17 import android.animation.ValueAnimator;
18 import android.animation.ValueAnimator.AnimatorUpdateListener;
7 import android.content.Context; 19 import android.content.Context;
20 import android.content.res.Configuration;
8 import android.content.res.Resources; 21 import android.content.res.Resources;
9 import android.graphics.Bitmap; 22 import android.graphics.Bitmap;
23 import android.graphics.Canvas;
24 import android.graphics.Color;
10 import android.graphics.drawable.BitmapDrawable; 25 import android.graphics.drawable.BitmapDrawable;
26 import android.graphics.drawable.ColorDrawable;
27 import android.graphics.drawable.Drawable;
11 import android.os.Build; 28 import android.os.Build;
29 import android.os.SystemClock;
12 import android.text.TextUtils; 30 import android.text.TextUtils;
13 import android.util.AttributeSet; 31 import android.util.AttributeSet;
14 import android.view.KeyEvent; 32 import android.view.KeyEvent;
15 import android.view.View; 33 import android.view.View;
16 import android.view.ViewGroup; 34 import android.view.ViewGroup;
17 import android.view.animation.Animation; 35 import android.view.animation.Animation;
18 import android.view.animation.AnimationSet; 36 import android.view.animation.AnimationSet;
19 import android.view.animation.ScaleAnimation; 37 import android.view.animation.ScaleAnimation;
20 import android.view.animation.TranslateAnimation; 38 import android.view.animation.TranslateAnimation;
39 import android.widget.AdapterView.OnItemSelectedListener;
21 import android.widget.ArrayAdapter; 40 import android.widget.ArrayAdapter;
22 import android.widget.Button; 41 import android.widget.Button;
23 import android.widget.EditText; 42 import android.widget.EditText;
43 import android.widget.FrameLayout;
24 import android.widget.ImageView; 44 import android.widget.ImageView;
25 import android.widget.LinearLayout;
26 import android.widget.Spinner; 45 import android.widget.Spinner;
27 import android.widget.TextView; 46 import android.widget.TextView;
28 import android.widget.AdapterView.OnItemSelectedListener;
29
30 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.NUM_S ECTIONS;
31 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_EMAIL;
32 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_CC;
33 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_CC_BILLING;
34 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_BILLING;
35 import static org.chromium.chrome.browser.autofill.AutofillDialogConstants.SECTI ON_SHIPPING;
36 47
37 import org.chromium.chrome.R; 48 import org.chromium.chrome.R;
38 49
39 import java.util.ArrayList; 50 import java.util.ArrayList;
40 import java.util.Arrays; 51 import java.util.Arrays;
41 import java.util.List; 52 import java.util.List;
42 53
43 /** 54 /**
44 * This is the parent layout that contains the layouts for different states of 55 * This is the parent layout that contains the layouts for different states of
45 * autofill dialog. In principle it shouldn't contain any logic related with the 56 * autofill dialog. In principle it shouldn't contain any logic related with the
46 * actual workflow, but rather respond to any UI update messages coming to it 57 * actual workflow, but rather respond to any UI update messages coming to it
47 * from the AutofillDialog. 58 * from the AutofillDialog.
48 */ 59 */
49 public class AutofillDialogContentView extends LinearLayout { 60 public class AutofillDialogView extends FrameLayout {
50 private static final int ANIMATION_DURATION_MS = 1000; 61 private static final int ANIMATION_DURATION_MS = 1000;
51 static final int INVALID_LAYOUT = -1; 62 static final int INVALID_LAYOUT = -1;
52 static final int LAYOUT_EDITING_EMAIL = 0; 63 static final int LAYOUT_EDITING_EMAIL = 0;
53 static final int LAYOUT_EDITING_SHIPPING = 1; 64 static final int LAYOUT_EDITING_SHIPPING = 1;
54 static final int LAYOUT_EDITING_CC = 2; 65 static final int LAYOUT_EDITING_CC = 2;
55 static final int LAYOUT_EDITING_BILLING = 3; 66 static final int LAYOUT_EDITING_BILLING = 3;
56 static final int LAYOUT_EDITING_CC_BILLING = 4; 67 static final int LAYOUT_EDITING_CC_BILLING = 4;
57 static final int LAYOUT_FETCHING = 5; 68 static final int LAYOUT_FETCHING = 5;
58 static final int LAYOUT_STEADY = 6; 69 static final int LAYOUT_STEADY = 6;
59 private final Runnable mDismissSteadyLayoutRunnable = new Runnable() { 70 private final Runnable mDismissSteadyLayoutRunnable = new Runnable() {
60 @Override 71 @Override
61 public void run() { 72 public void run() {
62 mSteadyLayout.setVisibility(GONE); 73 mSteadyLayout.setVisibility(GONE);
63 } 74 }
64 }; 75 };
65 private AutofillDialog mDialog; 76 private AutofillDialog mDialog;
66 private Spinner[] mSpinners = new Spinner[NUM_SECTIONS]; 77 private Spinner[] mSpinners = new Spinner[NUM_SECTIONS];
67 private AutofillDialogMenuAdapter[] mAdapters = new AutofillDialogMenuAdapte r[NUM_SECTIONS]; 78 private AutofillDialogMenuAdapter[] mAdapters = new AutofillDialogMenuAdapte r[NUM_SECTIONS];
68 private ViewGroup mSteadyLayout; 79 private ViewGroup mSteadyLayout;
69 private ViewGroup[] mEditLayouts = new ViewGroup[NUM_SECTIONS]; 80 private ViewGroup[] mEditLayouts = new ViewGroup[NUM_SECTIONS];
70 private int mCurrentLayout = -1; 81 private int mCurrentLayout = -1;
71 private String mCVCHint; 82 private String mCVCHint;
72 private Bitmap mCVCIcon; 83 private Bitmap mCVCIcon;
73 private OnItemSelectedListener mOnItemSelectedListener; 84 private OnItemSelectedListener mOnItemSelectedListener;
74 private OnItemEditButtonClickedListener mOnItemEditButtonClickedListener; 85 private OnItemEditButtonClickedListener mOnItemEditButtonClickedListener;
86 private View mTitle;
87 private View mContent;
88 private View mFooter;
89 private boolean mTransitionAnimationPlaying;
90 private float mVisibleContentHeight;
91 private ObjectAnimator mCurrentHeightAnimator;
92 private AnimationSet mCurrentLayoutAnimation;
93 private Drawable mBackground = new ColorDrawable(Color.LTGRAY);
94 private boolean mAnimateOnNextLayoutChange = false;
95 private int mCurrentOrientation;
96 private int mFrameHeight;
97 private int mFrameWidth;
75 98
76 /** 99 /**
77 * Interface definition for a callback to be invoked when an "Edit" button 100 * Interface definition for a callback to be invoked when an "Edit" button
78 * in the AutofillDialogMenuAdapter is clicked. 101 * in the AutofillDialogMenuAdapter is clicked.
79 */ 102 */
80 public interface OnItemEditButtonClickedListener { 103 public interface OnItemEditButtonClickedListener {
81 /** 104 /**
82 * Callback method to be invoked when an "Edit" button has been clicked. 105 * Callback method to be invoked when an "Edit" button has been clicked.
83 * @param section The dialog section associated with the adapter. 106 * @param section The dialog section associated with the adapter.
84 * @param position The position of the view in the adapter 107 * @param position The position of the view in the adapter
85 */ 108 */
86 void onItemEditButtonClicked(int section, int position); 109 void onItemEditButtonClicked(int section, int position);
87 } 110 }
88 111
89 public AutofillDialogContentView(Context context, AttributeSet attrs) { 112 public AutofillDialogView(Context context, AttributeSet attrs) {
90 super(context, attrs); 113 super(context, attrs);
114 setWillNotDraw(false);
91 } 115 }
92 116
93 @Override 117 @Override
94 protected void onFinishInflate () { 118 protected void onFinishInflate () {
95 mSteadyLayout = (ViewGroup) findViewById(R.id.general_layout); 119 mSteadyLayout = (ViewGroup) findViewById(R.id.general_layout);
120 mTitle = findViewById(R.id.title);
121 mContent = findViewById(R.id.content);
122 mFooter = findViewById(R.id.footer);
96 123
97 for (int i = 0; i < AutofillDialogConstants.NUM_SECTIONS; i++) { 124 for (int i = 0; i < AutofillDialogConstants.NUM_SECTIONS; i++) {
98 mEditLayouts[i] = (ViewGroup) findViewById( 125 mEditLayouts[i] = (ViewGroup) findViewById(
99 AutofillDialogUtils.getLayoutIDForSection(i)); 126 AutofillDialogUtils.getLayoutIDForSection(i));
100 int id = AutofillDialogUtils.getSpinnerIDForSection(i); 127 int id = AutofillDialogUtils.getSpinnerIDForSection(i);
101 mSpinners[i] = (Spinner) findViewById(id); 128 mSpinners[i] = (Spinner) findViewById(id);
102 } 129 }
103 130
131 int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
132 for (int i = 0; i < NUM_SECTIONS; i++) {
Ted C 2013/05/07 21:49:07 should these go in measure instead?
Yusuf 2013/05/08 21:39:00 This is just to avoid getting to a state where we
133 (mEditLayouts[i]).measure(spec, spec);
134 }
135 findViewById(R.id.loading_icon).measure(spec, spec);
136
137 mContent.addOnLayoutChangeListener(new OnLayoutChangeListener() {
138 @Override
139 public void onLayoutChange(View arg0, int arg1, int arg2, int arg3, int arg4, int arg5,
Ted C 2013/05/07 21:49:07 get the argument names from the sdk so they're not
Yusuf 2013/05/08 21:39:00 Done.
140 int arg6, int arg7, int arg8) {
141 if (mAnimateOnNextLayoutChange && mCurrentHeightAnimator != null
142 && !mCurrentHeightAnimator.isStarted()) {
143 mCurrentHeightAnimator.start();
144 mAnimateOnNextLayoutChange = false;
145 if (mCurrentLayoutAnimation != null && !mCurrentLayoutAnimat ion.hasStarted()) {
146 mCurrentLayoutAnimation.start();
147 }
148 }
149 }
150 });
151
152 mVisibleContentHeight = getAdjustedContentLayoutHeight(LAYOUT_FETCHING, null);
104 changeLayoutTo(LAYOUT_FETCHING); 153 changeLayoutTo(LAYOUT_FETCHING);
105 } 154 }
106 155
107 /** 156 /**
108 * Sets the controller dialog for this content view. 157 * Sets the controller dialog for this content view and initializes the view .
109 * @param dialog The autofill Dialog that should be set as the controller. 158 * @param dialog The autofill Dialog that should be set as the controller.
110 */ 159 */
111 public void setAutofillDialog(AutofillDialog dialog) { 160 public void initialize(AutofillDialog dialog) {
112 mDialog = dialog; 161 mDialog = dialog;
162
163 mDialog.getWindow().getDecorView().setBackground(null);
164
165 FrameLayout.LayoutParams layoutParams =
166 (android.widget.FrameLayout.LayoutParams) getLayoutParams();
167
168 mCurrentOrientation = getResources().getConfiguration().orientation;
169 mFrameHeight = getMaxHeightForOrientation(mCurrentOrientation);
170 layoutParams.height = mFrameHeight;
171 mFrameWidth = getResources().getDimensionPixelSize(R.dimen.autofill_dial og_width);
172 layoutParams.width = mFrameWidth;
173 requestLayout();
174 }
175
176 private int getMaxHeightForOrientation(int orientation) {
177 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
178 return getResources().getDimensionPixelSize(
179 R.dimen.autofill_dialog_max_height_portrait);
Ted C 2013/05/07 21:49:07 Hmm...can you use the same dimension name but use
Yusuf 2013/05/08 21:39:00 Done.
180 } else {
181 return getResources().getDimensionPixelSize(
182 R.dimen.autofill_dialog_max_height_landscape);
183 }
184 }
185
186 @Override
187 protected void onConfigurationChanged (Configuration newConfig) {
188 if (mCurrentOrientation != newConfig.orientation) {
Ted C 2013/05/07 21:49:07 I would check for equality and early out instead s
Yusuf 2013/05/08 21:39:00 Done.
189 mCurrentOrientation = newConfig.orientation;
190 FrameLayout.LayoutParams layoutParams =
191 (android.widget.FrameLayout.LayoutParams) getLayoutParams();
192 mFrameHeight = getMaxHeightForOrientation(mCurrentOrientation);
193 layoutParams.height = mFrameHeight;
194 requestLayout();
195 }
196 }
197
198 @Override
199 protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
200 if (!mTransitionAnimationPlaying) return super.drawChild(canvas, child, drawingTime);
Ted C 2013/05/07 21:49:07 Maybe make this: !mTransitionAnimationPlaying ||
Yusuf 2013/05/08 21:39:00 Done.
201
202 float top = mContent.getTop()
Ted C 2013/05/07 21:49:07 These aren't used outside of the if block, so prob
Yusuf 2013/05/08 21:39:00 Done.
203 + mContent.getMeasuredHeight() / 2 - mVisibleContentHeight / 2;
204 float bottom = mContent.getBottom()
205 - mContent.getMeasuredHeight() / 2 + mVisibleContentHeight / 2;
206 if (child.getId() == R.id.content) {
207 canvas.save();
208 canvas.clipRect(getLeft(), top, getRight(), bottom);
209 boolean result = super.drawChild(canvas, child, drawingTime);
210 canvas.restore();
211 return result;
212 }
213
214 return super.drawChild(canvas, child, drawingTime);
215 }
216
217 @Override
218 public void onDraw(Canvas canvas) {
219 if (mTransitionAnimationPlaying) {
220 mTitle.setTranslationY(mContent.getMeasuredHeight() / 2 - mVisibleCo ntentHeight / 2);
Ted C 2013/05/07 21:49:07 maybe extra some of these as variables and share t
Yusuf 2013/05/08 21:39:00 Done.
221 mContent.setTranslationY(mContent.getMeasuredHeight() / 2 - mVisible ContentHeight / 2);
222 mFooter.setTranslationY(- mContent.getMeasuredHeight() / 2 + mVisibl eContentHeight / 2);
Ted C 2013/05/07 21:49:07 unnecessary space between - and mContent
Yusuf 2013/05/08 21:39:00 Done.
223 }
224
225 canvas.save();
226 mBackground.setBounds(getLeft(),(int) (mTitle.getTop() + mTitle.getTrans lationY())
Ted C 2013/05/07 21:49:07 space after getLeft()
Yusuf 2013/05/08 21:39:00 Done.
227 , getRight(),(int) (mFooter.getBottom()+mFooter.getTranslationY( )));
Ted C 2013/05/07 21:49:07 leading comma should go on the previous line. Spa
Yusuf 2013/05/08 21:39:00 Done.
228 mBackground.draw(canvas);
229 canvas.restore();
230
231 super.onDraw(canvas);
113 } 232 }
114 233
115 /** 234 /**
116 * Prompts the content view to create the adapters for each section. This is 235 * Prompts the content view to create the adapters for each section. This is
117 * separated to be able to control the timing in a flexible manner. 236 * separated to be able to control the timing in a flexible manner.
118 */ 237 */
119 public void createAdapters() { 238 public void createAdapters() {
120 for (int i = 0; i < AutofillDialogConstants.NUM_SECTIONS; i++) { 239 for (int i = 0; i < AutofillDialogConstants.NUM_SECTIONS; i++) {
121 AutofillDialogMenuAdapter adapter; 240 AutofillDialogMenuAdapter adapter;
122 if (AutofillDialogUtils.containsCreditCardInfo(i)) { 241 if (AutofillDialogUtils.containsCreditCardInfo(i)) {
(...skipping 28 matching lines...) Expand all
151 * @param labels The label strings to be used for each section. 270 * @param labels The label strings to be used for each section.
152 */ 271 */
153 public void initializeLabelsForEachSection(String[] labels) { 272 public void initializeLabelsForEachSection(String[] labels) {
154 TextView labelView; 273 TextView labelView;
155 for (int i = 0; i < labels.length && i < NUM_SECTIONS; i++) { 274 for (int i = 0; i < labels.length && i < NUM_SECTIONS; i++) {
156 labelView = (TextView) findViewById(AutofillDialogUtils.getLabelIDFo rSection(i)); 275 labelView = (TextView) findViewById(AutofillDialogUtils.getLabelIDFo rSection(i));
157 labelView.setText(labels[i]); 276 labelView.setText(labels[i]);
158 } 277 }
159 } 278 }
160 279
280 private int getMeasuredTitleHeight() {
281 return mTitle.getMeasuredHeight();
282 }
283
284 private int getMeasuredFooterHeight() {
285 return mFooter.getMeasuredHeight();
286 }
287
288 private int getAdjustedContentLayoutHeight(int mode, View layout) {
289 assert mode != INVALID_LAYOUT;
290 int measuredContentHeight;
291 if (mode == LAYOUT_STEADY) {
292 measuredContentHeight = mSteadyLayout.getMeasuredHeight();
Ted C 2013/05/07 21:49:07 What happens if you rotate? Will all these measur
Yusuf 2013/05/08 21:39:00 Yes ,they are always in the hierarchy. This measur
293 } else if (mode == LAYOUT_FETCHING) {
294 measuredContentHeight = findViewById(R.id.loading_icon).getMeasuredH eight();
295 } else {
296 if (mode == LAYOUT_EDITING_CC_BILLING) {
297 // For CC_BILLING we have to measure again since it contains bot h CC and
298 // BILLING also. The last measure may be for just one of them.
299 int widthSpec = MeasureSpec.makeMeasureSpec(getWidth(), MeasureS pec.EXACTLY);
300 int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSP ECIFIED);
301 layout.measure(widthSpec, heightSpec);
Ted C 2013/05/07 21:49:07 Maybe a TODO to only do this if the mode that was
Yusuf 2013/05/08 21:39:00 Done.
302 }
303 measuredContentHeight = layout.getMeasuredHeight();
304 }
305 return Math.min(measuredContentHeight,
306 getMeasuredHeight() - getMeasuredTitleHeight() - getMeasuredFoot erHeight());
307 }
308
309 @Override
310 public void requestLayout () {
311 Exception e = new Exception();
312 e.printStackTrace();
Ted C 2013/05/07 21:49:07 probably should remove this :-) and for future re
Yusuf 2013/05/08 21:39:00 Done.
313 super.requestLayout();
314 }
315
161 @Override 316 @Override
162 protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) { 317 protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
163 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 318 mTitle.setTranslationY(0);
319 mContent.setTranslationY(0);
Ted C 2013/05/07 21:49:07 why do you need to reset these here? Maybe commen
Yusuf 2013/05/08 21:39:00 Done.
320 mFooter.setTranslationY(0);
321
322 int widthSpec = MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.EXAC TLY);
323 int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED) ;
324 measureChild(mTitle, widthSpec, heightSpec);
325 measureChild(mFooter, widthSpec, heightSpec);
326 heightSpec = MeasureSpec.makeMeasureSpec(
327 getHeight() - getMeasuredTitleHeight() - getMeasuredFooterHeight (),
328 MeasureSpec.AT_MOST);
329 mContent.measure(widthSpec, heightSpec);
330 long content = SystemClock.uptimeMillis();
Ted C 2013/05/07 21:49:07 not used?
Yusuf 2013/05/08 21:39:00 Done.
331
164 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 332 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
165 for (int i = 0; i < NUM_SECTIONS; i++) { 333 for (int i = 0; i < NUM_SECTIONS; i++) {
166 mSpinners[i].setDropDownWidth(mSpinners[i].getMeasuredWidth()); 334 mSpinners[i].setDropDownWidth(mSpinners[i].getMeasuredWidth());
167 mSpinners[i].setDropDownVerticalOffset(-mSpinners[i].getMeasured Height()); 335 mSpinners[i].setDropDownVerticalOffset(-mSpinners[i].getMeasured Height());
168 } 336 }
169 } 337 }
338 setMeasuredDimension(mFrameWidth, mFrameHeight);
Ted C 2013/05/07 21:49:07 why use getWidth() above and mFrameWidth here?
Yusuf 2013/05/08 21:39:00 Done.
339 }
340
341 @Override
342 protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
343 int totalHeight = getMeasuredTitleHeight()
344 + getMeasuredFooterHeight() + mContent.getMeasuredHeight();
345 int space = (getMeasuredHeight() - totalHeight) / 2 ;
Ted C 2013/05/07 21:49:07 I would rename space to specify something about th
Yusuf 2013/05/08 21:39:00 Done.
346 mTitle.layout(left, space, right, getMeasuredTitleHeight() + space);
347 mContent.layout(left, mTitle.getBottom(), right,
348 mTitle.getBottom() + mContent.getMeasuredHeight());
349 mFooter.layout(left, mContent.getBottom(), right, bottom - space);
170 } 350 }
171 351
172 /** 352 /**
173 * Set the listener for all the dropdown members in the layout. 353 * Set the listener for all the dropdown members in the layout.
174 * @param listener The listener object to attach to the dropdowns. 354 * @param listener The listener object to attach to the dropdowns.
175 */ 355 */
176 public void setOnItemSelectedListener(OnItemSelectedListener listener) { 356 public void setOnItemSelectedListener(OnItemSelectedListener listener) {
177 mOnItemSelectedListener = listener; 357 mOnItemSelectedListener = listener;
178 for (int i = 0; i < NUM_SECTIONS; i++) mSpinners[i].setOnItemSelectedLis tener(listener); 358 for (int i = 0; i < NUM_SECTIONS; i++) mSpinners[i].setOnItemSelectedLis tener(listener);
179 } 359 }
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 */ 435 */
256 public void updateMenuItemsForSection(int section, 436 public void updateMenuItemsForSection(int section,
257 List<AutofillDialogMenuItem> items, final int selectedMenuItem) { 437 List<AutofillDialogMenuItem> items, final int selectedMenuItem) {
258 final Spinner spinner = mSpinners[section]; 438 final Spinner spinner = mSpinners[section];
259 // Set the listener to null and reset it after updating the menu items t o avoid getting an 439 // Set the listener to null and reset it after updating the menu items t o avoid getting an
260 // onItemSelected call when the first item is selected after updating th e items. 440 // onItemSelected call when the first item is selected after updating th e items.
261 spinner.setOnItemSelectedListener(null); 441 spinner.setOnItemSelectedListener(null);
262 AutofillDialogMenuAdapter adapter = mAdapters[section]; 442 AutofillDialogMenuAdapter adapter = mAdapters[section];
263 adapter.clear(); 443 adapter.clear();
264 adapter.addAll(items); 444 adapter.addAll(items);
445 spinner.setSelection(selectedMenuItem);
265 spinner.post(new Runnable() { 446 spinner.post(new Runnable() {
266 @Override 447 @Override
267 public void run() { 448 public void run() {
268 spinner.setSelection(selectedMenuItem);
269 spinner.setOnItemSelectedListener(mOnItemSelectedListener); 449 spinner.setOnItemSelectedListener(mOnItemSelectedListener);
270 } 450 }
271 }); 451 });
272 } 452 }
273 453
274 /** 454 /**
275 * Updates a dropdown selection. 455 * Updates a dropdown selection.
276 * @param section The dialog section. 456 * @param section The dialog section.
277 * @param selectedMenuItem The index of the selected menu item, or -1. 457 * @param selectedMenuItem The index of the selected menu item, or -1.
278 */ 458 */
(...skipping 15 matching lines...) Expand all
294 setVisibilityForEditLayouts(false); 474 setVisibilityForEditLayouts(false);
295 if (mode == LAYOUT_FETCHING) { 475 if (mode == LAYOUT_FETCHING) {
296 mSteadyLayout.setVisibility(GONE); 476 mSteadyLayout.setVisibility(GONE);
297 findViewById(R.id.loading_icon).setVisibility(VISIBLE); 477 findViewById(R.id.loading_icon).setVisibility(VISIBLE);
298 return; 478 return;
299 } 479 }
300 findViewById(R.id.loading_icon).setVisibility(GONE); 480 findViewById(R.id.loading_icon).setVisibility(GONE);
301 mSteadyLayout.setVisibility(VISIBLE); 481 mSteadyLayout.setVisibility(VISIBLE);
302 if (mode == LAYOUT_STEADY) return; 482 if (mode == LAYOUT_STEADY) return;
303 483
304 addTranslateAnimations(mode);
305 addDisappearAnimationForSteadyLayout();
306 View centeredLayout = mEditLayouts[getSectionForLayoutMode(mode)]; 484 View centeredLayout = mEditLayouts[getSectionForLayoutMode(mode)];
307 addAppearAnimationForEditLayout(mode, centeredLayout);
308 485
309 centeredLayout.setVisibility(VISIBLE);
310 if (mode == LAYOUT_EDITING_CC_BILLING) { 486 if (mode == LAYOUT_EDITING_CC_BILLING) {
311 mEditLayouts[SECTION_CC].setVisibility(VISIBLE); 487 mEditLayouts[SECTION_CC].setVisibility(VISIBLE);
312 mEditLayouts[SECTION_BILLING].setVisibility(VISIBLE); 488 mEditLayouts[SECTION_BILLING].setVisibility(VISIBLE);
489 } else if (mode == LAYOUT_EDITING_CC || mode == LAYOUT_EDITING_BILLING) {
490 mEditLayouts[SECTION_CC_BILLING].setVisibility(VISIBLE);
313 } 491 }
314 ((View) centeredLayout.getParent()).setVisibility(VISIBLE); 492 centeredLayout.setVisibility(VISIBLE);
315 centeredLayout.animate(); 493 final float fromHeight = mSteadyLayout.getMeasuredHeight();
316 mSteadyLayout.animate(); 494 final float toHeight = getAdjustedContentLayoutHeight(mode, centeredLayo ut);
495 mCurrentHeightAnimator =
496 ObjectAnimator.ofFloat(this, "VisibleContentHeight", fromHeight, toHeight);
Ted C 2013/05/07 21:49:07 Maybe use a Property to avoid the reflection?
Yusuf 2013/05/08 21:39:00 I am not sure if the objectAnimator framework uses
David Trainor- moved to gerrit 2013/05/10 22:59:55 It uses reflection by looking for a method called
Yusuf 2013/05/14 02:15:10 Done.
497 mCurrentHeightAnimator.setDuration(ANIMATION_DURATION_MS);
498 mCurrentHeightAnimator.addUpdateListener(new AnimatorUpdateListener() {
499 @Override
500 public void onAnimationUpdate(ValueAnimator animator) {
501 invalidate();
Ted C 2013/05/07 21:49:07 If you can, it should be "slightly" faster to inva
Yusuf 2013/05/08 21:39:00 The header and the footer is also moving, so every
502 }
503 });
504 mCurrentHeightAnimator.addListener(new AnimatorListenerAdapter() {
505 @Override
506 public void onAnimationStart(Animator animator) {
507 mTransitionAnimationPlaying = true;
508 }
509
510 @Override
511 public void onAnimationEnd(Animator animator) {
512 mTransitionAnimationPlaying = false;
513 mVisibleContentHeight = toHeight;
514 }
515 });
516 mCurrentLayoutAnimation = addTranslateAnimations(mode);
517 mCurrentLayoutAnimation.addAnimation(addAppearAnimationForEditLayout(mod e, centeredLayout));
518 mAnimateOnNextLayoutChange = true;
519
317 postDelayed(mDismissSteadyLayoutRunnable, ANIMATION_DURATION_MS); 520 postDelayed(mDismissSteadyLayoutRunnable, ANIMATION_DURATION_MS);
318
319 mCurrentLayout = mode; 521 mCurrentLayout = mode;
320 } 522 }
321 523
322 private void setVisibilityForEditLayouts(boolean visible) { 524 private void setVisibilityForEditLayouts(boolean visible) {
323 int visibility = visible ? VISIBLE : GONE; 525 int visibility = visible ? VISIBLE : GONE;
324 for (int i = 0; i < NUM_SECTIONS; i++) { 526 for (int i = 0; i < NUM_SECTIONS; i++) {
325 if (mEditLayouts[i] != null) mEditLayouts[i].setVisibility(visibilit y); 527 if (mEditLayouts[i] != null) mEditLayouts[i].setVisibility(visibilit y);
326 } 528 }
327 } 529 }
328 530
329 /** 531 /**
330 * Sets the visibility for all items related with the given section. 532 * Sets the visibility for all items related with the given section.
331 * @param section The section that will change visibility. 533 * @param section The section that will change visibility.
332 * @param visible Whether the section should be visible. 534 * @param visible Whether the section should be visible.
333 */ 535 */
334 public void setVisibilityForSection(int section, boolean visible) { 536 public void setVisibilityForSection(int section, boolean visible) {
335 int visibility = visible ? VISIBLE : GONE; 537 int visibility = visible ? VISIBLE : GONE;
336 mSpinners[section].setVisibility(visibility); 538 mSpinners[section].setVisibility(visibility);
337 View labelView = findViewById(AutofillDialogUtils.getLabelIDForSection(s ection)); 539 View labelView = findViewById(AutofillDialogUtils.getLabelIDForSection(s ection));
338 if (labelView != null) labelView.setVisibility(visibility); 540 if (labelView != null) labelView.setVisibility(visibility);
339 } 541 }
340 542
341 private void addAppearAnimationForEditLayout(int mode, View layout) { 543 private AnimationSet addAppearAnimationForEditLayout(int mode, View layout) {
342 View centerView = mSpinners[getSectionForLayoutMode(mode)]; 544 View centerView = mSpinners[getSectionForLayoutMode(mode)];
343 float yOffset = centerView.getY() - (float) centerView.getHeight() / 2; 545 float yOffset = centerView.getY() - (float) centerView.getHeight() / 2;
344 546
345 TranslateAnimation toLocationAnimation = new TranslateAnimation(0, 0, yO ffset, 0); 547 TranslateAnimation toLocationAnimation = new TranslateAnimation(0, 0, yO ffset, 0);
346 toLocationAnimation.setDuration(ANIMATION_DURATION_MS); 548 toLocationAnimation.setDuration(ANIMATION_DURATION_MS);
347 ScaleAnimation scaleAnimation = new ScaleAnimation(1, 1, 0, 1, 549 ScaleAnimation scaleAnimation = new ScaleAnimation(1, 1, 0, 1,
348 Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.5f) ; 550 Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.5f) ;
349 scaleAnimation.setDuration(ANIMATION_DURATION_MS); 551 scaleAnimation.setDuration(ANIMATION_DURATION_MS);
350 scaleAnimation.setStartOffset(ANIMATION_DURATION_MS / 4);
351 552
352 AnimationSet appearAnimation = new AnimationSet(true); 553 AnimationSet appearAnimation = new AnimationSet(true);
353 appearAnimation.addAnimation(toLocationAnimation); 554 appearAnimation.addAnimation(toLocationAnimation);
354 appearAnimation.addAnimation(scaleAnimation); 555 appearAnimation.addAnimation(scaleAnimation);
355 556
356 layout.setAnimation(appearAnimation); 557 layout.setAnimation(appearAnimation);
558 return appearAnimation;
357 } 559 }
358 560
359 private void addDisappearAnimationForSteadyLayout() { 561 private AnimationSet addTranslateAnimations(int mode) {
360 ScaleAnimation scaleDownAnimation = new ScaleAnimation(1, 1, 1, 0,
361 Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0.5f) ;
362 scaleDownAnimation.setDuration(ANIMATION_DURATION_MS / 2);
363 scaleDownAnimation.setStartOffset(ANIMATION_DURATION_MS / 2);
364
365 mSteadyLayout.setAnimation(scaleDownAnimation);
366 }
367
368 private void addTranslateAnimations(int mode) {
369 float distance = getResources(). 562 float distance = getResources().
370 getDimensionPixelSize(R.dimen.autofill_translation_anim_distance ); 563 getDimensionPixelSize(R.dimen.autofill_translation_anim_distance );
371 TranslateAnimation toTopAnimation = new TranslateAnimation(0, 0, 0, -dis tance); 564 TranslateAnimation toTopAnimation = new TranslateAnimation(0, 0, 0, -dis tance);
372 toTopAnimation.setDuration(ANIMATION_DURATION_MS); 565 toTopAnimation.setDuration(ANIMATION_DURATION_MS);
373 TranslateAnimation toBottomAnimation = new TranslateAnimation(0, 0, 0, d istance); 566 TranslateAnimation toBottomAnimation = new TranslateAnimation(0, 0, 0, d istance);
374 toBottomAnimation.setDuration(ANIMATION_DURATION_MS); 567 toBottomAnimation.setDuration(ANIMATION_DURATION_MS);
375 for (int i = 0; i < mSteadyLayout.getChildCount(); i++) { 568 for (int i = 0; i < mSteadyLayout.getChildCount(); i++) {
376 View currentChild = mSteadyLayout.getChildAt(i); 569 View currentChild = mSteadyLayout.getChildAt(i);
377 if (currentChild.getVisibility() == GONE) continue; 570 if (currentChild.getVisibility() == GONE) continue;
378 571
379 if (currentChild.getTop() <= 572 if (currentChild.getTop() <=
380 mSpinners[getSectionForLayoutMode(mode)].getTop()) { 573 mSpinners[getSectionForLayoutMode(mode)].getTop()) {
381 currentChild.setAnimation(toTopAnimation); 574 currentChild.setAnimation(toTopAnimation);
382 currentChild.animate(); 575 } else {
383 } else if (currentChild.getTop() >
384 mSpinners[getSectionForLayoutMode(mode)].getTop()) {
385 currentChild.setAnimation(toBottomAnimation); 576 currentChild.setAnimation(toBottomAnimation);
386 currentChild.animate();
387 } 577 }
388 } 578 }
579 AnimationSet combined = new AnimationSet(true);
580 combined.addAnimation(toBottomAnimation);
581 combined.addAnimation(toTopAnimation);
582 return combined;
389 } 583 }
390 584
391 private static int getSectionForLayoutMode(int mode) { 585 private static int getSectionForLayoutMode(int mode) {
392 switch (mode) { 586 switch (mode) {
393 case LAYOUT_EDITING_EMAIL: 587 case LAYOUT_EDITING_EMAIL:
394 return SECTION_EMAIL; 588 return SECTION_EMAIL;
395 case LAYOUT_EDITING_CC: 589 case LAYOUT_EDITING_CC:
396 return SECTION_CC; 590 return SECTION_CC;
397 case LAYOUT_EDITING_BILLING: 591 case LAYOUT_EDITING_BILLING:
398 return SECTION_BILLING; 592 return SECTION_BILLING;
(...skipping 14 matching lines...) Expand all
413 */ 607 */
414 public static int getLayoutModeForSection(int section) { 608 public static int getLayoutModeForSection(int section) {
415 assert(section != AutofillDialogUtils.INVALID_SECTION); 609 assert(section != AutofillDialogUtils.INVALID_SECTION);
416 for (int i = 0; i < AutofillDialogConstants.NUM_SECTIONS; i++) { 610 for (int i = 0; i < AutofillDialogConstants.NUM_SECTIONS; i++) {
417 if (getSectionForLayoutMode(i) == section) return i; 611 if (getSectionForLayoutMode(i) == section) return i;
418 } 612 }
419 assert(false); 613 assert(false);
420 return INVALID_LAYOUT; 614 return INVALID_LAYOUT;
421 } 615 }
422 616
617 /**
618 * @return The current visible content height.
619 */
620 public float getVisibleContentHeight() {
621 return mVisibleContentHeight;
622 }
623
624 /**
625 * Sets the visible content height. This value is used for setting the clipR ect for the canvas
626 * in layout transitions.
627 * @param height The value to use for the visible content height.
628 */
629 public void setVisibleContentHeight(float height) {
630 mVisibleContentHeight = height;
631 }
632
423 private static class AutofillDialogMenuAdapter extends ArrayAdapter<Autofill DialogMenuItem> { 633 private static class AutofillDialogMenuAdapter extends ArrayAdapter<Autofill DialogMenuItem> {
424 protected boolean mShouldShowCVC = true; 634 protected boolean mShouldShowCVC = true;
425 private int mSection; 635 private int mSection;
426 private OnItemEditButtonClickedListener mOnItemEditButtonClickedListener ; 636 private OnItemEditButtonClickedListener mOnItemEditButtonClickedListener ;
427 637
428 public AutofillDialogMenuAdapter( 638 public AutofillDialogMenuAdapter(
429 int section, 639 int section,
430 Context context, 640 Context context,
431 List<AutofillDialogMenuItem> objects) { 641 List<AutofillDialogMenuItem> objects) {
432 super(context, R.layout.autofill_menu_item, objects); 642 super(context, R.layout.autofill_menu_item, objects);
433 mSection = section; 643 mSection = section;
434 } 644 }
435 645
436 public void setOnItemEditButtonClickedListener(OnItemEditButtonClickedLi stener listener) { 646 public void setOnItemEditButtonClickedListener(OnItemEditButtonClickedLi stener listener) {
437 mOnItemEditButtonClickedListener = listener; 647 mOnItemEditButtonClickedListener = listener;
438 } 648 }
439 649
440 /** 650 /**
441 * @return Whether the CVC Edit Box should be shown. 651 * @return Whether the CVC Edit Box should be shown.
442 */ 652 */
443 protected boolean shouldShowCVC() { 653 protected boolean shouldShowCVC() {
444 return mShouldShowCVC; 654 return mShouldShowCVC;
445 } 655 }
446 656
447 @Override 657 @Override
448 public View getView(int position, View convertView, ViewGroup parent) { 658 public View getView(int position, View convertView, ViewGroup parent) {
449 return initView(position, convertView, parent, false); 659 return initView(position, convertView, parent, false,
660 AutofillDialogUtils.getItemLayoutIDForSection(mSection));
450 } 661 }
451 662
452 @Override 663 @Override
453 public View getDropDownView(int position, View convertView, ViewGroup pa rent) { 664 public View getDropDownView(int position, View convertView, ViewGroup pa rent) {
454 return initView(position, convertView, parent, true); 665 return initView(position, convertView, parent, true, R.layout.autofi ll_menu_item);
455 } 666 }
456 667
457 private View initView( 668 private View initView(
458 final int position, View convertView, final ViewGroup parent, bo olean showButton) { 669 final int position, View convertView, final ViewGroup parent, bo olean showButton,
670 int layoutID) {
Ted C 2013/05/07 21:49:07 lowercase d in layoutId
Yusuf 2013/05/08 21:39:00 Done.
459 if (convertView == null) { 671 if (convertView == null) {
460 convertView = View.inflate(getContext(), 672 convertView = View.inflate(getContext(), layoutID, null);
461 R.layout.autofill_menu_item, null);
462 mShouldShowCVC = true; 673 mShouldShowCVC = true;
463 } 674 }
464 675
465 AutofillDialogMenuItem item = getItem(position); 676 AutofillDialogMenuItem item = getItem(position);
466 ImageView icon = (ImageView) convertView.findViewById(R.id.cc_icon); 677 ImageView icon = (ImageView) convertView.findViewById(R.id.cc_icon);
467 TextView line1 = (TextView) convertView.findViewById(R.id.adapter_it em_line_1); 678 TextView line1 = (TextView) convertView.findViewById(R.id.adapter_it em_line_1);
468 TextView line2 = (TextView) convertView.findViewById(R.id.adapter_it em_line_2); 679 TextView line2 = (TextView) convertView.findViewById(R.id.adapter_it em_line_2);
469 Button button = (Button) convertView.findViewById(R.id.adapter_item_ edit_button); 680 Button button = (Button) convertView.findViewById(R.id.adapter_item_ edit_button);
470 681
471 if (icon != null) { 682 if (icon != null) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 cvcEdit.setVisibility(VISIBLE); 751 cvcEdit.setVisibility(VISIBLE);
541 if (!TextUtils.isEmpty(mCVCHint)) { 752 if (!TextUtils.isEmpty(mCVCHint)) {
542 cvcEdit.setHint(mCVCHint); 753 cvcEdit.setHint(mCVCHint);
543 } 754 }
544 cvcEdit.setCompoundDrawables(null, null, mCVCIcon, null); 755 cvcEdit.setCompoundDrawables(null, null, mCVCIcon, null);
545 } 756 }
546 return spinnerView; 757 return spinnerView;
547 } 758 }
548 } 759 }
549 } 760 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698