Skip to content

Commit 2bd332c

Browse files
committed
Added error support
1 parent b2664f5 commit 2bd332c

File tree

12 files changed

+130
-3
lines changed

12 files changed

+130
-3
lines changed

material-stepper/src/main/java/com/stepstone/stepper/StepperLayout.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
import com.stepstone.stepper.internal.TabsContainer;
4848
import com.stepstone.stepper.type.AbstractStepperType;
4949
import com.stepstone.stepper.type.StepperTypeFactory;
50+
import com.stepstone.stepper.type.TabsStepperType;
5051
import com.stepstone.stepper.util.AnimationUtil;
5152
import com.stepstone.stepper.util.TintUtil;
5253

@@ -204,6 +205,8 @@ public final void goToPrevStep() {
204205

205206
private int mCurrentStepPosition;
206207

208+
private boolean mShowErrorStateOnBack;
209+
207210
@NonNull
208211
private StepperListener mListener = StepperListener.NULL;
209212

@@ -325,6 +328,14 @@ public void setCompleteButtonVerificationFailed(boolean verificationFailed) {
325328
mCompleteNavigationButton.setVerificationFailed(verificationFailed);
326329
}
327330

331+
/**
332+
* Set whether when going backwards should clear the error state from the Tab. Default is false
333+
* @param mShowErrorStateOnBack
334+
*/
335+
public void setShowErrorStateOnBack(boolean mShowErrorStateOnBack) {
336+
this.mShowErrorStateOnBack = mShowErrorStateOnBack;
337+
}
338+
328339
private void init(AttributeSet attrs, @AttrRes int defStyleAttr) {
329340
initDefaultValues();
330341
extractValuesFromAttributes(attrs, defStyleAttr);
@@ -455,6 +466,8 @@ private void extractValuesFromAttributes(AttributeSet attrs, @AttrRes int defSty
455466
mTypeIdentifier = a.getInt(R.styleable.StepperLayout_ms_stepperType, DEFAULT_TAB_DIVIDER_WIDTH);
456467
}
457468

469+
mShowErrorStateOnBack = a.getBoolean(R.styleable.StepperLayout_ms_showErrorStateOnBack, false);
470+
458471
a.recycle();
459472
}
460473
}
@@ -496,6 +509,11 @@ private void onNext() {
496509
if (verifyCurrentStep(step)) {
497510
return;
498511
}
512+
513+
//if moving forward and got no errors, set hasError to false, so we can have the tab with the check mark.
514+
if(mStepperType instanceof TabsStepperType)
515+
mTabsContainer.setErrorStep(mCurrentStepPosition, false);
516+
499517
OnNextClickedCallback onNextClickedCallback = new OnNextClickedCallback();
500518
if (step instanceof BlockingStep) {
501519
((BlockingStep) step).onNextClicked(onNextClickedCallback);
@@ -517,6 +535,11 @@ private void onError(@NonNull VerificationError verificationError) {
517535
Step step = findCurrentStep();
518536
if (step != null) {
519537
step.onError(verificationError);
538+
539+
//if moving forward and got errors, set hasError to true, showing the error drawable.
540+
if(mStepperType instanceof TabsStepperType)
541+
mTabsContainer.setErrorStep(mCurrentStepPosition, true);
542+
520543
}
521544
mListener.onError(verificationError);
522545
}
@@ -546,6 +569,11 @@ private void onUpdate(int newStepPosition, boolean animate) {
546569
}
547570
}
548571

572+
//needs to be here in case user for any reason decide to change whether or not to show errors when going back.
573+
if(mStepperType instanceof TabsStepperType) {
574+
mTabsContainer.setShowErrorStateOnBack(mShowErrorStateOnBack);
575+
}
576+
549577
mStepperType.onStepSelected(newStepPosition);
550578
mListener.onStepSelected(newStepPosition);
551579
Step step = mStepAdapter.findStep(mPager, newStepPosition);

material-stepper/src/main/java/com/stepstone/stepper/internal/StepTab.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,12 @@ public class StepTab extends RelativeLayout {
5656

5757
private final ImageView mStepDoneIndicator;
5858

59+
private final ImageView mStepErrorIndicator;
60+
5961
private int mDividerWidth = StepperLayout.DEFAULT_TAB_DIVIDER_WIDTH;
6062

63+
private boolean hasError;
64+
6165
public StepTab(Context context) {
6266
this(context, null);
6367
}
@@ -75,6 +79,7 @@ public StepTab(Context context, AttributeSet attrs, int defStyleAttr) {
7579

7680
mStepNumber = (TextView) findViewById(R.id.ms_stepNumber);
7781
mStepDoneIndicator = (ImageView) findViewById(R.id.ms_stepDoneIndicator);
82+
mStepErrorIndicator = (ImageView) findViewById(R.id.ms_stepErrorIndicator);
7883
mStepDivider = findViewById(R.id.ms_stepDivider);
7984
mStepTitle = ((TextView) findViewById(R.id.ms_stepTitle));
8085
}
@@ -92,15 +97,36 @@ public void toggleDividerVisibility(boolean show) {
9297
* @param done true if the step is done and the step's number should be replaced with a <i>done</i> icon, false otherwise
9398
* @param current true if the step is the current step, false otherwise
9499
*/
95-
public void updateState(final boolean done, final boolean current) {
100+
public void updateState(final boolean done, final boolean showErrorOnBack, final boolean current) {
101+
//if this tab has errors and the user decide not to clear when going backwards, simply ignore the update
102+
if(this.hasError && showErrorOnBack)
103+
return;
104+
96105
mStepDoneIndicator.setVisibility(done ? View.VISIBLE : View.GONE);
97106
mStepNumber.setVisibility(!done ? View.VISIBLE : View.GONE);
107+
mStepErrorIndicator.setVisibility(GONE);
98108
colorViewBackground(done ? mStepDoneIndicator : mStepNumber, done || current);
99109

110+
this.hasError = false;
111+
100112
mStepTitle.setTypeface(current ? Typeface.DEFAULT_BOLD : Typeface.DEFAULT);
101113
mStepTitle.setAlpha(done || current ? OPAQUE_ALPHA : INACTIVE_STEP_TITLE_ALPHA);
102114
}
103115

116+
/**
117+
* Update the error state of this tab. If it has error, show the error drawable.
118+
* @param hasError whether the tab has errors or not.
119+
*/
120+
public void updateErrorState(boolean hasError) {
121+
if(hasError) {
122+
mStepDoneIndicator.setVisibility(View.GONE);
123+
mStepNumber.setVisibility(View.GONE);
124+
mStepErrorIndicator.setVisibility(VISIBLE);
125+
}
126+
127+
this.hasError = hasError;
128+
}
129+
104130
/**
105131
* Sets the name of the step
106132
* @param title step name

material-stepper/src/main/java/com/stepstone/stepper/internal/TabsContainer.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ public void onTabClicked(int position) {
7979

8080
private List<Integer> mStepTitles;
8181

82+
private boolean mShowErrorStateOnBack;
83+
8284
public TabsContainer(Context context) {
8385
this(context, null);
8486
}
@@ -152,13 +154,29 @@ public void setCurrentStep(int newStepPosition) {
152154
StepTab childTab = (StepTab) mTabsInnerContainer.getChildAt(i);
153155
boolean done = i < newStepPosition;
154156
final boolean current = i == newStepPosition;
155-
childTab.updateState(done, current);
157+
childTab.updateState(done, mShowErrorStateOnBack, current);
156158
if (current) {
157159
mTabsScrollView.smoothScrollTo(childTab.getLeft() - mContainerLateralPadding, 0);
158160
}
159161
}
160162
}
161163

164+
/**
165+
* Set whether when going backwards should clear the error state from the Tab. Default is false
166+
* @param mShowErrorStateOnBack
167+
*/
168+
public void setShowErrorStateOnBack(boolean mShowErrorStateOnBack) {
169+
this.mShowErrorStateOnBack = mShowErrorStateOnBack;
170+
}
171+
172+
public void setErrorStep(int stepPosition, boolean hasError){
173+
if(mStepTitles.size() < stepPosition)
174+
return;
175+
176+
StepTab childTab = (StepTab) mTabsInnerContainer.getChildAt(stepPosition);
177+
childTab.updateErrorState(hasError);
178+
}
179+
162180
private View createStepTab(final int position, @StringRes int title) {
163181
StepTab view = (StepTab) LayoutInflater.from(getContext()).inflate(R.layout.ms_step_tab_container, mTabsInnerContainer, false);
164182
view.setStepNumber(String.valueOf(position + 1));
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24.0"
5+
android:viewportHeight="24.0">
6+
<path
7+
android:fillColor="#FF000000"
8+
android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>
9+
</vector>

material-stepper/src/main/res/layout/ms_step_tab.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@
2727
app:srcCompat="@drawable/ic_check"
2828
android:visibility="gone" />
2929

30+
<android.support.v7.widget.AppCompatImageView
31+
android:id="@+id/ms_stepErrorIndicator"
32+
android:layout_width="@dimen/ms_step_tab_counter_size"
33+
android:layout_height="@dimen/ms_step_tab_counter_size"
34+
android:scaleType="centerInside"
35+
app:srcCompat="@drawable/ic_warning"
36+
android:tint="@color/ms_errorColor"
37+
android:visibility="gone" />
38+
3039
</FrameLayout>
3140

3241
<TextView

material-stepper/src/main/res/values/attrs.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ limitations under the License.
4949

5050
<!-- Flag indicating if the Back (Previous step) button should be shown on the first step. False by default. -->
5151
<attr name="ms_showBackButtonOnFirstStep" format="boolean" />
52+
53+
<!-- Flag indicating wheter to keep showing the error state when user moves back. Only available with 'tabs' type. False by default. -->
54+
<attr name="ms_showErrorStateOnBack" format="boolean" />
5255

5356
<!-- REQUIRED: Type of the stepper-->
5457
<attr name="ms_stepperType">

sample/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
<activity android:name=".StyledProgressBarActivity" />
2525
<activity android:name=".DefaultTabsActivity" />
2626
<activity android:name=".StyledTabsActivity" />
27+
<activity android:name=".ShowErrorOnBackTabActivity"/>
2728
<activity android:name=".CombinationActivity" />
2829
<activity android:name=".CustomPageTransformerActivity" />
2930
<activity android:name=".DelayedTransitionStepperActivity" />

sample/src/main/java/com/stepstone/stepper/sample/AbstractStepperActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public abstract class AbstractStepperActivity extends AppCompatActivity implemen
3131

3232
private static final String CURRENT_STEP_POSITION_KEY = "position";
3333

34-
StepperLayout mStepperLayout;
34+
protected StepperLayout mStepperLayout;
3535

3636
@Override
3737
protected void onCreate(Bundle savedInstanceState) {

sample/src/main/java/com/stepstone/stepper/sample/MainActivity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ public void onStyledTabs(View view) {
6868
startActivity(new Intent(this, StyledTabsActivity.class));
6969
}
7070

71+
@OnClick(R.id.errorOnBackTabs)
72+
public void onErrorOnBackTabs(View view) {
73+
startActivity(new Intent(this, ShowErrorOnBackTabActivity.class));
74+
}
75+
7176
@OnClick(R.id.combination)
7277
public void onCombination(View view) {
7378
startActivity(new Intent(this, CombinationActivity.class));
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.stepstone.stepper.sample;
2+
3+
import android.os.Bundle;
4+
5+
/**
6+
* Created by leonardo on 10/01/17.
7+
*/
8+
9+
public class ShowErrorOnBackTabActivity extends AbstractStepperActivity {
10+
11+
@Override
12+
protected void onCreate(Bundle savedInstanceState) {
13+
super.onCreate(savedInstanceState);
14+
mStepperLayout.setShowErrorStateOnBack(true);
15+
}
16+
17+
@Override
18+
protected int getLayoutResId() {
19+
return R.layout.activity_default_tabs;
20+
}
21+
}

0 commit comments

Comments
 (0)