Skip to content

Commit 48d8473

Browse files
authored
Stepper feedback + sample app main screen redesign (#91)
- Added stepper feedback - added GIFs for the stepper feedback and tab error animations - redesigned the home screen of the sample app
1 parent 11be3bf commit 48d8473

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1211
-288
lines changed

README.md

Lines changed: 79 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Quoting the [documentation](https://www.google.com/design/spec/components/steppe
1212
1313
## Download (from JCenter)
1414
```groovy
15-
compile 'com.stepstone.stepper:material-stepper:3.1.0'
15+
compile 'com.stepstone.stepper:material-stepper:3.2.0'
1616
```
1717

1818
## Supported steppers
@@ -30,6 +30,8 @@ compile 'com.stepstone.stepper:material-stepper:3.1.0'
3030
- embedding the stepper anywhere in the view hierarchy and changing the stepper type for various device configurations, e.g. phone/tablet, portrait/landscape
3131
- step validation
3232
- use with Fragments or Views
33+
- showing errors in tabs
34+
- showing stepper feedback for ongoing operations (see [Stepper feedback](https://material.io/guidelines/components/steppers.html#steppers-types-of-steppers))
3335

3436
## Getting started
3537

@@ -341,10 +343,60 @@ For an example of how to use it with views please see the sample app.
341343

342344
### Showing an error on tabs if step verification failed
343345
To show an error in the tabbed stepper if step verification fails you need to set `ms_showErrorStateEnabled` attribute to `true`.
344-
<p><img src ="./gifs/error-on-tabs.gif" width="360" height="640"/></p>
346+
<p><img src ="./gifs/error-on-tabs.gif" width="640" height="360"/></p>
345347

346348
If you want to keep the error displayed when going back to the previous step you need to also set `ms_showErrorStateOnBackEnabled` to `true`.
347349

350+
### Stepper feedback
351+
It is possible to show stepper feedback for ongoing operations (see [Stepper feedback](https://material.io/guidelines/components/steppers.html#steppers-types-of-steppers)).
352+
To do so you firstly need to set ```ms_stepperFeedbackType``` to one or more of:
353+
* ```tabs``` - shows a progress message instead of the tabs during operation,
354+
* ```content``` - shows a progress bar on top of the steps' content and partially fades the content out during operation,
355+
* ```disabled_bottom_navigation``` - disables the buttons in the bottom navigation during operation.
356+
The default is ```none``` which does nothing. It is possible to use multiple flags together.
357+
358+
After setting this to show the feedback you need to call ```StepperLayout#showProgress(@NonNull String progressMessage)```
359+
and do hide the progress indicator you need to call ```StepperLayout#hideProgress()```.
360+
361+
<p><img src ="./gifs/stepper-feedback.gif" width="640" height="360"/></p>
362+
363+
E.g.
364+
In layout:
365+
```xml
366+
<?xml version="1.0" encoding="utf-8"?>
367+
<com.stepstone.stepper.StepperLayout xmlns:android="http://schemas.android.com/apk/res/android"
368+
xmlns:app="http://schemas.android.com/apk/res-auto"
369+
android:id="@+id/stepperLayout"
370+
android:layout_width="match_parent"
371+
android:layout_height="match_parent"
372+
app:ms_stepperType="tabs"
373+
app:ms_stepperFeedbackType="tabs|content|disabled_bottom_navigation" />
374+
```
375+
376+
and in BlockingStep:
377+
378+
```java
379+
public class StepperFeedbackStepFragment extends Fragment implements BlockingStep {
380+
381+
//...
382+
383+
@Override
384+
@UiThread
385+
public void onNextClicked(final StepperLayout.OnNextClickedCallback callback) {
386+
callback.getStepperLayout().showProgress("Operation in progress, please wait...");
387+
new Handler().postDelayed(new Runnable() {
388+
@Override
389+
public void run() {
390+
callback.goToNextStep();
391+
callback.getStepperLayout().hideProgress();
392+
}
393+
}, 2000L);
394+
}
395+
396+
//...
397+
398+
```
399+
348400
### Custom styling
349401
Basic styling can be done by choosing the active and inactive step colors.
350402
There are some additional properties which can be changed directly from StepperLayout's attributes e.g. the background of bottom navigation buttons (see <a href="#stepperlayout-attributes">StepperLayout attributes</a>)
@@ -356,28 +408,29 @@ See 'Custom StepperLayout theme' in the sample app for an example.
356408
For other examples, e.g. persisting state on rotation, displaying errors, changing whether the user can go to the next step, etc. check out the sample app.
357409

358410
## StepperLayout attributes
359-
| Attribute name | Format | Description |
360-
| --------------------------------|-------------------------------------------|-------------|
361-
| *ms_stepperType* | one of `dots`, `progress_bar` or `tabs` | **REQUIRED:** Type of the stepper |
362-
| *ms_backButtonColor* | color or reference | BACK button's text color |
363-
| *ms_nextButtonColor* | color or reference | NEXT button's text color |
364-
| *ms_completeButtonColor* | color or reference | COMPLETE button's text color |
365-
| *ms_activeStepColor* | color or reference | Active step's color |
366-
| *ms_inactiveStepColor* | color or reference | Inactive step's color |
367-
| *ms_bottomNavigationBackground* | reference | Background of the bottom navigation |
368-
| *ms_backButtonBackground* | reference | BACK button's background |
369-
| *ms_nextButtonBackground* | reference | NEXT button's background |
370-
| *ms_completeButtonBackground* | reference | COMPLETE button's background |
371-
| *ms_backButtonText* | string or reference | BACK button's text |
372-
| *ms_nextButtonText* | string or reference | NEXT button's text |
373-
| *ms_completeButtonText* | string or reference | COMPLETE button's text |
374-
| *ms_tabStepDividerWidth* | dimension or reference | The width of the horizontal tab divider used in tabs stepper type |
375-
| *ms_showBackButtonOnFirstStep* | boolean | Flag indicating if the Back (Previous step) button should be shown on the first step. False by default. |
376-
| *ms_errorColor* | color or reference | Error color in Tabs stepper |
377-
| *ms_showErrorStateEnabled* | boolean | Flag indicating whether to show the error state. Only applicable for 'tabs' type. False by default. |
378-
| *ms_showErrorStateOnBackEnabled*| boolean | Flag indicating whether to keep showing the error state when user moves back. Only applicable for 'tabs' type. False by default. |
379-
| *ms_tabNavigationEnabled* | boolean | Flag indicating whether step navigation is possible by clicking on the tabs directly. Only applicable for 'tabs' type. True by default. |
380-
| *ms_stepperLayoutTheme* | reference | Theme to use for even more custom styling of the stepper layout. It is recommended that it should extend @style/MSDefaultStepperLayoutTheme, which is the default theme used. |
411+
| Attribute name | Format | Description |
412+
| --------------------------------|---------------------------------------------------------------------|-------------|
413+
| *ms_stepperType* | one of `dots`, `progress_bar` or `tabs` | **REQUIRED:** Type of the stepper |
414+
| *ms_backButtonColor* | color or reference | BACK button's text color |
415+
| *ms_nextButtonColor* | color or reference | NEXT button's text color |
416+
| *ms_completeButtonColor* | color or reference | COMPLETE button's text color |
417+
| *ms_activeStepColor* | color or reference | Active step's color |
418+
| *ms_inactiveStepColor* | color or reference | Inactive step's color |
419+
| *ms_bottomNavigationBackground* | reference | Background of the bottom navigation |
420+
| *ms_backButtonBackground* | reference | BACK button's background |
421+
| *ms_nextButtonBackground* | reference | NEXT button's background |
422+
| *ms_completeButtonBackground* | reference | COMPLETE button's background |
423+
| *ms_backButtonText* | string or reference | BACK button's text |
424+
| *ms_nextButtonText* | string or reference | NEXT button's text |
425+
| *ms_completeButtonText* | string or reference | COMPLETE button's text |
426+
| *ms_tabStepDividerWidth* | dimension or reference | The width of the horizontal tab divider used in tabs stepper type |
427+
| *ms_showBackButtonOnFirstStep* | boolean | Flag indicating if the Back (Previous step) button should be shown on the first step. False by default. |
428+
| *ms_errorColor* | color or reference | Error color in Tabs stepper |
429+
| *ms_showErrorStateEnabled* | boolean | Flag indicating whether to show the error state. Only applicable for 'tabs' type. False by default. |
430+
| *ms_showErrorStateOnBackEnabled*| boolean | Flag indicating whether to keep showing the error state when user moves back. Only applicable for 'tabs' type. False by default. |
431+
| *ms_tabNavigationEnabled* | boolean | Flag indicating whether step navigation is possible by clicking on the tabs directly. Only applicable for 'tabs' type. True by default. |
432+
| *ms_stepperFeedbackType* | flag(s): `none` or `tabs`, `content` & `disabled_bottom_navigation` | Type(s) of stepper feedback. Can be a combination of `tabs`, `content` & `disabled_bottom_navigation`. Default is `none`.|
433+
| *ms_stepperLayoutTheme* | reference | Theme to use for even more custom styling of the stepper layout. It is recommended that it should extend @style/MSDefaultStepperLayoutTheme, which is the default theme used. |
381434
382435
### StepperLayout style attributes
383436
A list of `ms_stepperLayoutTheme` attributes responsible for styling of StepperLayout's child views.
@@ -390,8 +443,10 @@ A list of `ms_stepperLayoutTheme` attributes responsible for styling of StepperL
390443
| *ms_nextNavigationButtonStyle* | Used by ms_stepNextButton in layout/ms_stepper_layout |
391444
| *ms_completeNavigationButtonStyle*| Used by ms_stepCompleteButton in layout/ms_stepper_layout |
392445
| *ms_colorableProgressBarStyle* | Used by ms_stepProgressBar in layout/ms_stepper_layout |
446+
| *ms_stepPagerProgressBarStyle* | Used by ms_stepPagerProgressBar in layout/ms_stepper_layout |
393447
| *ms_stepTabsScrollViewStyle* | Used by ms_stepTabsScrollView in layout/ms_tabs_container |
394448
| *ms_stepTabsInnerContainerStyle* | Used by ms_stepTabsInnerContainer in layout/ms_tabs_container |
449+
| *ms_stepTabsProgressMessageStyle* | Used by ms_stepTabsProgressMessage in layout/ms_tabs_container|
395450
| *ms_stepTabContainerStyle* | Used in layout/ms_step_tab_container |
396451
| *ms_stepTabNumberStyle* | Used by ms_stepNumber in layout/ms_step_tab |
397452
| *ms_stepTabDoneIndicatorStyle* | Used by ms_stepDoneIndicator in layout/ms_step_tab |

gifs/error-on-tabs.gif

-403 KB
Loading

gifs/stepper-feedback.gif

1.22 MB
Loading

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,4 @@
1919

2020
POM_GROUP_ID=com.stepstone.stepper
2121
POM_ARTIFACT_ID=material-stepper
22-
POM_VERSION=3.1.0
22+
POM_VERSION=3.2.0

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

Lines changed: 82 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@
4343
import android.widget.LinearLayout;
4444

4545
import com.stepstone.stepper.adapter.StepAdapter;
46+
import com.stepstone.stepper.internal.feedback.StepperFeedbackType;
47+
import com.stepstone.stepper.internal.feedback.StepperFeedbackTypeFactory;
4648
import com.stepstone.stepper.internal.type.AbstractStepperType;
4749
import com.stepstone.stepper.internal.type.StepperTypeFactory;
4850
import com.stepstone.stepper.internal.util.AnimationUtil;
@@ -222,10 +224,14 @@ public void goToPrevStep() {
222224

223225
private int mTypeIdentifier = AbstractStepperType.PROGRESS_BAR;
224226

227+
private int mFeedbackTypeMask = StepperFeedbackType.NONE;
228+
225229
private StepAdapter mStepAdapter;
226230

227231
private AbstractStepperType mStepperType;
228232

233+
private StepperFeedbackType mStepperFeedbackType;
234+
229235
private int mCurrentStepPosition;
230236

231237
private boolean mShowErrorStateEnabled;
@@ -234,6 +240,8 @@ public void goToPrevStep() {
234240

235241
private boolean mTabNavigationEnabled;
236242

243+
private boolean mInProgress;
244+
237245
@StyleRes
238246
private int mStepperLayoutTheme;
239247

@@ -243,7 +251,7 @@ public void goToPrevStep() {
243251
private OnClickListener mOnBackClickListener = new OnClickListener() {
244252
@Override
245253
public void onClick(View v) {
246-
onPrevious();
254+
onBackClicked();
247255
}
248256
};
249257

@@ -370,6 +378,22 @@ public void proceed() {
370378
}
371379
}
372380

381+
/**
382+
* To be called when the user wants to go to the previous step.
383+
*/
384+
public void onBackClicked() {
385+
Step step = findCurrentStep();
386+
387+
updateErrorFlagWhenGoingBack();
388+
389+
OnBackClickedCallback onBackClickedCallback = new OnBackClickedCallback();
390+
if (step instanceof BlockingStep) {
391+
((BlockingStep) step).onBackClicked(onBackClickedCallback);
392+
} else {
393+
onBackClickedCallback.goToPrevStep();
394+
}
395+
}
396+
373397
/**
374398
* Sets the current step to the one at the provided index.
375399
* This does not verify the current step.
@@ -385,6 +409,11 @@ public void setCurrentStepPosition(int currentStepPosition) {
385409
onUpdate(currentStepPosition, true);
386410
}
387411

412+
/**
413+
* Returns the position of the currently selected step.
414+
*
415+
* @return position of the currently selected step
416+
*/
388417
public int getCurrentStepPosition() {
389418
return mCurrentStepPosition;
390419
}
@@ -397,6 +426,18 @@ public void setCompleteButtonVerificationFailed(boolean verificationFailed) {
397426
mCompleteNavigationButton.setVerificationFailed(verificationFailed);
398427
}
399428

429+
public void setNextButtonEnabled(boolean enabled) {
430+
mNextNavigationButton.setEnabled(enabled);
431+
}
432+
433+
public void setCompleteButtonEnabled(boolean enabled) {
434+
mCompleteNavigationButton.setEnabled(enabled);
435+
}
436+
437+
public void setBackButtonEnabled(boolean enabled) {
438+
mBackNavigationButton.setEnabled(enabled);
439+
}
440+
400441
/**
401442
* Set whether when going backwards should clear the error state from the Tab. Default is <code>false</code>.
402443
*
@@ -496,6 +537,40 @@ public void updateErrorFlag(boolean hasError) {
496537
mStepperType.setErrorFlag(mCurrentStepPosition, hasError);
497538
}
498539

540+
/**
541+
* Shows a progress indicator. This does not have to be a progress bar and it depends on chosen stepper feedback types.
542+
* @param progressMessage optional progress message if supported by the selected types
543+
*/
544+
public void showProgress(@NonNull String progressMessage) {
545+
mInProgress = true;
546+
mStepperFeedbackType.showProgress(progressMessage);
547+
}
548+
549+
/**
550+
* Hides the progress indicator.
551+
*/
552+
public void hideProgress() {
553+
mInProgress = false;
554+
mStepperFeedbackType.hideProgress();
555+
}
556+
557+
/**
558+
* Checks if there's an ongoing operation i.e. if {@link #showProgress(String)} was called and not followed by {@link #hideProgress()} yet.
559+
* @return true if in progress, false otherwise
560+
*/
561+
public boolean isInProgress() {
562+
return mInProgress;
563+
}
564+
565+
/**
566+
* Sets the mask for the stepper feedback type.
567+
* @param feedbackTypeMask step feedback type mask, should contain one or more flags from {@link StepperFeedbackType}
568+
*/
569+
public void setFeedbackType(int feedbackTypeMask) {
570+
mFeedbackTypeMask = feedbackTypeMask;
571+
mStepperFeedbackType = StepperFeedbackTypeFactory.createType(mFeedbackTypeMask, this);
572+
}
573+
499574
@SuppressWarnings("RestrictedApi")
500575
private void init(AttributeSet attrs, @AttrRes int defStyleAttr) {
501576
initDefaultValues();
@@ -523,6 +598,7 @@ public boolean onTouch(View view, MotionEvent motionEvent) {
523598
mTabsContainer.setVisibility(GONE);
524599

525600
mStepperType = StepperTypeFactory.createType(mTypeIdentifier, this);
601+
mStepperFeedbackType = StepperFeedbackTypeFactory.createType(mFeedbackTypeMask, this);
526602
}
527603

528604
private void initNavigation() {
@@ -645,7 +721,11 @@ private void extractValuesFromAttributes(AttributeSet attrs, @AttrRes int defSty
645721
mShowErrorStateEnabled = a.getBoolean(R.styleable.StepperLayout_ms_showErrorStateEnabled, mShowErrorStateEnabled);
646722

647723
if (a.hasValue(R.styleable.StepperLayout_ms_stepperType)) {
648-
mTypeIdentifier = a.getInt(R.styleable.StepperLayout_ms_stepperType, DEFAULT_TAB_DIVIDER_WIDTH);
724+
mTypeIdentifier = a.getInt(R.styleable.StepperLayout_ms_stepperType, AbstractStepperType.PROGRESS_BAR);
725+
}
726+
727+
if (a.hasValue(R.styleable.StepperLayout_ms_stepperFeedbackType)) {
728+
mFeedbackTypeMask = a.getInt(R.styleable.StepperLayout_ms_stepperFeedbackType, StepperFeedbackType.NONE);
649729
}
650730

651731
mShowErrorStateOnBackEnabled = a.getBoolean(R.styleable.StepperLayout_ms_showErrorStateOnBack, false);
@@ -678,19 +758,6 @@ private Step findCurrentStep() {
678758
return mStepAdapter.findStep(mCurrentStepPosition);
679759
}
680760

681-
private void onPrevious() {
682-
Step step = findCurrentStep();
683-
684-
updateErrorFlagWhenGoingBack();
685-
686-
OnBackClickedCallback onBackClickedCallback = new OnBackClickedCallback();
687-
if (step instanceof BlockingStep) {
688-
((BlockingStep) step).onBackClicked(onBackClickedCallback);
689-
} else {
690-
onBackClickedCallback.goToPrevStep();
691-
}
692-
}
693-
694761
private void updateErrorFlagWhenGoingBack() {
695762
updateErrorFlag(mShowErrorStateOnBackEnabled && mStepperType.getErrorAtPosition(mCurrentStepPosition));
696763
}

0 commit comments

Comments
 (0)