Create Flow

The default create screen is extremely customizable allowing you to swap assets, colors, and some functionality. If that’s not enough you can create your own. The goal of the create screen is to modify a PendingVoucher and then send it forward in the flow.

Step 1: Extend BaseVoucherCreationFragment

The create screen must extend the BaseVoucherCreationFragment which does much of the heavy lifting when interacting with the rest of the create flow. It requires that you implement one method. onPendingVoucherChanged is called whenever there’s changes to the PendingVoucher. Generally PersonalizationOptions are used to change the voucher, when that happens this method will be called.

public class SimpleCreateFragment extends BaseVoucherCreationFragment {

    @Override
    public void onPendingVoucherChanged(PendingVoucher pendingVoucher) {

    }
}
class SimpleCreateFragment : BaseVoucherCreationFragment() {

    override fun onPendingVoucherChanged(pendingVoucher: PendingVoucher) {

    }
}

Protected Methods

The fragment has access to the following methods:

// Allows quick access of the create configuration and all it's settings.
CreateConfiguration getCreateConfig()

// The current pending voucher being modified
PendingVoucher getPendingVoucher()

// Used to navigate forward in the create flow and/or preview the gift.
CreateScreenContract.Navigator getNavigator() 

// Returns the current set of PersonalizationOptions that are to be used to add/remove/modify elements in a PendingVoucher.
public List<PersonalizationOption> getPersonalizationOptions() 
// Allows quick access of the create configuration and all it's settings.
fun getCreateConfig() : CreateConfiguration

// The current pending voucher being modified
fun getPendingVoucher() : PendingVoucher

// Used to navigate forward in the create flow and/or preview the gift.
fun getNavigator() : CreateScreenContract.Navigator

// Returns the current set of PersonalizationOptions that are to be used to add/remove/modify elements in a PendingVoucher.
fun getPersonalizationOptions() : List<PersonalizationOption> 

Using the Navigator

When you want to move forward in the flow:

getNavigator().moveToLoading(getActivity(), getPendingVoucher());
navigator.moveToLoading(activity, pendingVoucher)

If you want to preview the gift:

getNavigator().previewGift(getActivity(), getPendingVoucher());
navigator.previewGift(activity, pendingVoucher)

Using the PersonalizationOptions

To edit the PendingVoucher generally you use the Personalization Options which you can grab by calling getPersonalizationOptions()

Add or modify

option.addOrModifyItem(@Nullable Long mediaId) will launch the add flow for that personalization. If you are modifying a personalization where multiple are possible (eg. Images) then you must pass in a mediaId to identify the item you want to modify.

Remove

option.removeItem(@Nullable Long mediaId) will remove that personalization. If there are multiple of that type (eg. images) then you must pass in a mediaId to identify the item that you want to remove.

Simple Example

Here is a simple example of buttons that each will launch the PersonalizationOptions in order to add the personalization.

// Display all the options
for (final PersonalizationOption option : getPersonalizationOptions()) {
    VouchrButton button = new VouchrButton(getContext());
    button.setText(option.getTitle());
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            option.addOrModifyItem(null);
        }
    });
    ViewGroup.MarginLayoutParams params = new ViewGroup.MarginLayoutParams(MATCH_PARENT, WRAP_CONTENT);
    params.setMargins(Util.dpToPixel(8), Util.dpToPixel(8), Util.dpToPixel(8), Util.dpToPixel(8));
    optionsLayout.addView(button, params);
}
for (option in getPersonalizationOptions()) {
    val button = VouchrButton(context)
    button.setText(option.title)
    button.setOnClickListener {
        option.addOrModifyItem(null)
    }
    val params = ViewGroup.MarginLayoutParams(MATCH_PARENT, WRAP_CONTENT)
    params.setMargins(Util.dpToPixel(8), Util.dpToPixel(8), Util.dpToPixel(8), Util.dpToPixel(8))
    optionsLayout.addView(button, params)
}

Full Example

SimpleCreateFragment.java

public class SimpleCreateFragment extends BaseVoucherCreationFragment {

    private VouchrButton nextButton;
    private VouchrButton previewButton;
    private LinearLayout optionsLayout;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.simple_voucher_create, container, false);
        nextButton = view.findViewById(R.id.nextButton);
        previewButton = view.findViewById(R.id.previewButton);
        optionsLayout = view.findViewById(R.id.optionsLayout);
        return view;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // The next button will move forward in the flow
        nextButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getNavigator().moveToLoading(getActivity(), getPendingVoucher());
            }
        });

        // The preview button will launch the preview screen 
        // to show what the voucher will look like for the claimer.
        previewButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getNavigator().previewGift(getActivity(), getPendingVoucher());
            }
        });

        // Display all the options
        for (final PersonalizationOption option : getPersonalizationOptions()) {
            VouchrButton button = new VouchrButton(getContext());
            button.setText(option.getTitle());
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    option.addOrModifyItem(null);
                }
            });
            ViewGroup.MarginLayoutParams params =
                    new ViewGroup.MarginLayoutParams(MATCH_PARENT, WRAP_CONTENT);
            int margin = Util.dpToPixel(8);
            params.setMargins(margin, margin, margin, margin);
            optionsLayout.addView(button, params);
        }

    }

    @Override
    public void onPendingVoucherChanged(PendingVoucher pendingVoucher) {
    }

}
class SimpleCreateFragment : BaseVoucherCreationFragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.simple_voucher_create, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // The next button will move forward in the flow
        nextButton.setOnClickListener {
            navigator.moveToLoading(activity, pendingVoucher)
        }

        // The preview button will launch the preview screen
        // to show what the voucher will look like for the claimer.
        previewButton.setOnClickListener {
            navigator.previewGift(activity, pendingVoucher)
        }

        // Display all the options
        for (option in personalizationOptions) {
            val button = VouchrButton(context)
            button.setText(option.title)
            button.setOnClickListener { option.addOrModifyItem(null) }
            val params = ViewGroup.MarginLayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
            val margin = Util.dpToPixel(8)
            params.setMargins(margin, margin, margin, margin)
            optionsLayout.addView(button, params)
        }
    }
    override fun onPendingVoucherChanged(pendingVoucher: PendingVoucher) {
    }

}

simple_voucher_create.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/giftContentsText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:text="Gift Options"
        android:textAppearance="?TextAppearance.SecondaryHeader"
        app:layout_constraintTop_toBottomOf="@+id/previewButton"
        app:layout_constraintStart_toStartOf="parent" />

    <LinearLayout
        android:id="@+id/optionsLayout"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_margin="8dp"
        android:orientation="vertical"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/giftContentsText" />

    <com.surpriise.vouchrcommon.ui.components.VouchrButton
        android:id="@+id/nextButton"
        style="?VouchrButton.Light.Positive"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:paddingLeft="@dimen/default_margin"
        android:paddingTop="@dimen/default_half_margin"
        android:paddingRight="@dimen/default_margin"
        android:paddingBottom="@dimen/default_half_margin"
        android:text="@string/next"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <com.surpriise.vouchrcommon.ui.components.VouchrButton
        android:id="@+id/previewButton"
        style="?VouchrButton.Light.Neutral"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:paddingLeft="@dimen/default_margin"
        android:paddingTop="@dimen/default_half_margin"
        android:paddingRight="@dimen/default_margin"
        android:paddingBottom="@dimen/default_half_margin"
        android:text="@string/preview"
        app:layout_constraintEnd_toStartOf="@id/nextButton"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

Step 2: Set CreateFlowController

Setup the CreateFlowController while building the CreateConfiguration. When you setup the CreateFlowController override the createScreen function and pass in your own screen that we built in step 1.

CreateConfiguration createConfiguration = new CreateConfiguration.Builder(context)
        .setCreateFlowController(new CreateFlowController.Default() {
            @Override
            public BaseVoucherCreationFragment createScreen(PendingVoucher pv, CreateConfiguration cc) {
                return new SimpleCreateFragment();
            }
        })
        .build();

Engine.Builder engineBuilder = new Engine.Builder(VOUCHR_BASE_URL, SDK_ID);
engineBuilder.setCreateConfig(new CreateConfiguration.Builder(this).build());
engineBuilder.build().startup(this);
val createConfiguration = CreateConfiguration.Builder(context)
        .setCreateFlowController(object : CreateFlowController.Default() {
            override fun createScreen(PendingVoucher pv, CreateConfiguration cc) : BaseVoucherCreationFragment {
                return SimpleCreateFragment()
            }
        })
        .build()

val engineBuilder = Engine.Builder(VOUCHR_BASE_URL, SDK_ID)
engineBuilder.setCreateConfig(CreateConfiguration.Builder(this).build())
engineBuilder.build().startup(this)

More information on the CreateFlowController can be found in the JavaDocs here

Step 3: Launching the create flow

To start the create flow use the following IntentBuilder.

VoucherCreationActivity.IntentBuilder.init().start(this);
VoucherCreationActivity.IntentBuilder.init().start(this)

And depending on your theme you should see something like this

Create Screen