{"id":13848160,"url":"https://github.com/ernestoyaquello/VerticalStepperForm","last_synced_at":"2025-07-12T11:33:40.762Z","repository":{"id":45018308,"uuid":"61065728","full_name":"ernestoyaquello/VerticalStepperForm","owner":"ernestoyaquello","description":"Vertical Stepper Form Library for Android. It follows Google Material Design guidelines.","archived":false,"fork":false,"pushed_at":"2022-01-14T00:07:36.000Z","size":5790,"stargazers_count":1052,"open_issues_count":4,"forks_count":219,"subscribers_count":38,"default_branch":"master","last_synced_at":"2024-08-09T23:01:49.027Z","etag":null,"topics":["android","form","forms","java","material-design","material-ui","vertical-stepper-forms"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ernestoyaquello.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-06-13T19:59:59.000Z","updated_at":"2024-08-07T21:44:04.000Z","dependencies_parsed_at":"2022-08-30T06:01:21.467Z","dependency_job_id":null,"html_url":"https://github.com/ernestoyaquello/VerticalStepperForm","commit_stats":null,"previous_names":["ernestoyaquello/vertical-stepper-form"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ernestoyaquello%2FVerticalStepperForm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ernestoyaquello%2FVerticalStepperForm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ernestoyaquello%2FVerticalStepperForm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ernestoyaquello%2FVerticalStepperForm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ernestoyaquello","download_url":"https://codeload.github.com/ernestoyaquello/VerticalStepperForm/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225820303,"owners_count":17529138,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","form","forms","java","material-design","material-ui","vertical-stepper-forms"],"created_at":"2024-08-04T19:00:43.929Z","updated_at":"2025-07-12T11:33:40.754Z","avatar_url":"https://github.com/ernestoyaquello.png","language":"Java","funding_links":["https://www.buymeacoffee.com/ernestoyaquello"],"categories":["Java"],"sub_categories":[],"readme":"## 🪦 RIP: This library is now archived\n\nIt was nice while it lasted, but this library has endured too much hardship already. First Kotlin, then Compose...\n\n\u003e If you must, the rest of this outdated readme continues below.\n\n---\n\n# Vertical Stepper Form Library\n\n[![issues](https://img.shields.io/github/issues/ernestoyaquello/VerticalStepperForm?style=for-the-badge)](https://github.com/ernestoyaquello/VerticalStepperForm/issues)\n[![pull requests](https://img.shields.io/github/issues-pr/ernestoyaquello/VerticalStepperForm?style=for-the-badge)](https://github.com/ernestoyaquello/VerticalStepperForm/pulls)\n[![contributors](https://img.shields.io/github/contributors/ernestoyaquello/VerticalStepperForm?style=for-the-badge)](https://github.com/ernestoyaquello/VerticalStepperForm/graphs/contributors)\n\nThis Android library implements a highly customizable **vertical stepper form**.\n\n## Demo\n\n![Demo picture](https://raw.githubusercontent.com/ernestoyaquello/VerticalStepperForm/master/stepper-example.gif)\n\n## Support This Library\n\nThe creation (and maintenance) of this library requires time and effort. If you find it useful and want to support it, please use the link below:\n\n[![Buy me a coffee!](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/ernestoyaquello)\n\n## How To Use It\n### 1. Reference The Library\n\nAdd the library to your project via `mavenCentral` by adding the following in the app's `build.gradle` file:\n\n```\ndependencies {\n    implementation 'com.ernestoyaquello.stepperform:vertical-stepper-form:2.7.0'\n}\n```\n\n\u003e Make sure you are using AndroidX instead of the old support libraries; otherwise this library might not work.\n\n### 2. Add The Form To Your Layout\n\nAdd the view `VerticalStepperFormView` to your layout using XML. For design purposes, it is recommended that you don't put anything else than this view in the layout of the screen that will contain the form:\n\n```xml\n\u003c!-- new_user_form_activity.xml --\u003e\n\u003cernestoyaquello.com.verticalstepperform.VerticalStepperFormView\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/stepper_form\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    app:form_circle_background_color=\"@color/colorPrimary\"\n    app:form_next_button_background_color=\"@color/colorPrimary\"\n    app:form_next_button_pressed_background_color=\"@color/colorPrimaryDark\"/\u003e\n```\n\nAs you can see in this example, only the properties `form_circle_background_color`, `form_next_button_background_color` and `form_next_button_pressed_background_color` are being used to configure the form, but **there are plenty of other ones that you can use to customize it as you please**.\n\n### 3. Define Your Steps\n\nEach one of the fields of your form **must be defined as a step**.\n\nTo define a step, create a class that extends `Step\u003cT\u003e`, where `T` will be the type of the step's data (e.g., `String` if the data of the step is the user's name, `Integer` if it is the user's age, etc). For instance:\n\n```java\npublic class UserNameStep extends Step\u003cString\u003e {\n\n    private EditText userNameView;\n\n    public UserNameStep(String stepTitle) {\n        super(stepTitle);\n    }\n\n    @Override\n    protected View createStepContentLayout() {\n        // Here we generate the view that will be used by the library as the content of the step.\n        // In this case we do it programmatically, but we could also do it by inflating an XML layout.\n        userNameView = new EditText(getContext());\n        userNameView.setSingleLine(true);\n        userNameView.setHint(\"Your Name\");\n        ...\n        userNameView.addTextChangedListener(new TextWatcher() {\n            ...\n            @Override\n            public void onTextChanged(CharSequence s, int start, int before, int count) {\n                // Whenever the user updates the user name text, we update the state of the step.\n                // The step will be marked as completed only if its data is valid, which will be\n                // checked automatically by the form with a call to isStepDataValid().\n                markAsCompletedOrUncompleted(true);\n            }\n        });\n\n        return userNameView;\n    }\n    \n    @Override\n    protected IsDataValid isStepDataValid(String stepData) {\n        // The step's data (i.e., the user name) will be considered valid only if it is longer than \n        // three characters. In case it is not, we will display an error message for feedback.\n        // In an optional step, you should implement this method to always return a valid value.\n        boolean isNameValid = stepData.length() \u003e= 3;\n        String errorMessage = !isNameValid ? \"3 characters minimum\" : \"\";\n\n        return new IsDataValid(isNameValid, errorMessage);\n    }\n\n    @Override\n    public String getStepData() {\n        // We get the step's data from the value that the user has typed in the EditText view.\n        Editable userName = userNameView.getText();\n        return userName != null ? userName.toString() : \"\";\n    }\n\n    @Override\n    public String getStepDataAsHumanReadableString() {\n        // Because the step's data is already a human-readable string, we don't need to convert it.\n        // However, we return \"(Empty)\" if the text is empty to avoid not having any text to display.\n        // This string will be displayed in the subtitle of the step whenever the step gets closed.\n        String userName = getStepData();        \n        return !userName.isEmpty() ? userName : \"(Empty)\";\n    }\n\n    @Override\n    protected void onStepOpened(boolean animated) {\n        // This will be called automatically whenever the step gets opened.\n    }\n\n    @Override\n    protected void onStepClosed(boolean animated) {\n        // This will be called automatically whenever the step gets closed.\n    }\n    \n    @Override\n    protected void onStepMarkedAsCompleted(boolean animated) {\n        // This will be called automatically whenever the step is marked as completed.\n    }\n\n    @Override\n    protected void onStepMarkedAsUncompleted(boolean animated) {\n        // This will be called automatically whenever the step is marked as uncompleted.\n    }\n\n    @Override\n    protected void restoreStepData(String stepData) {\n        // To restore the step after a configuration change, we restore the text of its EditText view.\n        userNameView.setText(stepData);\n    }\n}\n```\n\nMost of the methods showed above will be called automatically by the library. For example, every time the user opens a step, the callback `onStepOpened()` will be invoked and the open step will be marked as completed or uncompleted automatically depending on the value returned by `isStepDataValid()`. Then, the callback `onStepMarkedAsCompleted()`, if applicable, will also be invoked.\n\nIt is worth noting that each step has a reference to the context accessible through `getContext()` and a reference to the form accessible through `getFormView()`, as well as several other useful methods.\n\n### 4. Set Up The Form And Initialize It\n\nOnce you have defined all your steps, you will need to find the view of the form to set it up and initialize it:\n\n```java\npublic class CreateUserAccountActivity extends Activity implements StepperFormListener {\n\n    private UserNameStep userNameStep;\n    private UserEmailStep userEmailStep;\n    private UserAgeStep userAgeStep;\n    \n    private VerticalStepperFormView verticalStepperForm;\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.new_user_form_activity);\n\n        // Create the steps.\n        userNameStep = new UserNameStep(\"User Name\");\n        userEmailStep = new UserEmailStep(\"User Email\");\n        userAgeStep = new UserAgeStep(\"User Age\");\n\n        // Find the form view, set it up and initialize it.\n        verticalStepperForm = findViewById(R.id.stepper_form);\n        verticalStepperForm\n            .setup(this, userNameStep, userEmailStep, userAgeStep)\n            .init();\n    }\n\n    @Override\n    public void onCompletedForm() {\n        // This method will be called when the user clicks on the last confirmation button of the \n        // form in an attempt to save or send the data.\n    }\n\n    @Override\n    public void onCancelledForm() {\n        // This method will be called when the user clicks on the cancel button of the form.\n    }\n\n    @Override\n    public void onStepAdded(int index, Step\u003c?\u003e addedStep) {\n        // This will be called when a step is added dynamically through the form method addStep().\n    }\n\n    @Override\n    public void onStepRemoved(int index) {\n        // This will be called when a step is removed dynamically through the form method removeStep().\n    }\n}\n```\n\nAs you can see in the code above, we set up the form by passing several parameters through the method `setup()`:\n\n1. An implementation of the interface `StepperFormListener` (in this case, this listener is implemented by the activity, so we just send `this` as a parameter).\n2. The steps that will be displayed in the form: `userNameStep`, `userEmailStep` and `userAgeStep` in our example.\n\nHowever, **we can also customize the form just before initializing it**:\n\n```java\nverticalStepperForm\n    .setup(this, userNameStep, userEmailStep, userAgeStep)\n    .allowNonLinearNavigation(true)\n    .displayBottomNavigation(false)\n    .lastStepNextButtonText(\"Create User\")\n    ...\n    .init();\n```\n\nThere are many methods available to customize the form, but **all the configuration options that you can specify via code are also available in XML**, so it is up to you to set up the form in one way or another.\n\n#### About The Listener\n\nThese are the two most important methods of the `StepperFormListener`:\n\n##### `onCompletedForm()`\n\nThis method will get called when the user clicks on the last confirmation button of the form in an attempt to save/send the information, so **we can use it to save or send the data of the form**. It is worth noting that it will only get invoked if all the steps are marked as completed.\n\nJust before calling this method, the form disables the navigation between steps, as well as all the buttons. To revert the form to normal (for example, because the data couldn't be saved and we want to re-activate the buttons of the form), it is necessary to call `verticalStepperForm.cancelFormCompletionOrCancellationAttempt()`.\n\n##### `onCancelledForm()`\n\nThis method will get called when the user clicks on the optional cancellation button of the last step in order to avoid saving/sending the data. **We can use it to ask the user to confirm the cancellation**, after which we could just close the form screen and navigate away from it.\n\nRight before calling this method, the form disables the navigation between steps, as well as all the buttons. To revert the form to normal (for example, because the user decides not to cancel it), it is necessary to call `verticalStepperForm.cancelFormCompletionOrCancellationAttempt()`.\n\n## Further Details\n\nCheck out the [sample application code](https://github.com/ernestoyaquello/VerticalStepperForm/tree/master/app/src/main/java/verticalstepperform/ernestoyaquello/com/verticalstepperform) to see a more complete example of how this library can be used to create vertical stepper forms.\n\n## Contribution\n\nFeel free to contribute to this library, any help will be welcomed!\n\n## License\n\n```\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fernestoyaquello%2FVerticalStepperForm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fernestoyaquello%2FVerticalStepperForm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fernestoyaquello%2FVerticalStepperForm/lists"}