From 64cae78d53a7c0d4dc0a80bfddc03ecdee2667f7 Mon Sep 17 00:00:00 2001 From: Keyvan Amiri Date: Tue, 9 Feb 2016 11:53:03 -0800 Subject: [PATCH] SupportLeanbackShowcase: Added new credit card workflow and theme background for the wizard view Created a payment workflow consisting of a set of fragments for entering & adding new credit card information (checks in place for validity of the card number as well as expiration date). Also, changed the dropdown subaction's background colors to be consistent with the rest of guided step fragment view. Fixed the back key pressed to "not" exit the entire wizard on the last fragment (it not goes back to the payment fragment section when back button is pressed). Change-Id: I39cf316f09b765cffbd0a7e012539c49dbe238ed --- .../wizard/WizardExample1stStepFragment.java | 2 +- .../wizard/WizardExample2ndStepFragment.java | 70 +++++++-- .../app/wizard/WizardExampleActivity.java | 3 +- .../wizard/WizardNewPaymentStepFragment.java | 135 ++++++++++++++++++ .../app/src/main/res/values/colors.xml | 5 +- .../app/src/main/res/values/strings.xml | 11 +- .../app/src/main/res/values/themes.xml | 5 +- 7 files changed, 213 insertions(+), 18 deletions(-) create mode 100644 samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardNewPaymentStepFragment.java diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample1stStepFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample1stStepFragment.java index c3623d00d..cbfa86874 100644 --- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample1stStepFragment.java +++ b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample1stStepFragment.java @@ -56,7 +56,7 @@ public class WizardExample1stStepFragment extends WizardExampleBaseStepFragment .title(getString(R.string.wizard_example_rent_sd)) .editable(false) .description(mMovie.getPriceSd() + " " + - R.string.wizard_example_watch_sd) + getString(R.string.wizard_example_watch_sd)) .build(); actions.add(action); } diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample2ndStepFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample2ndStepFragment.java index 019af2f83..917bd130c 100644 --- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample2ndStepFragment.java +++ b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExample2ndStepFragment.java @@ -14,6 +14,7 @@ package android.support.v17.leanback.supportleanbackshowcase.app.wizard; +import android.app.FragmentManager; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -26,6 +27,7 @@ import android.support.v17.leanback.widget.GuidedAction; import android.support.v17.leanback.widget.GuidedActionsStylist; import android.widget.Toast; +import java.util.ArrayList; import java.util.List; /** @@ -36,6 +38,16 @@ public class WizardExample2ndStepFragment extends WizardExampleBaseStepFragment private static final String ARG_HD = "hd"; private static final int ACTION_ID_CONFIRM = 1; private static final int ACTION_ID_PAYMENT_METHOD = ACTION_ID_CONFIRM + 1; + private static final int ACTION_ID_NEW_PAYMENT = ACTION_ID_PAYMENT_METHOD + 1; + + protected static ArrayList sCards = new ArrayList<>(); + protected static int sSelectedCard = -1; + + static { + sCards.add("Visa-1234"); + sCards.add("Master-4321"); + } + public static GuidedStepFragment build(boolean hd, WizardExampleBaseStepFragment previousFragment) { GuidedStepFragment fragment = new WizardExample2ndStepFragment(); @@ -66,27 +78,67 @@ public class WizardExample2ndStepFragment extends WizardExampleBaseStepFragment .description(rentHighDefinition ? mMovie.getPriceHd() : mMovie.getPriceSd()) .editable(false) .build(); + action.setEnabled(false); actions.add(action); + List subActions = new ArrayList<>(); action = new GuidedAction.Builder(getActivity()) .id(ACTION_ID_PAYMENT_METHOD) .title(R.string.wizard_example_payment_method) .editTitle("") .description(R.string.wizard_example_input_credit) - .editable(true) + .subActions(subActions) .build(); actions.add(action); } @Override - public void onGuidedActionEdited(GuidedAction action) { - CharSequence editTitle = action.getEditTitle(); - if (TextUtils.isDigitsOnly(editTitle) && editTitle.length() == 16) { - action.setDescription(getString(R.string.wizard_example_visa, - editTitle.subSequence(editTitle.length() - 4, editTitle.length()))); - } else if (editTitle.length() == 0) { - action.setDescription(getString(R.string.wizard_example_input_credit)); + public void onResume() { + super.onResume(); + GuidedAction payment = findActionById(ACTION_ID_PAYMENT_METHOD); + + List paymentSubActions = payment.getSubActions(); + paymentSubActions.clear(); + for (int i = 0; i < sCards.size(); i++) { + paymentSubActions.add(new GuidedAction.Builder(getActivity()) + .title(sCards.get(i)) + .description("") + .checkSetId(GuidedAction.DEFAULT_CHECK_SET_ID) + .build() + ); + } + paymentSubActions.add(new GuidedAction.Builder(getActivity()) + .id(ACTION_ID_NEW_PAYMENT) + .title("Add New Card") + .description("") + .editable(false) + .build() + ); + if ( sSelectedCard >= 0 && sSelectedCard < sCards.size() ) { + payment.setDescription(sCards.get(sSelectedCard)); + findActionById(ACTION_ID_CONFIRM).setEnabled(true); + } else + findActionById(ACTION_ID_CONFIRM).setEnabled(false); + notifyActionChanged(findActionPositionById(ACTION_ID_CONFIRM)); + } + + @Override + public boolean onSubGuidedActionClicked(GuidedAction action) { + + if (action.isChecked()) { + String payment = action.getTitle().toString(); + if ( (sSelectedCard = sCards.indexOf(payment)) != -1 ) { + findActionById(ACTION_ID_PAYMENT_METHOD).setDescription(payment); + notifyActionChanged(findActionPositionById(ACTION_ID_PAYMENT_METHOD)); + findActionById(ACTION_ID_CONFIRM).setEnabled(true); + notifyActionChanged(findActionPositionById(ACTION_ID_CONFIRM)); + } + return true; } else { - action.setDescription(getString(R.string.wizard_example_input_credit_wrong)); + FragmentManager fm = getFragmentManager(); + GuidedStepFragment fragment = new WizardNewPaymentStepFragment(); + fragment.setArguments(getArguments()); + add(fm, fragment); + return false; } } diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleActivity.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleActivity.java index f5d293708..96f71f870 100644 --- a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleActivity.java +++ b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardExampleActivity.java @@ -25,7 +25,8 @@ import android.support.v17.leanback.supportleanbackshowcase.R; */ public class WizardExampleActivity extends Activity { - @Override public void onCreate(Bundle savedInstanceState) { + @Override + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().setBackgroundDrawableResource(R.drawable.wizard_background_blackned); diff --git a/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardNewPaymentStepFragment.java b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardNewPaymentStepFragment.java new file mode 100644 index 000000000..2a89b7f75 --- /dev/null +++ b/samples/SupportLeanbackShowcase/app/src/main/java/android/support/v17/leanback/supportleanbackshowcase/app/wizard/WizardNewPaymentStepFragment.java @@ -0,0 +1,135 @@ +package android.support.v17.leanback.supportleanbackshowcase.app.wizard; + +import android.app.FragmentManager; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v17.leanback.supportleanbackshowcase.R; +import android.support.v17.leanback.widget.GuidanceStylist; +import android.support.v17.leanback.widget.GuidedAction; +import android.support.v17.leanback.widget.GuidedDatePickerAction; +import android.text.TextUtils; + +import java.util.Calendar; +import java.util.List; + +/** + * Created by keyvana on 2/8/16. + */ +public class WizardNewPaymentStepFragment extends WizardExampleBaseStepFragment { + + private static final int ACTION_ID_CARD_NUMBER = 1; + private static final int ACTION_ID_PAYMENT_EXP = ACTION_ID_CARD_NUMBER + 1; + + @NonNull + @Override + public GuidanceStylist.Guidance onCreateGuidance(Bundle savedInstanceState) { + String title = getString(R.string.wizard_example_new_payment_guidance_title); + String description = getString(R.string.wizard_example_new_payment_guidance_description); + String breadcrumb = mMovie.getBreadcrump(); + + GuidanceStylist.Guidance guidance = new GuidanceStylist.Guidance(title, description, + breadcrumb, null); + return guidance; + } + + @Override + public void onCreateActions(List actions, Bundle savedInstanceState) { + actions.add(new GuidedAction.Builder(getActivity()) + .id(ACTION_ID_CARD_NUMBER) + .title(R.string.wizard_example_input_card) + .editTitle("") + .description(R.string.wizard_example_input_card) + .editDescription("Card number") + .editable(true) + .build() + ); + + actions.add(new GuidedDatePickerAction.Builder(getActivity()) + .id(ACTION_ID_PAYMENT_EXP) + .title(R.string.wizard_example_expiration_date) + .datePickerFormat("MY") + .build() + ); + } + + @Override + public void onCreateButtonActions(@NonNull List actions, + Bundle savedInstanceState) { + actions.add(new GuidedAction.Builder(getActivity()) + .clickAction(GuidedAction.ACTION_ID_OK) + .build() + ); + actions.get(actions.size() - 1).setEnabled(false); + } + + @Override + public void onGuidedActionClicked(GuidedAction action) { + if (action.getId() == GuidedAction.ACTION_ID_OK) { + CharSequence cardNumber = findActionById(ACTION_ID_CARD_NUMBER).getDescription(); + WizardExample2ndStepFragment.sSelectedCard = WizardExample2ndStepFragment.sCards.size(); + WizardExample2ndStepFragment.sCards.add(cardNumber.toString()); + popBackStackToGuidedStepFragment(WizardNewPaymentStepFragment.class, + FragmentManager.POP_BACK_STACK_INCLUSIVE); + } + } + + @Override + public long onGuidedActionEditedAndProceed(GuidedAction action) { + + boolean cardNumberCheck = false; + boolean expDateCheck = false; + + if (action.getId() == ACTION_ID_CARD_NUMBER) { + CharSequence cardNumber = action.getEditTitle(); + cardNumberCheck = isCardNumberValid(cardNumber); + expDateCheck = isExpDateValid(findActionById(ACTION_ID_PAYMENT_EXP)); + updateOkButton(cardNumberCheck && expDateCheck); + + if (cardNumberCheck) { + String last4Digits = cardNumber.subSequence(cardNumber.length() - 4, + cardNumber.length()).toString(); + + if ( (Integer.parseInt(last4Digits) & 1) == 0 ) + action.setDescription(getString(R.string.wizard_example_visa, + last4Digits)); + else + action.setDescription(getString(R.string.wizard_example_master, + last4Digits)); + + return GuidedAction.ACTION_ID_NEXT; + } else if (cardNumber.length() == 0) { + action.setDescription(getString(R.string.wizard_example_input_card)); + return GuidedAction.ACTION_ID_CURRENT; + } else { + action.setDescription(getString(R.string.wizard_example_input_credit_wrong)); + return GuidedAction.ACTION_ID_CURRENT; + } + + } else if (action.getId() == ACTION_ID_PAYMENT_EXP) { + expDateCheck = isExpDateValid(action); + cardNumberCheck = isCardNumberValid(findActionById(ACTION_ID_CARD_NUMBER) + .getEditTitle()); + updateOkButton(cardNumberCheck && expDateCheck); + if (expDateCheck) { + return GuidedAction.ACTION_ID_NEXT; + } + } + return GuidedAction.ACTION_ID_CURRENT; + } + + private void updateOkButton(boolean enabled) { + findButtonActionById(GuidedAction.ACTION_ID_OK).setEnabled(enabled); + notifyButtonActionChanged(findButtonActionPositionById(GuidedAction.ACTION_ID_OK)); + } + + private static boolean isCardNumberValid(CharSequence number) { + return (TextUtils.isDigitsOnly(number) && number.length() == 16); + } + + private static boolean isExpDateValid(GuidedAction dateAction) { + long date = ((GuidedDatePickerAction) dateAction).getDate(); + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(date); + return Calendar.getInstance().before(c); + } +} diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/values/colors.xml b/samples/SupportLeanbackShowcase/app/src/main/res/values/colors.xml index 465651555..84d9d189f 100644 --- a/samples/SupportLeanbackShowcase/app/src/main/res/values/colors.xml +++ b/samples/SupportLeanbackShowcase/app/src/main/res/values/colors.xml @@ -42,6 +42,7 @@ #0374BF #022A4E - #C03800 - #263238 + #C03800 + #C03800 + #263238 diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/values/strings.xml b/samples/SupportLeanbackShowcase/app/src/main/res/values/strings.xml index a25b964c8..66c329e05 100644 --- a/samples/SupportLeanbackShowcase/app/src/main/res/values/strings.xml +++ b/samples/SupportLeanbackShowcase/app/src/main/res/values/strings.xml @@ -42,6 +42,8 @@ Watch in HD on supported devices Watch in standard definition on the web and supported devices Rental period: start within 30 days,\nfinish within 24 hours + Enter credit card number + Exp. date Payment Method \'Payment Method\' clicked. Rent @@ -51,8 +53,11 @@ Watch now Later \'Watch now\' clicked. - Input credit card number - Visa XXXX-XXXX-XXXX-%s - Error credit card number + New credit card + Enter new credit card information here + Input Payment Type + Visa-%s + Master-%s + Error: invalid credit card number sJust a second... \ No newline at end of file diff --git a/samples/SupportLeanbackShowcase/app/src/main/res/values/themes.xml b/samples/SupportLeanbackShowcase/app/src/main/res/values/themes.xml index 14f2c2025..7f951753b 100644 --- a/samples/SupportLeanbackShowcase/app/src/main/res/values/themes.xml +++ b/samples/SupportLeanbackShowcase/app/src/main/res/values/themes.xml @@ -35,7 +35,8 @@