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 |