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