diff --git a/demo/src/main/java/moe/feng/common/stepperview/demo/fragment/VerticalStepperAdapterDemoFragment.java b/demo/src/main/java/moe/feng/common/stepperview/demo/fragment/VerticalStepperAdapterDemoFragment.java index 7e7cbc2..5ed6da6 100644 --- a/demo/src/main/java/moe/feng/common/stepperview/demo/fragment/VerticalStepperAdapterDemoFragment.java +++ b/demo/src/main/java/moe/feng/common/stepperview/demo/fragment/VerticalStepperAdapterDemoFragment.java @@ -2,6 +2,8 @@ import android.content.Context; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.view.LayoutInflater; @@ -26,16 +28,16 @@ public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle saved @Override public void onViewCreated(View view, Bundle savedInstanceState) { mVerticalStepperView = view.findViewById(R.id.vertical_stepper_view); - mVerticalStepperView.setViewAdapter(this); + mVerticalStepperView.setStepperAdapter(this); } @Override - public String getTitle(int index) { + public @NonNull String getTitle(int index) { return "Step " + index; } @Override - public String getSummary(int index) { + public @Nullable String getSummary(int index) { switch (index) { case 0: return "Summarized if needed"; diff --git a/library/src/main/java/moe/feng/common/stepperview/IStepperAdapter.java b/library/src/main/java/moe/feng/common/stepperview/IStepperAdapter.java index c688bb1..74a4a9e 100644 --- a/library/src/main/java/moe/feng/common/stepperview/IStepperAdapter.java +++ b/library/src/main/java/moe/feng/common/stepperview/IStepperAdapter.java @@ -1,21 +1,71 @@ package moe.feng.common.stepperview; import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.view.View; import android.view.ViewGroup; +/** + * Base interface providing the adapter to populate steps inside of + * a {@link IStepperAdapter}. You have to implement this and create your + * own adapter to configure steps. + * + * Or you can use a more specific implementation of this, such as + * {@link ViewBasedStepperAdapter}. + */ public interface IStepperAdapter { - String getTitle(int index); + /** + * This method will be called by the VerticalStepperView to obtain a title string + * to describe the title of specified step. The string cannot be null. + * + * @param index The index of the title requested + * @return A title for the requested step + */ + @NonNull String getTitle(int index); - String getSummary(int index); + /** + * This method may be called by the VerticalStepperView to obtain a title string + * to describe the summary of specified step. It may return null indicating + * no summary for this step. + * + * @param index The index of the summary requested + * @return A summary for the requested step + */ + @Nullable String getSummary(int index); + /** + * Get the count of steppers + * + * @return The size of adapter + */ int size(); + /** + * When the specified step need a custom view, this method will be called + * for creating custom view. If you want to add it to ItemView by yourself, + * it can return null. The returned view will be added to ItemView. + * + * @param index Index + * @param context Context + * @param parent Vertical Stepper Item View + * @return The custom view created + */ View onCreateCustomView(int index, Context context, VerticalStepperItemView parent); + /** + * This method will be called when a stepper is showed. + * + * @param index The index of stepper showed + */ void onShow(int index); + /** + * This method will be called when a stepper is hidden. + * + * @param index The index of stepper hidden + */ void onHide(int index); } diff --git a/library/src/main/java/moe/feng/common/stepperview/IStepperView.java b/library/src/main/java/moe/feng/common/stepperview/IStepperView.java index 31f8b65..d313e97 100644 --- a/library/src/main/java/moe/feng/common/stepperview/IStepperView.java +++ b/library/src/main/java/moe/feng/common/stepperview/IStepperView.java @@ -3,14 +3,55 @@ import android.graphics.drawable.Drawable; import android.support.annotation.ColorInt; +/** + * Base interface providing a view base of stepper component. + * You have to implement this and create your own stepper view. + * + * We have made some stepper view: + * - {@link VerticalStepperView} + */ interface IStepperView { - IStepperAdapter getViewAdapter(); + /** + * Get stepper adapter + * + * @return Stepper Adapter + */ + IStepperAdapter getStepperAdapter(); + + /** + * Return the index of current step + * + * @return Index + */ int getCurrentStep(); + /** + * Get normal point color + * + * @return Normal Point Color + */ @ColorInt int getNormalColor(); + + /** + * Get activated point color + * + * @return Activated Point Color + */ @ColorInt int getActivatedColor(); + + /** + * Get animation duration + * + * @return Animation Duration + */ int getAnimationDuration(); + + /** + * Get done icon drawable + * + * @return Done icon drawable + */ Drawable getDoneIcon(); } diff --git a/library/src/main/java/moe/feng/common/stepperview/VerticalStepperItemView.java b/library/src/main/java/moe/feng/common/stepperview/VerticalStepperItemView.java index 8f83296..c20afc7 100644 --- a/library/src/main/java/moe/feng/common/stepperview/VerticalStepperItemView.java +++ b/library/src/main/java/moe/feng/common/stepperview/VerticalStepperItemView.java @@ -25,6 +25,9 @@ public class VerticalStepperItemView extends FrameLayout { + /** + * Internal Views + */ private View mPointBackground, mLineView; private TextView mPointNumber; private TextView mTitleText, mSummaryText; @@ -33,16 +36,25 @@ public class VerticalStepperItemView extends FrameLayout { private ImageView mDoneIconView; private View mMarginBottomView; + /** + * Step state + */ private String mTitle, mSummary; private int mIndex = 1; private boolean isLastStep = false; private int mState = STATE_NORMAL; + /** + * View attributes + */ private int mAnimationDuration; private int mNormalColor, mActivatedColor; private Drawable mDoneIcon; private boolean mAnimationEnabled = true; + /** + * The bind views + */ private @Nullable VerticalStepperItemView mPrevItemView, mNextItemView; public static final int STATE_NORMAL = 0, STATE_SELECTED = 1, STATE_DONE = 2; @@ -110,6 +122,9 @@ FrameLayout getCustomView() { return mCustomView; } + /** + * Remove custom view manually + */ public void removeCustomView() { mCustomView.removeAllViews(); } @@ -148,6 +163,11 @@ private void updateMarginBottom() { mMarginBottomView.getLayoutParams().height = (!isLastStep ? (mState != STATE_SELECTED ? 28 : 36) : 0) * DP; } + /** + * Set up the state of this stepper item + * + * @param state The state of this stepper item + */ public void setState(@State int state) { // Change point background if (state != STATE_NORMAL && mState == STATE_NORMAL) { @@ -185,56 +205,117 @@ public void setState(@State int state) { updateMarginBottom(); } + /** + * Get the state of this stepper item + * + * @return The state of this stepper item + */ public @State int getState() { return mState; } + /** + * Set title for this step + * + * @param title The title should be set + */ public void setTitle(String title) { mTitle = title; mTitleText.setText(title); } + /** + * Set title for this step + * + * @param titleRes The title resource should be set + */ public void setTitle(@StringRes int titleRes) { setTitle(getResources().getString(titleRes)); } + /** + * Get the title of this step + * + * @return The title of this step + */ public String getTitle() { return mTitle; } - public void setSummary(String summary) { + /** + * Set summary for this step. + * If you set a null value, it will hide the summary view. + * + * @param summary The summary should be set or null + */ + public void setSummary(@Nullable String summary) { mSummary = summary; mSummaryText.setText(summary); mSummaryText.setVisibility(mState != STATE_SELECTED && !TextUtils.isEmpty(mSummary) ? View.VISIBLE : View.GONE); } + /** + * Set summary for this step. + * + * @param summaryRes The summary resource should be set + */ public void setSummary(@StringRes int summaryRes) { setSummary(getResources().getString(summaryRes)); } + /** + * Get the summary of this step + * + * @return The summary of this step + */ public String getSummary() { return mSummary; } + /** + * Set index for this step + * + * @param index Index + */ public void setIndex(int index) { mIndex = index; mPointNumber.setText(String.valueOf(index)); } + /** + * Get the index of this step + * + * @return The index of this step + */ public int getIndex() { return mIndex; } + /** + * Set if it is last step + * + * @param isLastStep If it is last step + */ public void setIsLastStep(boolean isLastStep) { this.isLastStep = isLastStep; mLineView.setVisibility(isLastStep ? View.INVISIBLE : View.VISIBLE); updateMarginBottom(); } + /** + * Return if it is last step + * + * @return If it is last step + */ public boolean isLastStep() { return isLastStep; } + /** + * Set if animation should be enabled + * + * @param shouldAnimate If animation should be enabled + */ public void setAnimationEnabled(boolean shouldAnimate) { mAnimationEnabled = shouldAnimate; if (shouldAnimate) { @@ -244,31 +325,67 @@ public void setAnimationEnabled(boolean shouldAnimate) { } } + /** + * Get if animation is enabled + * + * @return If animation is enabled + */ public boolean isAnimationEnabled() { return mAnimationEnabled; } + /** + * Set done icon drawable + * + * @param drawable Done icon drawable + */ public void setDoneIcon(Drawable drawable) { mDoneIcon = drawable; mDoneIconView.setImageDrawable(drawable); } + /** + * Set done icon drawable resource + * + * @param drawableRes Done icon drawable resource + */ public void setDoneIconResource(@DrawableRes int drawableRes) { setDoneIcon(getResources().getDrawable(drawableRes)); } + /** + * Get done icon drawable + * + * @return Done icon drawable + */ public Drawable getDoneIcon() { return mDoneIcon; } + /** + * Set animation duration + * + * @param duration Animation Duration + */ public void setAnimationDuration(int duration) { mAnimationDuration = duration; } + /** + * Get animation duration + * + * @return Animation Duration + */ public int getAnimationDuration() { return mAnimationDuration; } + /** + * Bind two stepper items for automatically setting state with nextStep() or prevStep() + * + * @param prevItem The previous item + * @param nextItem The next item + */ public void bindSteppers(@Nullable VerticalStepperItemView prevItem, @Nullable VerticalStepperItemView nextItem) { if (prevItem != null) { mPrevItemView = prevItem; @@ -284,6 +401,11 @@ public void bindSteppers(@Nullable VerticalStepperItemView prevItem, @Nullable V } } + /** + * Bind stepper items for automatically setting state with nextStep() or prevStep() + * + * @param items Stepper items + */ public static void bindSteppers(@NonNull VerticalStepperItemView... items) { for (int i = 0; i < items.length - 1; i++) { if (i != 0) { @@ -293,10 +415,20 @@ public static void bindSteppers(@NonNull VerticalStepperItemView... items) { } } + /** + * Return if stepper can go previous + * + * @return If stepper can go previous + */ public boolean canPrevStep() { return mPrevItemView != null; } + /** + * Go previous step + * + * @return If success + */ public boolean prevStep() { if (canPrevStep()) { setState(STATE_NORMAL); @@ -306,10 +438,20 @@ public boolean prevStep() { return false; } + /** + * Return if stepper can go next + * + * @return If stepper can go next + */ public boolean canNextStep() { return mNextItemView != null; } + /** + * Go next step + * + * @return If success + */ public boolean nextStep() { if (canNextStep()) { setState(STATE_DONE); @@ -319,6 +461,11 @@ public boolean nextStep() { return false; } + /** + * Set normal point color + * + * @param color Normal Point Color + */ public void setNormalColor(@ColorInt int color) { mNormalColor = color; if (mState == STATE_NORMAL) { @@ -326,14 +473,29 @@ public void setNormalColor(@ColorInt int color) { } } + /** + * Set normal point color + * + * @param colorRes Normal Point Color resource + */ public void setNormalColorResource(@ColorRes int colorRes) { setNormalColor(getResources().getColor(colorRes)); } + /** + * Get normal point color + * + * @return Normal Point Color + */ public @ColorInt int getNormalColor() { return mNormalColor; } + /** + * Set activated point color + * + * @param color Activated Point Color + */ public void setActivatedColor(@ColorInt int color) { mActivatedColor = color; if (mState != STATE_NORMAL) { @@ -341,10 +503,20 @@ public void setActivatedColor(@ColorInt int color) { } } + /** + * Set activated point color + * + * @param colorRes Activated Point Color resource + */ public void setActivatedColorResource(@ColorRes int colorRes) { setActivatedColor(getResources().getColor(colorRes)); } + /** + * Get activated point color + * + * @return Activated Point Color + */ public @ColorInt int getActivatedColor() { return mActivatedColor; } diff --git a/library/src/main/java/moe/feng/common/stepperview/VerticalStepperView.java b/library/src/main/java/moe/feng/common/stepperview/VerticalStepperView.java index 9e8d759..916e585 100644 --- a/library/src/main/java/moe/feng/common/stepperview/VerticalStepperView.java +++ b/library/src/main/java/moe/feng/common/stepperview/VerticalStepperView.java @@ -3,6 +3,8 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; +import android.support.annotation.ColorInt; +import android.support.annotation.ColorRes; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; @@ -13,13 +15,22 @@ public class VerticalStepperView extends FrameLayout implements IStepperView { + /** + * Internal view / adapter + */ private RecyclerView mListView; private ItemAdapter mAdapter; + /** + * View State + */ private IStepperAdapter mViewAdapter; private int mCurrentStep = 0; - private boolean mAnimationEnabled; + /** + * View attributes + */ + private boolean mAnimationEnabled; private int mAnimationDuration; private int mNormalColor, mActivatedColor; private Drawable mDoneIcon; @@ -75,26 +86,53 @@ private void prepareListView(Context context) { addView(mListView, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); } - public void setViewAdapter(IStepperAdapter viewAdapter) { - mViewAdapter = viewAdapter; + /** + * Set up the stepper adapter + * + * @param stepperAdapter Stepper Adapter + */ + public void setStepperAdapter(IStepperAdapter stepperAdapter) { + mViewAdapter = stepperAdapter; mAdapter.notifyDataSetChanged(); } + /** + * Return the count of steps + * + * @return The count of steps + */ public int getStepCount() { return mViewAdapter != null ? mViewAdapter.size() : 0; } + /** + * Return if stepper can go next + * + * @return If stepper can go next + */ public boolean canNext() { return mViewAdapter != null && mCurrentStep < mViewAdapter.size() - 1; } + /** + * Return if stepper can go previous + * + * @return If stepper can go previous + */ public boolean canPrev() { return mViewAdapter != null && mCurrentStep > 0; } + /** + * Go next step + * + * @return If success + */ public boolean nextStep() { if (canNext()) { + mViewAdapter.onHide(mCurrentStep); mCurrentStep++; + mViewAdapter.onShow(mCurrentStep); if (mAnimationEnabled) { mAdapter.notifyItemRangeChanged(mCurrentStep - 1, 2); } else { @@ -105,9 +143,16 @@ public boolean nextStep() { return false; } + /** + * Go previous step + * + * @return If success + */ public boolean prevStep() { if (canPrev()) { + mViewAdapter.onHide(mCurrentStep); mCurrentStep--; + mViewAdapter.onShow(mCurrentStep); if (mAnimationEnabled) { mAdapter.notifyItemRangeChanged(mCurrentStep, 2); } else { @@ -118,44 +163,127 @@ public boolean prevStep() { return false; } + /** + * Get Stepper Adapter + * + * @return Stepper Adapter + */ @Override - public IStepperAdapter getViewAdapter() { + public IStepperAdapter getStepperAdapter() { return mViewAdapter; } + /** + * Get the index of current step + * + * @return The index of current step + */ @Override public int getCurrentStep() { return mCurrentStep; } + /** + * Set normal point color + * + * @param color Normal Point Color + */ + public void setNormalColor(@ColorInt int color) { + mNormalColor = color; + mAdapter.notifyDataSetChanged(); + } + + /** + * Set normal point color + * + * @param colorRes Normal Point Color resource + */ + public void setNormalColorResource(@ColorRes int colorRes) { + setNormalColor(getResources().getColor(colorRes)); + } + + /** + * Get normal point color + * + * @return Normal Point Color + */ @Override public int getNormalColor() { return mNormalColor; } + /** + * Set activated point color + * + * @param color Activated Point Color + */ + public void setActivatedColor(@ColorInt int color) { + mActivatedColor = color; + mAdapter.notifyDataSetChanged(); + } + + /** + * Set activated point color + * + * @param colorRes Activated Point Color resource + */ + public void setActivatedColorResource(@ColorRes int colorRes) { + setActivatedColor(getResources().getColor(colorRes)); + } + + /** + * Get activated point color + * + * @return Activated Point Color + */ @Override public int getActivatedColor() { return mActivatedColor; } + /** + * Get animation duration + * + * @return Animation duration + */ @Override public int getAnimationDuration() { return mAnimationDuration; } + /** + * Get done icon drawable + * + * @return Done Icon Drawable + */ @Override public Drawable getDoneIcon() { return mDoneIcon; } + /** + * Set if animation should be enabled + * + * @param enabled If animation should be enabled + */ public void setAnimationEnabled(boolean enabled) { mAnimationEnabled = enabled; } + /** + * Return if animation is enabled + * + * @return If animation is enabled + */ public boolean isAnimationEnabled() { return mAnimationEnabled; } + /** + * Set the current step by index + * + * @param currentStep The index of current step + */ public void setCurrentStep(int currentStep) { int minIndex = Math.min(currentStep, mCurrentStep); int count = Math.abs(mCurrentStep - currentStep) + 1; @@ -168,6 +296,9 @@ public void setCurrentStep(int currentStep) { } } + /** + * Internal RecyclerView Adapter to show item views + */ class ItemAdapter extends RecyclerView.Adapter { @Override @@ -179,8 +310,8 @@ public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) { public void onBindViewHolder(ItemHolder holder, int position) { holder.mItemView.setIndex(position + 1); holder.mItemView.setIsLastStep(position == getItemCount() - 1); - holder.mItemView.setTitle(getViewAdapter().getTitle(position)); - holder.mItemView.setSummary(getViewAdapter().getSummary(position)); + holder.mItemView.setTitle(getStepperAdapter().getTitle(position)); + holder.mItemView.setSummary(getStepperAdapter().getSummary(position)); holder.mItemView.setNormalColor(mNormalColor); holder.mItemView.setActivatedColor(mActivatedColor); holder.mItemView.setAnimationDuration(mAnimationDuration); @@ -194,7 +325,7 @@ public void onBindViewHolder(ItemHolder holder, int position) { holder.mItemView.setState(VerticalStepperItemView.STATE_SELECTED); } holder.mItemView.removeCustomView(); - View customView = getViewAdapter().onCreateCustomView(position, getContext(), holder.mItemView); + View customView = getStepperAdapter().onCreateCustomView(position, getContext(), holder.mItemView); if (customView != null) { holder.mItemView.addView(customView); }