1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.example.android.leanback; 18 19 import android.app.Activity; 20 import android.app.Fragment; 21 import android.app.FragmentManager; 22 import android.content.Context; 23 import android.content.res.Configuration; 24 import android.graphics.drawable.Drawable; 25 import android.os.Bundle; 26 import android.text.InputType; 27 import android.text.TextUtils; 28 import android.util.Log; 29 import android.view.LayoutInflater; 30 import android.view.View; 31 import android.view.ViewGroup; 32 import android.view.inputmethod.EditorInfo; 33 34 import androidx.core.content.res.ResourcesCompat; 35 import androidx.leanback.app.GuidedStepFragment; 36 import androidx.leanback.widget.GuidanceStylist; 37 import androidx.leanback.widget.GuidanceStylist.Guidance; 38 import androidx.leanback.widget.GuidedAction; 39 import androidx.leanback.widget.GuidedActionsStylist; 40 import androidx.leanback.widget.GuidedDatePickerAction; 41 42 import org.jspecify.annotations.NonNull; 43 import org.jspecify.annotations.Nullable; 44 45 import java.util.ArrayList; 46 import java.util.Calendar; 47 import java.util.List; 48 49 /** 50 * Activity that showcases different aspects of GuidedStepFragments. 51 */ 52 public class GuidedStepActivity extends Activity { 53 54 private static final int BACK = 2; 55 56 private static final int FIRST_NAME = 3; 57 private static final int LAST_NAME = 4; 58 private static final int PASSWORD = 5; 59 private static final int PAYMENT = 6; 60 private static final int NEW_PAYMENT = 7; 61 private static final int PAYMENT_EXPIRE = 8; 62 private static final int REFRESH = 9; 63 64 private static final long RADIO_ID_BASE = 0; 65 private static final long CHECKBOX_ID_BASE = 100; 66 67 private static final long DEFAULT_OPTION = RADIO_ID_BASE; 68 69 private static final String[] OPTION_NAMES = { "Option A", "Option B", "Option C" }; 70 private static final String[] OPTION_DESCRIPTIONS = { "Here's one thing you can do", 71 "Here's another thing you can do", "Here's one more thing you can do" }; 72 73 private static final String TAG = GuidedStepActivity.class.getSimpleName(); 74 75 @Override onCreate(@ullable Bundle savedInstanceState)76 protected void onCreate(@Nullable Bundle savedInstanceState) { 77 Log.v(TAG, "onCreate"); 78 super.onCreate(savedInstanceState); 79 setContentView(R.layout.guided_step_activity); 80 if (savedInstanceState == null) { 81 GuidedStepFragment.addAsRoot(this, new FirstStepFragment(), 82 R.id.lb_guidedstep_host); 83 } 84 } 85 86 @Override onConfigurationChanged(@ullable Configuration newConfig)87 public void onConfigurationChanged(@Nullable Configuration newConfig) { 88 Log.v(TAG, "onConfigurationChanged"); 89 super.onConfigurationChanged(newConfig); 90 } 91 92 @Override onSaveInstanceState(@ullable Bundle outState)93 protected void onSaveInstanceState(@Nullable Bundle outState) { 94 Log.v(TAG, "onSaveInstanceState"); 95 super.onSaveInstanceState(outState); 96 } 97 98 @Override onRestoreInstanceState(@ullable Bundle savedInstanceState)99 protected void onRestoreInstanceState(@Nullable Bundle savedInstanceState) { 100 Log.v(TAG, "onRestoreInstanceState"); 101 super.onRestoreInstanceState(savedInstanceState); 102 } 103 addAction(List<GuidedAction> actions, long id, String title, String desc)104 private static GuidedAction addAction(List<GuidedAction> actions, long id, String title, 105 String desc) { 106 GuidedAction action; 107 actions.add(action = new GuidedAction.Builder(null) 108 .id(id) 109 .title(title) 110 .description(desc) 111 .build()); 112 return action; 113 } 114 addAction(List<GuidedAction> actions, long id, String title, String desc, List<GuidedAction> subActions)115 private static GuidedAction addAction(List<GuidedAction> actions, long id, String title, 116 String desc, List<GuidedAction> subActions) { 117 GuidedAction action; 118 actions.add(action = new GuidedAction.Builder(null) 119 .id(id) 120 .title(title) 121 .description(desc) 122 .subActions(subActions) 123 .build()); 124 return action; 125 } 126 addEditableAction(Context context, List<GuidedAction> actions, long id, String title, String desc)127 private static GuidedAction addEditableAction(Context context, List<GuidedAction> actions, 128 long id, String title, String desc) { 129 GuidedAction action; 130 actions.add(action = new GuidedAction.Builder(context) 131 .id(id) 132 .title(title) 133 .description(desc) 134 .editable(true) 135 .icon(androidx.leanback.R.drawable.lb_ic_search_mic) 136 .build()); 137 return action; 138 } 139 addEditableAction(List<GuidedAction> actions, long id, String title, String editTitle, int editInputType, String desc, String editDesc)140 private static GuidedAction addEditableAction(List<GuidedAction> actions, long id, String title, 141 String editTitle, int editInputType, String desc, String editDesc) { 142 GuidedAction action; 143 actions.add(action = new GuidedAction.Builder(null) 144 .id(id) 145 .title(title) 146 .editTitle(editTitle) 147 .editInputType(editInputType) 148 .description(desc) 149 .editDescription(editDesc) 150 .editable(true) 151 .build()); 152 return action; 153 } 154 addDatePickerAction(List<GuidedAction> actions, long id, String title)155 private static GuidedDatePickerAction addDatePickerAction(List<GuidedAction> actions, long id, 156 String title) { 157 GuidedDatePickerAction action; 158 actions.add(action = new GuidedDatePickerAction.Builder(null) 159 .id(id) 160 .title(title) 161 .datePickerFormat("MY") 162 .build()); 163 return action; 164 } 165 addEditableDescriptionAction(List<GuidedAction> actions, long id, String title, String desc, String editDescription, int descriptionEditInputType)166 private static GuidedAction addEditableDescriptionAction(List<GuidedAction> actions, long id, 167 String title, String desc, String editDescription, int descriptionEditInputType) { 168 GuidedAction action; 169 actions.add(action = new GuidedAction.Builder(null) 170 .id(id) 171 .title(title) 172 .description(desc) 173 .editDescription(editDescription) 174 .descriptionEditInputType(descriptionEditInputType) 175 .descriptionEditable(true) 176 .build()); 177 return action; 178 } 179 addCheckedAction(List<GuidedAction> actions, long id, String title, String desc, int checkSetId)180 private static GuidedAction addCheckedAction(List<GuidedAction> actions, long id, 181 String title, String desc, int checkSetId) { 182 GuidedAction action; 183 actions.add(action = new GuidedAction.Builder(null) 184 .id(id) 185 .title(title) 186 .description(desc) 187 .checkSetId(checkSetId) 188 .build()); 189 return action; 190 } 191 192 public static class FirstStepFragment extends GuidedStepFragment { 193 194 @Override onProvideTheme()195 public int onProvideTheme() { 196 return R.style.Theme_Example_Leanback_GuidedStep_First; 197 } 198 199 @Override onCreateGuidance(@ullable Bundle savedInstanceState)200 public @NonNull Guidance onCreateGuidance(@Nullable Bundle savedInstanceState) { 201 String title = getString(R.string.guidedstep_first_title); 202 String breadcrumb = getString(R.string.guidedstep_first_breadcrumb); 203 String description = getString(R.string.guidedstep_first_description); 204 final Context context = getActivity(); 205 Drawable icon = ResourcesCompat.getDrawable(context.getResources(), 206 R.drawable.ic_main_icon, context.getTheme()); 207 return new Guidance(title, description, breadcrumb, icon); 208 } 209 210 @Override onCreateActions(@onNull List<GuidedAction> actions, @Nullable Bundle savedInstanceState)211 public void onCreateActions(@NonNull List<GuidedAction> actions, 212 @Nullable Bundle savedInstanceState) { 213 Context context = getActivity(); 214 actions.add(new GuidedAction.Builder(context) 215 .clickAction(GuidedAction.ACTION_ID_CONTINUE) 216 .description("Let's do it") 217 .build()); 218 actions.add(new GuidedAction.Builder(context) 219 .id(REFRESH) 220 .title("Refresh") 221 .build()); 222 actions.add(new GuidedAction.Builder(context) 223 .clickAction(GuidedAction.ACTION_ID_CANCEL) 224 .description("Never mind") 225 .build()); 226 } 227 228 @Override onGuidedActionClicked(@onNull GuidedAction action)229 public void onGuidedActionClicked(@NonNull GuidedAction action) { 230 FragmentManager fm = getFragmentManager(); 231 if (action.getId() == GuidedAction.ACTION_ID_CONTINUE) { 232 GuidedStepFragment.add(fm, new SecondStepFragment(), R.id.lb_guidedstep_host); 233 } else if (action.getId() == REFRESH) { 234 // swap actions position and change content: 235 Context context = getActivity(); 236 ArrayList<GuidedAction> newActions = new ArrayList(); 237 newActions.add(new GuidedAction.Builder(context) 238 .id(REFRESH) 239 .title("Refresh done") 240 .build()); 241 newActions.add(new GuidedAction.Builder(context) 242 .clickAction(GuidedAction.ACTION_ID_CONTINUE) 243 .description("Let's do it") 244 .build()); 245 newActions.add(new GuidedAction.Builder(context) 246 .clickAction(GuidedAction.ACTION_ID_CANCEL) 247 .description("Never mind") 248 .build()); 249 setActions(newActions); 250 } else if (action.getId() == GuidedAction.ACTION_ID_CANCEL){ 251 finishGuidedStepFragments(); 252 } 253 } 254 } 255 256 public interface NewPaymentFragmentTarget { onNewPaymentFragmentStarted()257 void onNewPaymentFragmentStarted(); onNewPaymentAdded(int selection)258 void onNewPaymentAdded(int selection); 259 } 260 261 static ArrayList<String> sCards = new ArrayList<String>(); 262 static int sSelectedCard = -1; 263 static { 264 sCards.add("Visa-1234"); 265 sCards.add("AmEx-4321"); 266 } 267 268 public static class NewPaymentStepFragment extends GuidedStepFragment { 269 270 NewPaymentFragmentTarget mNewPaymentTarget; 271 272 @Override onCreate(@ullable Bundle savedInstance)273 public void onCreate(@Nullable Bundle savedInstance) { 274 super.onCreate(savedInstance); 275 Fragment targetFragment = getTargetFragment(); 276 if (targetFragment instanceof NewPaymentFragmentTarget) { 277 mNewPaymentTarget = ((NewPaymentFragmentTarget) targetFragment); 278 mNewPaymentTarget.onNewPaymentFragmentStarted(); 279 } 280 } 281 282 @Override onCreateGuidance(@ullable Bundle savedInstanceState)283 public @NonNull Guidance onCreateGuidance(@Nullable Bundle savedInstanceState) { 284 String title = getString(R.string.guidedstep_newpayment_title); 285 String breadcrumb = getString(R.string.guidedstep_newpayment_breadcrumb); 286 String description = getString(R.string.guidedstep_newpayment_description); 287 final Context context = getActivity(); 288 Drawable icon = ResourcesCompat.getDrawable(context.getResources(), 289 R.drawable.ic_main_icon, context.getTheme()); 290 return new Guidance(title, description, breadcrumb, icon); 291 } 292 293 @Override onCreateActions(@onNull List<GuidedAction> actions, @Nullable Bundle savedInstanceState)294 public void onCreateActions(@NonNull List<GuidedAction> actions, 295 @Nullable Bundle savedInstanceState) { 296 addEditableAction(actions, NEW_PAYMENT, "Input credit card number", "", 297 InputType.TYPE_CLASS_NUMBER, 298 "Input credit card number", "Input credit card number"); 299 addDatePickerAction(actions, PAYMENT_EXPIRE, "Exp:"); 300 } 301 302 @Override onCreateButtonActions(@onNull List<GuidedAction> actions, @Nullable Bundle savedInstanceState)303 public void onCreateButtonActions(@NonNull List<GuidedAction> actions, 304 @Nullable Bundle savedInstanceState) { 305 Context context = getActivity(); 306 actions.add(new GuidedAction.Builder(context).clickAction(GuidedAction.ACTION_ID_OK) 307 .build()); 308 actions.get(actions.size() - 1).setEnabled(false); 309 } 310 311 @Override onGuidedActionClicked(@onNull GuidedAction action)312 public void onGuidedActionClicked(@NonNull GuidedAction action) { 313 if (action.getId() == GuidedAction.ACTION_ID_OK) { 314 CharSequence desc = findActionById(NEW_PAYMENT).getDescription(); 315 String cardNumber = desc.subSequence(desc.length() - 4, desc.length()).toString(); 316 String card; 317 if ((Integer.parseInt(cardNumber) & 1) == 0) { 318 card = "Visa "+cardNumber; 319 } else { 320 card = "AmEx "+cardNumber; 321 } 322 int selection = sCards.size(); 323 sCards.add(card); 324 if (mNewPaymentTarget != null) { 325 mNewPaymentTarget.onNewPaymentAdded(selection); 326 } 327 popBackStackToGuidedStepFragment(NewPaymentStepFragment.class, 328 FragmentManager.POP_BACK_STACK_INCLUSIVE); 329 } 330 } 331 332 @Override onGuidedActionEditedAndProceed(@onNull GuidedAction action)333 public long onGuidedActionEditedAndProceed(@NonNull GuidedAction action) { 334 if (action.getId() == NEW_PAYMENT) { 335 CharSequence editTitle = action.getEditTitle(); 336 if (isCardNumberValid(editTitle)) { 337 editTitle = editTitle.subSequence(editTitle.length() - 4, editTitle.length()); 338 action.setDescription("Visa XXXX-XXXX-XXXX-" + editTitle); 339 updateOkButton(isExpDateValid(findActionById(PAYMENT_EXPIRE))); 340 return GuidedAction.ACTION_ID_NEXT; 341 } else if (editTitle.length() == 0) { 342 action.setDescription("Input credit card number"); 343 updateOkButton(false); 344 return GuidedAction.ACTION_ID_CURRENT; 345 } else { 346 action.setDescription("Error credit card number"); 347 updateOkButton(false); 348 return GuidedAction.ACTION_ID_CURRENT; 349 } 350 } else if (action.getId() == PAYMENT_EXPIRE) { 351 updateOkButton(isExpDateValid(action) && 352 isCardNumberValid(findActionById(NEW_PAYMENT).getEditTitle())); 353 } 354 return GuidedAction.ACTION_ID_NEXT; 355 } 356 isCardNumberValid(CharSequence number)357 boolean isCardNumberValid(CharSequence number) { 358 return TextUtils.isDigitsOnly(number) && number.length() == 16; 359 } 360 isExpDateValid(GuidedAction action)361 boolean isExpDateValid(GuidedAction action) { 362 long date = ((GuidedDatePickerAction) action).getDate(); 363 Calendar c = Calendar.getInstance(); 364 c.setTimeInMillis(date); 365 return Calendar.getInstance().before(c); 366 } 367 updateOkButton(boolean enabled)368 void updateOkButton(boolean enabled) { 369 findButtonActionById(GuidedAction.ACTION_ID_OK).setEnabled(enabled); 370 notifyButtonActionChanged(findButtonActionPositionById(GuidedAction.ACTION_ID_OK)); 371 } 372 } 373 374 public static class SecondStepFragment extends GuidedStepFragment 375 implements NewPaymentFragmentTarget { 376 377 378 boolean mExpandPaymentListInOnCreateView; 379 380 @Override onNewPaymentAdded(int selection)381 public void onNewPaymentAdded(int selection) { 382 // if a new payment is added, we don't need expand the sub actions list. 383 mExpandPaymentListInOnCreateView = false; 384 sSelectedCard = selection; 385 updatePaymentAction(findActionById(PAYMENT)); 386 findButtonActionById(GuidedAction.ACTION_ID_CONTINUE).setEnabled(sSelectedCard != -1); 387 } 388 389 @Override onNewPaymentFragmentStarted()390 public void onNewPaymentFragmentStarted() { 391 // if a new payment fragment is opened, when come back we should expand the payment 392 // sub actions list unless user created a new payment in onNewPaymentAdded 393 mExpandPaymentListInOnCreateView = true; 394 } 395 396 @Override onCreateActionsStylist()397 public @NonNull GuidedActionsStylist onCreateActionsStylist() { 398 return new GuidedActionsStylist() { 399 @Override 400 protected void setupImeOptions(GuidedActionsStylist.ViewHolder vh, 401 GuidedAction action) { 402 if (action.getId() == PASSWORD) { 403 vh.getEditableDescriptionView().setImeActionLabel("Confirm!", 404 EditorInfo.IME_ACTION_DONE); 405 } else { 406 super.setupImeOptions(vh, action); 407 } 408 } 409 }; 410 } 411 412 @Override 413 public @NonNull Guidance onCreateGuidance(@Nullable Bundle savedInstanceState) { 414 String title = getString(R.string.guidedstep_second_title); 415 String breadcrumb = getString(R.string.guidedstep_second_breadcrumb); 416 String description = getString(R.string.guidedstep_second_description); 417 final Context context = getActivity(); 418 Drawable icon = ResourcesCompat.getDrawable(context.getResources(), 419 R.drawable.ic_main_icon, context.getTheme()); 420 return new Guidance(title, description, breadcrumb, icon); 421 } 422 423 @Override 424 public void onCreateActions(@NonNull List<GuidedAction> actions, 425 @Nullable Bundle savedInstanceState) { 426 addEditableAction(getActivity(), actions, FIRST_NAME, "Pat", "Your first name"); 427 addEditableAction(getActivity(), actions, LAST_NAME, "Smith", "Your last name"); 428 List<GuidedAction> subActions = new ArrayList<GuidedAction>(); 429 updatePaymentAction(addAction(actions, PAYMENT, "Select Payment", "", subActions)); 430 addEditableDescriptionAction(actions, PASSWORD, "Password", "", "", 431 InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD); 432 } 433 434 @Override 435 public void onCreateButtonActions(@NonNull List<GuidedAction> actions, 436 @Nullable Bundle savedInstanceState) { 437 actions.add(new GuidedAction.Builder(getActivity()) 438 .clickAction(GuidedAction.ACTION_ID_CONTINUE) 439 .description("Continue") 440 .enabled(isPasswordValid() && isPaymentValid()) 441 .build()); 442 } 443 444 @Override 445 public void onGuidedActionClicked(@NonNull GuidedAction action) { 446 if (action.getId() == GuidedAction.ACTION_ID_CONTINUE) { 447 FragmentManager fm = getFragmentManager(); 448 GuidedStepFragment.add(fm, new ThirdStepFragment(), R.id.lb_guidedstep_host); 449 } 450 } 451 452 void updatePaymentAction(GuidedAction paymentAction) { 453 List<GuidedAction> subActions = paymentAction.getSubActions(); 454 subActions.clear(); 455 for (int i = 0; i < sCards.size(); i++) { 456 addCheckedAction(subActions, -1, sCards.get(i), "", 457 GuidedAction.DEFAULT_CHECK_SET_ID); 458 if (i == sSelectedCard) { 459 subActions.get(i).setChecked(true); 460 } 461 } 462 addAction(subActions, NEW_PAYMENT, "Add New Card", ""); 463 paymentAction.setDescription(sSelectedCard == -1 ? "" : sCards.get(sSelectedCard)); 464 } 465 466 @Override 467 public long onGuidedActionEditedAndProceed(@NonNull GuidedAction action) { 468 if (action.getId() == PASSWORD) { 469 CharSequence password = action.getEditDescription(); 470 if (password.length() > 0) { 471 if (isPaymentValid()) { 472 updateContinue(true); 473 return GuidedAction.ACTION_ID_NEXT; 474 } else { 475 updateContinue(false); 476 return GuidedAction.ACTION_ID_CURRENT; 477 } 478 } else { 479 updateContinue(false); 480 return GuidedAction.ACTION_ID_CURRENT; 481 } 482 } 483 return GuidedAction.ACTION_ID_NEXT; 484 } 485 486 @Override 487 public boolean onSubGuidedActionClicked(@NonNull GuidedAction action) { 488 if (action.isChecked()) { 489 String payment = action.getTitle().toString(); 490 for (int i = 0; i < sCards.size(); i++) { 491 if (payment.equals(sCards.get(i))) { 492 sSelectedCard = i; 493 findActionById(PAYMENT).setDescription(payment); 494 notifyActionChanged(findActionPositionById(PAYMENT)); 495 updateContinue(isPasswordValid()); 496 break; 497 } 498 } 499 return true; 500 } else { 501 FragmentManager fm = getFragmentManager(); 502 NewPaymentStepFragment newPaymentFragment = new NewPaymentStepFragment(); 503 newPaymentFragment.setTargetFragment(this, 0); 504 GuidedStepFragment.add(fm, newPaymentFragment, R.id.lb_guidedstep_host); 505 return false; 506 } 507 } 508 509 @Override 510 public @Nullable View onCreateView(@NonNull LayoutInflater inflater, 511 @NonNull ViewGroup container, @Nullable Bundle savedInstanceState) { 512 View view = super.onCreateView(inflater, container, savedInstanceState); 513 if (mExpandPaymentListInOnCreateView) { 514 expandAction(findActionById(PAYMENT), false); 515 } 516 return view; 517 } 518 519 boolean isPaymentValid() { 520 CharSequence paymentType = findActionById(PAYMENT).getDescription(); 521 return (paymentType.length() >= 4 && 522 paymentType.subSequence(0, 4).toString().equals("Visa")) || 523 (paymentType.length() >= 4 && 524 paymentType.subSequence(0, 4).toString().equals("AmEx")); 525 } 526 527 boolean isPasswordValid() { 528 return findActionById(PASSWORD).getEditDescription().length() > 0; 529 } 530 531 void updateContinue(boolean enabled) { 532 findButtonActionById(GuidedAction.ACTION_ID_CONTINUE).setEnabled(enabled); 533 notifyButtonActionChanged(findButtonActionPositionById( 534 GuidedAction.ACTION_ID_CONTINUE)); 535 } 536 } 537 538 public static class ThirdStepFragment extends GuidedStepFragment { 539 540 private long mSelectedOption = DEFAULT_OPTION; 541 542 @Override 543 public @NonNull Guidance onCreateGuidance(@Nullable Bundle savedInstanceState) { 544 String title = getString(R.string.guidedstep_third_title); 545 String breadcrumb = getString(R.string.guidedstep_third_breadcrumb); 546 String description = getString(R.string.guidedstep_third_description); 547 final Context context = getActivity(); 548 Drawable icon = ResourcesCompat.getDrawable(context.getResources(), 549 R.drawable.ic_main_icon, context.getTheme()); 550 return new Guidance(title, description, breadcrumb, icon); 551 } 552 553 @Override 554 public @NonNull GuidanceStylist onCreateGuidanceStylist() { 555 return new GuidanceStylist() { 556 @Override 557 public int onProvideLayoutId() { 558 return R.layout.guidedstep_second_guidance; 559 } 560 }; 561 } 562 563 @Override 564 public void onCreateActions(@NonNull List<GuidedAction> actions, 565 @Nullable Bundle savedInstanceState) { 566 String desc = "The description can be quite long as well. " 567 + "Just be sure to set multilineDescription to true in the GuidedAction." 568 + "For testing purpose we make this line even longer since " 569 + "multilineDescriptionMinLines will be set to 2."; 570 actions.add(new GuidedAction.Builder(getActivity()) 571 .title("Note that Guided Actions can have titles that are quite long.") 572 .description(desc) 573 .multilineDescription(true) 574 .infoOnly(true) 575 .enabled(true) 576 .focusable(false) 577 .build()); 578 for (int i = 0; i < OPTION_NAMES.length; i++) { 579 addCheckedAction(actions, RADIO_ID_BASE + i, OPTION_NAMES[i], 580 OPTION_DESCRIPTIONS[i], GuidedAction.DEFAULT_CHECK_SET_ID); 581 if (i == DEFAULT_OPTION) { 582 actions.get(actions.size() -1).setChecked(true); 583 } 584 } 585 for (int i = 0; i < OPTION_NAMES.length; i++) { 586 addCheckedAction(actions, CHECKBOX_ID_BASE + i, OPTION_NAMES[i], 587 OPTION_DESCRIPTIONS[i], GuidedAction.CHECKBOX_CHECK_SET_ID); 588 } 589 } 590 591 @Override 592 public void onCreateButtonActions(@NonNull List<GuidedAction> actions, 593 @Nullable Bundle savedInstanceState) { 594 actions.add(new GuidedAction.Builder(getActivity()) 595 .clickAction(GuidedAction.ACTION_ID_CONTINUE) 596 .build()); 597 } 598 599 @Override 600 public void onGuidedActionClicked(@NonNull GuidedAction action) { 601 if (action.getId() == GuidedAction.ACTION_ID_CONTINUE) { 602 FragmentManager fm = getFragmentManager(); 603 FourthStepFragment f = new FourthStepFragment(); 604 Bundle arguments = new Bundle(); 605 arguments.putLong(FourthStepFragment.EXTRA_OPTION, mSelectedOption); 606 f.setArguments(arguments); 607 GuidedStepFragment.add(fm, f, R.id.lb_guidedstep_host); 608 } else if (action.getCheckSetId() == GuidedAction.DEFAULT_CHECK_SET_ID) { 609 mSelectedOption = action.getId(); 610 } 611 } 612 613 } 614 615 public static class FourthStepFragment extends GuidedStepFragment { 616 public static final String EXTRA_OPTION = "extra_option"; 617 618 public FourthStepFragment() { 619 } 620 621 public long getOption() { 622 Bundle b = getArguments(); 623 if (b == null) return 0; 624 return b.getLong(EXTRA_OPTION, 0); 625 } 626 627 @Override 628 public @NonNull Guidance onCreateGuidance(@Nullable Bundle savedInstanceState) { 629 String title = getString(R.string.guidedstep_fourth_title); 630 String breadcrumb = getString(R.string.guidedstep_fourth_breadcrumb); 631 String description = "You chose: " + OPTION_NAMES[(int) getOption()]; 632 final Context context = getActivity(); 633 Drawable icon = ResourcesCompat.getDrawable(context.getResources(), 634 R.drawable.ic_main_icon, context.getTheme()); 635 return new Guidance(title, description, breadcrumb, icon); 636 } 637 638 @Override 639 public void onCreateActions(@NonNull List<GuidedAction> actions, 640 @Nullable Bundle savedInstanceState) { 641 actions.add(new GuidedAction.Builder(getActivity()) 642 .clickAction(GuidedAction.ACTION_ID_FINISH) 643 .description("All Done...") 644 .build()); 645 addAction(actions, BACK, "Start Over", "Let's try this again..."); 646 } 647 648 @Override 649 public void onGuidedActionClicked(@NonNull GuidedAction action) { 650 if (action.getId() == GuidedAction.ACTION_ID_FINISH) { 651 finishGuidedStepFragments(); 652 } else if (action.getId() == BACK) { 653 // pop 4, 3, 2 654 popBackStackToGuidedStepFragment(SecondStepFragment.class, 655 FragmentManager.POP_BACK_STACK_INCLUSIVE); 656 } 657 } 658 659 } 660 661 } 662