package com.door43.util.wizard; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.util.Log; import java.util.ArrayList; /** * This class provides an easy to way to create a step by step wizard within a single activity. */ public abstract class WizardActivity extends ActionBarActivity implements WizardFragment.OnFragmentInteractionListener { private ArrayList<WizardFragment> mFragments = new ArrayList<>(); private int mCurrentFragmentIndex = 0; private int mContainerViewId = -1; private static final String STATE_INDEX = "fragment_index"; private StepDirection mStepDirection = StepDirection.NEXT; private boolean mHasInstanceState = false; public enum StepDirection { NEXT, PREVIOUS } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // restore state if(savedInstanceState != null) { mCurrentFragmentIndex = savedInstanceState.getInt(STATE_INDEX, -1); mHasInstanceState = true; } } @Override public void onResume() { super.onResume(); if(!mHasInstanceState) { // only load the first step when the activity starts up loadStep(); } } /** * Returns the direction in which the wizard step was made * @return */ public StepDirection getStepDirection() { return mStepDirection; } /** * Sets the container view id that will be replaced with each step * @param containerViewId The view container to be replaced e.g. R.id.wizard_content */ protected void setReplacementContainerViewId(int containerViewId) { mContainerViewId = containerViewId; } /** * Adds a fragment to the list of steps * @param fragment */ protected void addStep(WizardFragment fragment) { mFragments.add(fragment); } /** * Called when the user reaches the end of the wizard */ public abstract void onFinish(); /** * Navigates to the next step if one exists */ @Override public void onNext() { mStepDirection = StepDirection.NEXT; if(mContainerViewId == -1) { throw new IllegalArgumentException(toString() + " must call setReplacementContainerViewId before navigating between steps"); } mCurrentFragmentIndex ++; if(mCurrentFragmentIndex >= mFragments.size()) { mCurrentFragmentIndex = mFragments.size() - 1; // we are done onFinish(); } else { loadStep(); } } /** * Closes the activity */ @Override public void onCancel() { finish(); } /** * Navigates to the previous step if one exists */ @Override public void onPrevious() { mStepDirection = StepDirection.PREVIOUS; if(mContainerViewId == -1) { throw new IllegalArgumentException(toString() + " must call setReplacementContainerViewId before navigating between steps"); } if(mCurrentFragmentIndex > 0) { mCurrentFragmentIndex--; loadStep(); } } /** * Inserts the current step fragment into the layout */ protected void loadStep() { if (mCurrentFragmentIndex >= 0 && mCurrentFragmentIndex < mFragments.size()) { getFragmentManager().beginTransaction().replace(mContainerViewId, mFragments.get(mCurrentFragmentIndex)).commit(); } else { Log.w("Step", "Invalid wizard fragment index: " + mCurrentFragmentIndex); finish(); } } /** * Navigates to the next step if one exists after skipping the number of steps. * @param numSteps The number of steps to be skipped. Positive numbers will skip forward. Negative numbers will skip backwards. */ @Override public void onSkip(int numSteps) { if(numSteps < 0) { mCurrentFragmentIndex += numSteps; onPrevious(); } else { mCurrentFragmentIndex += numSteps; onNext(); } } @Override public void onSaveInstanceState(Bundle outState) { outState.putInt(STATE_INDEX, mCurrentFragmentIndex); super.onSaveInstanceState(outState); } }