| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.chrome.browser.firstrun; | |
| 6 | |
| 7 import android.content.Context; | |
| 8 import android.graphics.Bitmap; | |
| 9 import android.graphics.drawable.Drawable; | |
| 10 import android.os.Bundle; | |
| 11 import android.text.TextPaint; | |
| 12 import android.text.TextUtils; | |
| 13 import android.text.method.LinkMovementMethod; | |
| 14 import android.text.style.ClickableSpan; | |
| 15 import android.util.AttributeSet; | |
| 16 import android.view.View; | |
| 17 import android.widget.AdapterView; | |
| 18 import android.widget.ArrayAdapter; | |
| 19 import android.widget.Button; | |
| 20 import android.widget.FrameLayout; | |
| 21 import android.widget.ImageView; | |
| 22 import android.widget.LinearLayout; | |
| 23 import android.widget.Spinner; | |
| 24 import android.widget.TextView; | |
| 25 | |
| 26 import org.chromium.base.ApiCompatibilityUtils; | |
| 27 import org.chromium.chrome.R; | |
| 28 import org.chromium.chrome.browser.firstrun.ImageCarousel.ImageCarouselPositionC
hangeListener; | |
| 29 import org.chromium.chrome.browser.profiles.ProfileDownloader; | |
| 30 import org.chromium.chrome.browser.signin.SigninManager; | |
| 31 import org.chromium.sync.signin.AccountManagerHelper; | |
| 32 import org.chromium.ui.text.SpanApplier; | |
| 33 import org.chromium.ui.text.SpanApplier.SpanInfo; | |
| 34 | |
| 35 import java.util.List; | |
| 36 | |
| 37 /** | |
| 38 * This view allows the user to select an account to log in to, add an account, | |
| 39 * cancel account selection, etc. Users of this class should | |
| 40 * {@link AccountFirstRunView#setListener(Listener)} after the view has been | |
| 41 * inflated. | |
| 42 */ | |
| 43 public class AccountFirstRunView extends FrameLayout | |
| 44 implements ImageCarouselPositionChangeListener, ProfileDownloader.Observ
er { | |
| 45 | |
| 46 /** | |
| 47 * Callbacks for various account selection events. | |
| 48 */ | |
| 49 public interface Listener { | |
| 50 /** | |
| 51 * The user canceled account selection. | |
| 52 */ | |
| 53 public void onAccountSelectionCanceled(); | |
| 54 | |
| 55 /** | |
| 56 * The user wants to make a new account. | |
| 57 */ | |
| 58 public void onNewAccount(); | |
| 59 | |
| 60 /** | |
| 61 * The user selected an account. | |
| 62 * This call will be followed by either {@link #onSettingsClicked} or | |
| 63 * {@link #onDoneClicked}. | |
| 64 * @param accountName The name of the account | |
| 65 */ | |
| 66 public void onAccountSelected(String accountName); | |
| 67 | |
| 68 /** | |
| 69 * The user has completed the dialog flow. | |
| 70 * This will only be called after {@link #onAccountSelected} and should
exit the View. | |
| 71 */ | |
| 72 public void onDoneClicked(); | |
| 73 | |
| 74 /** | |
| 75 * The user has selected to view sync settings. | |
| 76 * This will only be called after {@link #onAccountSelected} and should
exit the View. | |
| 77 */ | |
| 78 public void onSettingsClicked(); | |
| 79 | |
| 80 /** | |
| 81 * Failed to set the forced account because it wasn't found. | |
| 82 * @param forcedAccountName The name of the forced-sign-in account | |
| 83 */ | |
| 84 public void onFailedToSetForcedAccount(String forcedAccountName); | |
| 85 } | |
| 86 | |
| 87 private class SpinnerOnItemSelectedListener implements AdapterView.OnItemSel
ectedListener { | |
| 88 @Override | |
| 89 public void onItemSelected(AdapterView<?> parent, View view, int pos, lo
ng id) { | |
| 90 String accountName = parent.getItemAtPosition(pos).toString(); | |
| 91 if (accountName.equals(mAddAnotherAccount)) { | |
| 92 // Don't allow "add account" to remain selected. http://crbug.co
m/421052 | |
| 93 int oldPosition = mArrayAdapter.getPosition(mAccountName); | |
| 94 if (oldPosition == -1) oldPosition = 0; | |
| 95 mSpinner.setSelection(oldPosition, false); | |
| 96 | |
| 97 mListener.onNewAccount(); | |
| 98 } else { | |
| 99 mAccountName = accountName; | |
| 100 if (!mPositionSetProgrammatically) mImageCarousel.scrollTo(pos,
false, false); | |
| 101 mPositionSetProgrammatically = false; | |
| 102 } | |
| 103 } | |
| 104 @Override | |
| 105 public void onNothingSelected(AdapterView<?> parent) { | |
| 106 mAccountName = parent.getItemAtPosition(0).toString(); | |
| 107 } | |
| 108 } | |
| 109 | |
| 110 private static final String TAG = "AccountFirstRunView"; | |
| 111 | |
| 112 private static final int EXPERIMENT_TITLE_VARIANT_MASK = 1; | |
| 113 private static final int EXPERIMENT_SUMMARY_VARIANT_MASK = 2; | |
| 114 private static final int EXPERIMENT_LAYOUT_VARIANT_MASK = 4; | |
| 115 private static final int EXPERIMENT_MAX_VALUE = 7; | |
| 116 | |
| 117 private static final String SETTINGS_LINK_OPEN = "<LINK1>"; | |
| 118 private static final String SETTINGS_LINK_CLOSE = "</LINK1>"; | |
| 119 | |
| 120 private AccountManagerHelper mAccountManagerHelper; | |
| 121 private List<String> mAccountNames; | |
| 122 private ArrayAdapter<CharSequence> mArrayAdapter; | |
| 123 private ImageCarousel mImageCarousel; | |
| 124 private Button mPositiveButton; | |
| 125 private Button mNegativeButton; | |
| 126 private TextView mTitle; | |
| 127 private TextView mDescriptionText; | |
| 128 private Listener mListener; | |
| 129 private Spinner mSpinner; | |
| 130 private Drawable mSpinnerBackground; | |
| 131 private String mForcedAccountName; | |
| 132 private String mAccountName; | |
| 133 private String mAddAnotherAccount; | |
| 134 private ProfileDataCache mProfileData; | |
| 135 private boolean mSignedIn; | |
| 136 private boolean mPositionSetProgrammatically; | |
| 137 private int mDescriptionTextId; | |
| 138 private int mCancelButtonTextId; | |
| 139 private boolean mIsChildAccount; | |
| 140 private boolean mHorizontalModeEnabled = true; | |
| 141 private boolean mShowSettingsSpan = true; | |
| 142 | |
| 143 public AccountFirstRunView(Context context, AttributeSet attrs) { | |
| 144 super(context, attrs); | |
| 145 mAccountManagerHelper = AccountManagerHelper.get(getContext().getApplica
tionContext()); | |
| 146 } | |
| 147 | |
| 148 /** | |
| 149 * Initializes this view with profile images and full names. | |
| 150 * @param profileData ProfileDataCache that will be used to call to retrieve
user account info. | |
| 151 */ | |
| 152 public void init(ProfileDataCache profileData) { | |
| 153 setProfileDataCache(profileData); | |
| 154 } | |
| 155 | |
| 156 /** | |
| 157 * Sets the profile data cache. | |
| 158 * @param profileData ProfileDataCache that will be used to call to retrieve
user account info. | |
| 159 */ | |
| 160 public void setProfileDataCache(ProfileDataCache profileData) { | |
| 161 mProfileData = profileData; | |
| 162 mProfileData.setObserver(this); | |
| 163 updateProfileImages(); | |
| 164 } | |
| 165 | |
| 166 @Override | |
| 167 protected void onFinishInflate() { | |
| 168 super.onFinishInflate(); | |
| 169 | |
| 170 mImageCarousel = (ImageCarousel) findViewById(R.id.image_slider); | |
| 171 mImageCarousel.setListener(this); | |
| 172 | |
| 173 mPositiveButton = (Button) findViewById(R.id.positive_button); | |
| 174 mNegativeButton = (Button) findViewById(R.id.negative_button); | |
| 175 | |
| 176 // A workaround for Android support library ignoring padding set in XML.
b/20307607 | |
| 177 int padding = getResources().getDimensionPixelSize(R.dimen.fre_button_pa
dding); | |
| 178 ApiCompatibilityUtils.setPaddingRelative(mPositiveButton, padding, 0, pa
dding, 0); | |
| 179 ApiCompatibilityUtils.setPaddingRelative(mNegativeButton, padding, 0, pa
dding, 0); | |
| 180 | |
| 181 mTitle = (TextView) findViewById(R.id.title); | |
| 182 mDescriptionText = (TextView) findViewById(R.id.description); | |
| 183 // For the spans to be clickable. | |
| 184 mDescriptionText.setMovementMethod(LinkMovementMethod.getInstance()); | |
| 185 mDescriptionTextId = R.string.fre_account_choice_description; | |
| 186 | |
| 187 // TODO(peconn): Ensure this is changed to R.string.cancel when used in
Settings > Sign In. | |
| 188 mCancelButtonTextId = R.string.fre_skip_text; | |
| 189 | |
| 190 // Set the invisible TextView to contain the longest text the visible Te
xtView can hold. | |
| 191 // It assumes that the signed in description for child accounts is the l
ongest text. | |
| 192 ((TextView) findViewById(R.id.longest_description)).setText(getSignedInD
escription(true)); | |
| 193 | |
| 194 mAddAnotherAccount = getResources().getString(R.string.fre_add_account); | |
| 195 | |
| 196 mSpinner = (Spinner) findViewById(R.id.google_accounts_spinner); | |
| 197 mSpinnerBackground = mSpinner.getBackground(); | |
| 198 mArrayAdapter = new ArrayAdapter<CharSequence>( | |
| 199 getContext().getApplicationContext(), R.layout.fre_spinner_text)
; | |
| 200 | |
| 201 mArrayAdapter.setDropDownViewResource(R.layout.fre_spinner_dropdown); | |
| 202 mSpinner.setAdapter(mArrayAdapter); | |
| 203 mSpinner.setOnItemSelectedListener(new SpinnerOnItemSelectedListener()); | |
| 204 | |
| 205 // Only set the spinner's content description right before the accessibi
lity action is going | |
| 206 // to be performed. Otherwise, the the content description is read when
the | |
| 207 // AccountFirstRunView is created because setting the spinner's adapter
causes a | |
| 208 // TYPE_VIEW_SELECTED event. ViewPager loads the next and previous pages
according to | |
| 209 // it's off-screen page limit, which is one by default, so without this
the content | |
| 210 // description ends up being read when the card before this one shown. | |
| 211 mSpinner.setAccessibilityDelegate(new AccessibilityDelegate() { | |
| 212 @Override | |
| 213 public boolean performAccessibilityAction(View host, int action, Bun
dle args) { | |
| 214 if (mSpinner.getContentDescription() == null) { | |
| 215 mSpinner.setContentDescription(getResources().getString( | |
| 216 R.string.accessibility_fre_account_spinner)); | |
| 217 } | |
| 218 return super.performAccessibilityAction(host, action, args); | |
| 219 } | |
| 220 }); | |
| 221 | |
| 222 showSignInPage(); | |
| 223 } | |
| 224 | |
| 225 @Override | |
| 226 protected void onAttachedToWindow() { | |
| 227 super.onAttachedToWindow(); | |
| 228 updateAccounts(); | |
| 229 } | |
| 230 | |
| 231 @Override | |
| 232 public void onWindowVisibilityChanged(int visibility) { | |
| 233 super.onWindowVisibilityChanged(visibility); | |
| 234 if (visibility == View.VISIBLE) { | |
| 235 if (updateAccounts()) { | |
| 236 // A new account has been added and the visibility has returned
to us. | |
| 237 // The updateAccounts function will have selected the new accoun
t. | |
| 238 // Shortcut to confirm sign in page. | |
| 239 showConfirmSignInPage(); | |
| 240 } | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 @Override | |
| 245 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
| 246 // This assumes that view's layout_width is set to match_parent. | |
| 247 assert MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY; | |
| 248 int width = MeasureSpec.getSize(widthMeasureSpec); | |
| 249 int height = MeasureSpec.getSize(heightMeasureSpec); | |
| 250 LinearLayout content = (LinearLayout) findViewById(R.id.fre_content); | |
| 251 int paddingStart = 0; | |
| 252 if (mHorizontalModeEnabled | |
| 253 && width >= 2 * getResources().getDimension(R.dimen.fre_image_ca
rousel_width) | |
| 254 && width > height) { | |
| 255 content.setOrientation(LinearLayout.HORIZONTAL); | |
| 256 paddingStart = getResources().getDimensionPixelSize(R.dimen.fre_marg
in); | |
| 257 } else { | |
| 258 content.setOrientation(LinearLayout.VERTICAL); | |
| 259 } | |
| 260 ApiCompatibilityUtils.setPaddingRelative(content, | |
| 261 paddingStart, | |
| 262 content.getPaddingTop(), | |
| 263 ApiCompatibilityUtils.getPaddingEnd(content), | |
| 264 content.getPaddingBottom()); | |
| 265 super.onMeasure(widthMeasureSpec, heightMeasureSpec); | |
| 266 } | |
| 267 | |
| 268 /** | |
| 269 * Changes the visuals slightly for when this view appears in the recent tab
s page instead of | |
| 270 * in first run. For example, the title text is changed as well as the butto
n style. | |
| 271 * This is currently used in the Recent Tabs Promo and the bookmarks page. | |
| 272 */ | |
| 273 public void configureForRecentTabsOrBookmarksPage() { | |
| 274 mHorizontalModeEnabled = false; | |
| 275 mShowSettingsSpan = false; | |
| 276 | |
| 277 setBackgroundResource(R.color.ntp_bg); | |
| 278 mTitle.setText(R.string.sign_in_to_chrome); | |
| 279 | |
| 280 mCancelButtonTextId = R.string.cancel; | |
| 281 setUpCancelButton(); | |
| 282 | |
| 283 setPadding(0, 0, 0, | |
| 284 getResources().getDimensionPixelOffset(R.dimen.sign_in_promo_pad
ding_bottom)); | |
| 285 } | |
| 286 | |
| 287 /** | |
| 288 * Changes the visuals slightly for when this view is shown in a subsequent
run after user adds | |
| 289 * a Google account to the device. | |
| 290 */ | |
| 291 public void configureForAddAccountPromo() { | |
| 292 int experimentGroup = SigninManager.getAndroidSigninPromoExperimentGroup
(); | |
| 293 assert experimentGroup >= 0 && experimentGroup <= EXPERIMENT_MAX_VALUE; | |
| 294 | |
| 295 if ((experimentGroup & EXPERIMENT_TITLE_VARIANT_MASK) != 0) { | |
| 296 mTitle.setText(R.string.make_chrome_yours); | |
| 297 } | |
| 298 | |
| 299 mDescriptionTextId = (experimentGroup & EXPERIMENT_SUMMARY_VARIANT_MASK)
!= 0 | |
| 300 ? R.string.sign_in_to_chrome_summary_variant : R.string.sign_in_
to_chrome_summary; | |
| 301 | |
| 302 if ((experimentGroup & EXPERIMENT_LAYOUT_VARIANT_MASK) != 0) { | |
| 303 mImageCarousel.setVisibility(GONE); | |
| 304 | |
| 305 ImageView illustrationView = new ImageView(getContext()); | |
| 306 illustrationView.setImageResource(R.drawable.signin_promo_illustrati
on); | |
| 307 illustrationView.setBackgroundColor(ApiCompatibilityUtils.getColor(g
etResources(), | |
| 308 R.color.illustration_background_color)); | |
| 309 | |
| 310 LinearLayout linearLayout = (LinearLayout) findViewById(R.id.fre_acc
ount_linear_layout); | |
| 311 linearLayout.addView(illustrationView, 0); | |
| 312 } | |
| 313 } | |
| 314 | |
| 315 /** | |
| 316 * Enable or disable UI elements so the user can't select an account, cancel
, etc. | |
| 317 * | |
| 318 * @param enabled The state to change to. | |
| 319 */ | |
| 320 public void setButtonsEnabled(boolean enabled) { | |
| 321 mPositiveButton.setEnabled(enabled); | |
| 322 mNegativeButton.setEnabled(enabled); | |
| 323 } | |
| 324 | |
| 325 /** | |
| 326 * Set the account selection event listener. See {@link Listener} | |
| 327 * | |
| 328 * @param listener The listener. | |
| 329 */ | |
| 330 public void setListener(Listener listener) { | |
| 331 mListener = listener; | |
| 332 } | |
| 333 | |
| 334 /** | |
| 335 * Refresh the list of available system account. | |
| 336 * @return Whether any new accounts were added (the first newly added accoun
t will now be | |
| 337 * selected). | |
| 338 */ | |
| 339 private boolean updateAccounts() { | |
| 340 if (mSignedIn) return false; | |
| 341 | |
| 342 List<String> oldAccountNames = mAccountNames; | |
| 343 mAccountNames = mAccountManagerHelper.getGoogleAccountNames(); | |
| 344 int accountToSelect = 0; | |
| 345 if (isInForcedAccountMode()) { | |
| 346 accountToSelect = mAccountNames.indexOf(mForcedAccountName); | |
| 347 if (accountToSelect < 0) { | |
| 348 mListener.onFailedToSetForcedAccount(mForcedAccountName); | |
| 349 return false; | |
| 350 } | |
| 351 } else { | |
| 352 accountToSelect = getIndexOfNewElement( | |
| 353 oldAccountNames, mAccountNames, mSpinner.getSelectedItemPosi
tion()); | |
| 354 } | |
| 355 | |
| 356 mArrayAdapter.clear(); | |
| 357 if (!mAccountNames.isEmpty()) { | |
| 358 mSpinner.setVisibility(View.VISIBLE); | |
| 359 mArrayAdapter.addAll(mAccountNames); | |
| 360 mArrayAdapter.add(mAddAnotherAccount); | |
| 361 | |
| 362 setUpSignInButton(true); | |
| 363 mDescriptionText.setText(mDescriptionTextId); | |
| 364 | |
| 365 } else { | |
| 366 mSpinner.setVisibility(View.GONE); | |
| 367 mArrayAdapter.add(mAddAnotherAccount); | |
| 368 setUpSignInButton(false); | |
| 369 mDescriptionText.setText(R.string.fre_no_account_choice_description)
; | |
| 370 } | |
| 371 | |
| 372 if (mProfileData != null) mProfileData.update(); | |
| 373 updateProfileImages(); | |
| 374 | |
| 375 mSpinner.setSelection(accountToSelect); | |
| 376 mAccountName = mArrayAdapter.getItem(accountToSelect).toString(); | |
| 377 mImageCarousel.scrollTo(accountToSelect, false, false); | |
| 378 | |
| 379 return oldAccountNames != null | |
| 380 && !(oldAccountNames.size() == mAccountNames.size() | |
| 381 && oldAccountNames.containsAll(mAccountNames)); | |
| 382 } | |
| 383 | |
| 384 /** | |
| 385 * Attempt to select a new element that is in the new list, but not in the o
ld list. | |
| 386 * If no such element exist and both the new and the old lists are the same
then keep | |
| 387 * the selection. Otherwise select the first element. | |
| 388 * @param oldList Old list of user accounts. | |
| 389 * @param newList New list of user accounts. | |
| 390 * @param oldIndex Index of the selected account in the old list. | |
| 391 * @return The index of the new element, if it does not exist but lists are
the same the | |
| 392 * return the old index, otherwise return 0. | |
| 393 */ | |
| 394 private static int getIndexOfNewElement( | |
| 395 List<String> oldList, List<String> newList, int oldIndex) { | |
| 396 if (oldList == null || newList == null) return 0; | |
| 397 if (oldList.size() == newList.size() && oldList.containsAll(newList)) re
turn oldIndex; | |
| 398 if (oldList.size() + 1 == newList.size()) { | |
| 399 for (int i = 0; i < newList.size(); i++) { | |
| 400 if (!oldList.contains(newList.get(i))) return i; | |
| 401 } | |
| 402 } | |
| 403 return 0; | |
| 404 } | |
| 405 | |
| 406 @Override | |
| 407 public void onProfileDownloaded(String accountId, String fullName, String gi
venName, | |
| 408 Bitmap bitmap) { | |
| 409 updateProfileImages(); | |
| 410 } | |
| 411 | |
| 412 private void updateProfileImages() { | |
| 413 if (mProfileData == null) return; | |
| 414 | |
| 415 int count = mAccountNames.size(); | |
| 416 | |
| 417 Bitmap[] images; | |
| 418 if (count == 0) { | |
| 419 images = new Bitmap[1]; | |
| 420 images[0] = mProfileData.getImage(null); | |
| 421 } else { | |
| 422 images = new Bitmap[count]; | |
| 423 for (int i = 0; i < count; ++i) { | |
| 424 images[i] = mProfileData.getImage(mAccountNames.get(i)); | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 mImageCarousel.setImages(images); | |
| 429 updateProfileName(); | |
| 430 } | |
| 431 | |
| 432 private void updateProfileName() { | |
| 433 if (!mSignedIn) return; | |
| 434 | |
| 435 String name = null; | |
| 436 if (mProfileData != null) { | |
| 437 if (mIsChildAccount) name = mProfileData.getGivenName(mAccountName); | |
| 438 if (name == null) name = mProfileData.getFullName(mAccountName); | |
| 439 } | |
| 440 if (name == null) name = mAccountName; | |
| 441 String text = String.format(getResources().getString(R.string.fre_hi_nam
e), name); | |
| 442 mTitle.setText(text); | |
| 443 } | |
| 444 | |
| 445 /** | |
| 446 * Updates the view to show that sign in has completed. | |
| 447 */ | |
| 448 public void switchToSignedMode() { | |
| 449 showConfirmSignInPage(); | |
| 450 } | |
| 451 | |
| 452 private void showSignInPage() { | |
| 453 mSignedIn = false; | |
| 454 mTitle.setText(R.string.sign_in_to_chrome); | |
| 455 | |
| 456 mSpinner.setEnabled(true); | |
| 457 mSpinner.setBackground(mSpinnerBackground); | |
| 458 mImageCarousel.setVisibility(VISIBLE); | |
| 459 | |
| 460 setUpCancelButton(); | |
| 461 updateAccounts(); | |
| 462 | |
| 463 mImageCarousel.setSignedInMode(false); | |
| 464 } | |
| 465 | |
| 466 private void showConfirmSignInPage() { | |
| 467 mSignedIn = true; | |
| 468 updateProfileName(); | |
| 469 | |
| 470 mSpinner.setEnabled(false); | |
| 471 mSpinner.setBackground(null); | |
| 472 setUpConfirmButton(); | |
| 473 setUpUndoButton(); | |
| 474 | |
| 475 if (mShowSettingsSpan) { | |
| 476 ClickableSpan settingsSpan = new ClickableSpan() { | |
| 477 @Override | |
| 478 public void onClick(View widget) { | |
| 479 mListener.onAccountSelected(mAccountName); | |
| 480 mListener.onSettingsClicked(); | |
| 481 } | |
| 482 | |
| 483 @Override | |
| 484 public void updateDrawState(TextPaint textPaint) { | |
| 485 textPaint.setColor(textPaint.linkColor); | |
| 486 textPaint.setUnderlineText(false); | |
| 487 } | |
| 488 }; | |
| 489 mDescriptionText.setText(SpanApplier.applySpans(getSignedInDescripti
on(mIsChildAccount), | |
| 490 new SpanInfo(SETTINGS_LINK_OPEN, SETTINGS_LINK_CLOSE, settin
gsSpan))); | |
| 491 } else { | |
| 492 // If we aren't showing the span, get rid of the LINK1 annotations. | |
| 493 mDescriptionText.setText(getSignedInDescription(mIsChildAccount) | |
| 494 .replace(SETTINGS_LINK_OPEN, "") | |
| 495 .replace(SETTINGS_LINK_CLOSE, "")); | |
| 496 } | |
| 497 | |
| 498 mImageCarousel.setVisibility(VISIBLE); | |
| 499 mImageCarousel.setSignedInMode(true); | |
| 500 } | |
| 501 | |
| 502 private void setUpCancelButton() { | |
| 503 setNegativeButtonVisible(true); | |
| 504 | |
| 505 mNegativeButton.setText(getResources().getText(mCancelButtonTextId)); | |
| 506 mNegativeButton.setOnClickListener(new OnClickListener() { | |
| 507 @Override | |
| 508 public void onClick(View v) { | |
| 509 setButtonsEnabled(false); | |
| 510 mListener.onAccountSelectionCanceled(); | |
| 511 } | |
| 512 }); | |
| 513 } | |
| 514 | |
| 515 private void setUpSignInButton(boolean hasAccounts) { | |
| 516 if (hasAccounts) { | |
| 517 mPositiveButton.setText(R.string.choose_account_sign_in); | |
| 518 mPositiveButton.setOnClickListener(new OnClickListener() { | |
| 519 @Override | |
| 520 public void onClick(View v) { | |
| 521 showConfirmSignInPage(); | |
| 522 } | |
| 523 }); | |
| 524 } else { | |
| 525 mPositiveButton.setText(R.string.fre_no_accounts); | |
| 526 mPositiveButton.setOnClickListener(new OnClickListener() { | |
| 527 @Override | |
| 528 public void onClick(View v) { | |
| 529 mListener.onNewAccount(); | |
| 530 } | |
| 531 }); | |
| 532 } | |
| 533 } | |
| 534 | |
| 535 private void setUpUndoButton() { | |
| 536 setNegativeButtonVisible(!isInForcedAccountMode()); | |
| 537 if (isInForcedAccountMode()) return; | |
| 538 | |
| 539 mNegativeButton.setText(getResources().getText(R.string.undo)); | |
| 540 mNegativeButton.setOnClickListener(new OnClickListener() { | |
| 541 @Override | |
| 542 public void onClick(View v) { | |
| 543 showSignInPage(); | |
| 544 } | |
| 545 }); | |
| 546 } | |
| 547 | |
| 548 private void setUpConfirmButton() { | |
| 549 mPositiveButton.setText(getResources().getText(R.string.fre_accept)); | |
| 550 mPositiveButton.setOnClickListener(new OnClickListener() { | |
| 551 @Override | |
| 552 public void onClick(View v) { | |
| 553 mListener.onAccountSelected(mAccountName); | |
| 554 mListener.onDoneClicked(); | |
| 555 } | |
| 556 }); | |
| 557 } | |
| 558 | |
| 559 private void setNegativeButtonVisible(boolean enabled) { | |
| 560 if (enabled) { | |
| 561 mNegativeButton.setVisibility(View.VISIBLE); | |
| 562 findViewById(R.id.positive_button_end_padding).setVisibility(View.GO
NE); | |
| 563 } else { | |
| 564 mNegativeButton.setVisibility(View.GONE); | |
| 565 findViewById(R.id.positive_button_end_padding).setVisibility(View.IN
VISIBLE); | |
| 566 } | |
| 567 } | |
| 568 | |
| 569 private String getSignedInDescription(boolean childAccount) { | |
| 570 if (childAccount) { | |
| 571 return getResources().getString(R.string.fre_signed_in_description)
+ '\n' | |
| 572 + getResources().getString(R.string.fre_signed_in_descriptio
n_uca_addendum); | |
| 573 } else { | |
| 574 return getResources().getString(R.string.fre_signed_in_description); | |
| 575 } | |
| 576 } | |
| 577 | |
| 578 /** | |
| 579 * @param isChildAccount Whether this view is for a child account. | |
| 580 */ | |
| 581 public void setIsChildAccount(boolean isChildAccount) { | |
| 582 mIsChildAccount = isChildAccount; | |
| 583 } | |
| 584 | |
| 585 /** | |
| 586 * Switches the view to "no choice, just a confirmation" forced-account mode
. | |
| 587 * @param forcedAccountName An account that should be force-selected. | |
| 588 */ | |
| 589 public void switchToForcedAccountMode(String forcedAccountName) { | |
| 590 mForcedAccountName = forcedAccountName; | |
| 591 updateAccounts(); | |
| 592 assert TextUtils.equals(mAccountName, mForcedAccountName); | |
| 593 switchToSignedMode(); | |
| 594 assert TextUtils.equals(mAccountName, mForcedAccountName); | |
| 595 } | |
| 596 | |
| 597 /** | |
| 598 * @return Whether the view is in signed in mode. | |
| 599 */ | |
| 600 public boolean isSignedIn() { | |
| 601 return mSignedIn; | |
| 602 } | |
| 603 | |
| 604 /** | |
| 605 * @return Whether the view is in "no choice, just a confirmation" forced-ac
count mode. | |
| 606 */ | |
| 607 public boolean isInForcedAccountMode() { | |
| 608 return mForcedAccountName != null; | |
| 609 } | |
| 610 | |
| 611 @Override | |
| 612 public void onPositionChanged(int i) { | |
| 613 mPositionSetProgrammatically = true; | |
| 614 mSpinner.setSelection(i); | |
| 615 } | |
| 616 } | |
| OLD | NEW |