Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |