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