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