├── .gitignore
├── .idea
└── gradle.xml
├── AndroidManifest.xml
├── LICENSE
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── libs
└── android-support-v4.jar
├── res
├── drawable-xhdpi
│ ├── ic_launcher.png
│ ├── item_focused.9.png
│ └── item_pressed.9.png
├── drawable
│ ├── finish_background.xml
│ ├── selectable_item_background.xml
│ └── shadow.xml
├── layout
│ ├── activity_main.xml
│ ├── fragment_instruction.xml
│ ├── fragment_page.xml
│ ├── fragment_page_customer_info.xml
│ ├── list_item_review.xml
│ └── toolbar.xml
├── values-v21
│ └── styles.xml
└── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
└── src
└── com
└── example
└── android
└── wizardpager
├── MainActivity.java
├── SandwichWizardModel.java
└── wizard
├── model
├── AbstractWizardModel.java
├── BranchPage.java
├── CustomerInfoPage.java
├── InstructionPage.java
├── ModelCallbacks.java
├── MultipleFixedChoicePage.java
├── Page.java
├── PageList.java
├── PageTreeNode.java
├── ReviewItem.java
└── SingleFixedChoicePage.java
└── ui
├── CustomerInfoFragment.java
├── InstructionFragment.java
├── MultipleChoiceFragment.java
├── PageFragmentCallbacks.java
├── ReviewFragment.java
├── SingleChoiceFragment.java
└── StepPagerStrip.java
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | # Local sandbox
4 | _sandbox
5 |
6 | # built application files
7 | *.apk
8 | *.ap_
9 |
10 | # files for the dex VM
11 | *.dex
12 |
13 | # Java class files
14 | *.class
15 |
16 | # generated files
17 | out/
18 | bin/
19 | gen/
20 |
21 | # Local configuration file (sdk path, etc)
22 | local.properties
23 |
24 | # Eclipse project files
25 | .classpath
26 | .project
27 |
28 | # IDEA files
29 | *.iml
30 | *.ipr
31 | *.iws
32 |
33 | # Other build files
34 | project.properties
35 | ant.properties
36 | build.xml
37 | proguard-project.txt
38 |
39 | # Built application files
40 | /*/build/
41 | /build
42 |
43 | # Gradle generated files
44 | .gradle/
45 |
46 | # User-specific configurations
47 | .idea/libraries/
48 | .idea/workspace.xml
49 | .idea/tasks.xml
50 | .idea/.name
51 | .idea/compiler.xml
52 | .idea/copyright/profiles_settings.xml
53 | .idea/encodings.xml
54 | .idea/misc.xml
55 | .idea/modules.xml
56 | .idea/scopes/scope_settings.xml
57 | .idea/vcs.xml
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
21 |
22 |
23 |
24 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction, and
10 | distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright
13 | owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all other entities
16 | that control, are controlled by, or are under common control with that entity.
17 | For the purposes of this definition, "control" means (i) the power, direct or
18 | indirect, to cause the direction or management of such entity, whether by
19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20 | outstanding shares, or (iii) beneficial ownership of such entity.
21 |
22 | "You" (or "Your") shall mean an individual or Legal Entity exercising
23 | permissions granted by this License.
24 |
25 | "Source" form shall mean the preferred form for making modifications, including
26 | but not limited to software source code, documentation source, and configuration
27 | files.
28 |
29 | "Object" form shall mean any form resulting from mechanical transformation or
30 | translation of a Source form, including but not limited to compiled object code,
31 | generated documentation, and conversions to other media types.
32 |
33 | "Work" shall mean the work of authorship, whether in Source or Object form, made
34 | available under the License, as indicated by a copyright notice that is included
35 | in or attached to the work (an example is provided in the Appendix below).
36 |
37 | "Derivative Works" shall mean any work, whether in Source or Object form, that
38 | is based on (or derived from) the Work and for which the editorial revisions,
39 | annotations, elaborations, or other modifications represent, as a whole, an
40 | original work of authorship. For the purposes of this License, Derivative Works
41 | shall not include works that remain separable from, or merely link (or bind by
42 | name) to the interfaces of, the Work and Derivative Works thereof.
43 |
44 | "Contribution" shall mean any work of authorship, including the original version
45 | of the Work and any modifications or additions to that Work or Derivative Works
46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work
47 | by the copyright owner or by an individual or Legal Entity authorized to submit
48 | on behalf of the copyright owner. For the purposes of this definition,
49 | "submitted" means any form of electronic, verbal, or written communication sent
50 | to the Licensor or its representatives, including but not limited to
51 | communication on electronic mailing lists, source code control systems, and
52 | issue tracking systems that are managed by, or on behalf of, the Licensor for
53 | the purpose of discussing and improving the Work, but excluding communication
54 | that is conspicuously marked or otherwise designated in writing by the copyright
55 | owner as "Not a Contribution."
56 |
57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58 | of whom a Contribution has been received by Licensor and subsequently
59 | incorporated within the Work.
60 |
61 | 2. Grant of Copyright License.
62 |
63 | Subject to the terms and conditions of this License, each Contributor hereby
64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65 | irrevocable copyright license to reproduce, prepare Derivative Works of,
66 | publicly display, publicly perform, sublicense, and distribute the Work and such
67 | Derivative Works in Source or Object form.
68 |
69 | 3. Grant of Patent License.
70 |
71 | Subject to the terms and conditions of this License, each Contributor hereby
72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73 | irrevocable (except as stated in this section) patent license to make, have
74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75 | such license applies only to those patent claims licensable by such Contributor
76 | that are necessarily infringed by their Contribution(s) alone or by combination
77 | of their Contribution(s) with the Work to which such Contribution(s) was
78 | submitted. If You institute patent litigation against any entity (including a
79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80 | Contribution incorporated within the Work constitutes direct or contributory
81 | patent infringement, then any patent licenses granted to You under this License
82 | for that Work shall terminate as of the date such litigation is filed.
83 |
84 | 4. Redistribution.
85 |
86 | You may reproduce and distribute copies of the Work or Derivative Works thereof
87 | in any medium, with or without modifications, and in Source or Object form,
88 | provided that You meet the following conditions:
89 |
90 | You must give any other recipients of the Work or Derivative Works a copy of
91 | this License; and
92 | You must cause any modified files to carry prominent notices stating that You
93 | changed the files; and
94 | You must retain, in the Source form of any Derivative Works that You distribute,
95 | all copyright, patent, trademark, and attribution notices from the Source form
96 | of the Work, excluding those notices that do not pertain to any part of the
97 | Derivative Works; and
98 | If the Work includes a "NOTICE" text file as part of its distribution, then any
99 | Derivative Works that You distribute must include a readable copy of the
100 | attribution notices contained within such NOTICE file, excluding those notices
101 | that do not pertain to any part of the Derivative Works, in at least one of the
102 | following places: within a NOTICE text file distributed as part of the
103 | Derivative Works; within the Source form or documentation, if provided along
104 | with the Derivative Works; or, within a display generated by the Derivative
105 | Works, if and wherever such third-party notices normally appear. The contents of
106 | the NOTICE file are for informational purposes only and do not modify the
107 | License. You may add Your own attribution notices within Derivative Works that
108 | You distribute, alongside or as an addendum to the NOTICE text from the Work,
109 | provided that such additional attribution notices cannot be construed as
110 | modifying the License.
111 | You may add Your own copyright statement to Your modifications and may provide
112 | additional or different license terms and conditions for use, reproduction, or
113 | distribution of Your modifications, or for any such Derivative Works as a whole,
114 | provided Your use, reproduction, and distribution of the Work otherwise complies
115 | with the conditions stated in this License.
116 |
117 | 5. Submission of Contributions.
118 |
119 | Unless You explicitly state otherwise, any Contribution intentionally submitted
120 | for inclusion in the Work by You to the Licensor shall be under the terms and
121 | conditions of this License, without any additional terms or conditions.
122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of
123 | any separate license agreement you may have executed with Licensor regarding
124 | such Contributions.
125 |
126 | 6. Trademarks.
127 |
128 | This License does not grant permission to use the trade names, trademarks,
129 | service marks, or product names of the Licensor, except as required for
130 | reasonable and customary use in describing the origin of the Work and
131 | reproducing the content of the NOTICE file.
132 |
133 | 7. Disclaimer of Warranty.
134 |
135 | Unless required by applicable law or agreed to in writing, Licensor provides the
136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138 | including, without limitation, any warranties or conditions of TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140 | solely responsible for determining the appropriateness of using or
141 | redistributing the Work and assume any risks associated with Your exercise of
142 | permissions under this License.
143 |
144 | 8. Limitation of Liability.
145 |
146 | In no event and under no legal theory, whether in tort (including negligence),
147 | contract, or otherwise, unless required by applicable law (such as deliberate
148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be
149 | liable to You for damages, including any direct, indirect, special, incidental,
150 | or consequential damages of any character arising as a result of this License or
151 | out of the use or inability to use the Work (including but not limited to
152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153 | any and all other commercial damages or losses), even if such Contributor has
154 | been advised of the possibility of such damages.
155 |
156 | 9. Accepting Warranty or Additional Liability.
157 |
158 | While redistributing the Work or Derivative Works thereof, You may choose to
159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160 | other liability obligations and/or rights consistent with this License. However,
161 | in accepting such obligations, You may act only on Your own behalf and on Your
162 | sole responsibility, not on behalf of any other Contributor, and only if You
163 | agree to indemnify, defend, and hold each Contributor harmless for any liability
164 | incurred by, or claims asserted against, such Contributor by reason of your
165 | accepting any such warranty or additional liability.
166 |
167 | END OF TERMS AND CONDITIONS
168 |
169 | APPENDIX: How to apply the Apache License to your work
170 |
171 | To apply the Apache License to your work, attach the following boilerplate
172 | notice, with the fields enclosed by brackets "[]" replaced with your own
173 | identifying information. (Don't include the brackets!) The text should be
174 | enclosed in the appropriate comment syntax for the file format. We also
175 | recommend that a file or class name and description of purpose be included on
176 | the same "printed page" as the copyright notice for easier identification within
177 | third-party archives.
178 |
179 | Copyright [yyyy] [name of copyright owner]
180 |
181 | Licensed under the Apache License, Version 2.0 (the "License");
182 | you may not use this file except in compliance with the License.
183 | You may obtain a copy of the License at
184 |
185 | http://www.apache.org/licenses/LICENSE-2.0
186 |
187 | Unless required by applicable law or agreed to in writing, software
188 | distributed under the License is distributed on an "AS IS" BASIS,
189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190 | See the License for the specific language governing permissions and
191 | limitations under the License.
192 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Android Lollipop wizard template
2 | ===============================
3 |
4 | Fork of Roman Nurik's Example `ViewPager`-based wizard UI sample code. For further information on his wizard, see [his Google+ post](https://plus.google.com/+RomanNurik/posts/6cVymZvn3f4) or [his Github project page](https://github.com/romannurik/android-wizardpager).
5 |
6 | This template wizard is a Lollipop version of the original wizard.
7 |
8 |
9 |
10 |
11 |
12 |
13 | I've provided a GIF showing the wizard in action.
14 |
15 | 
16 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | mavenCentral()
4 | }
5 | dependencies {
6 | classpath 'com.android.tools.build:gradle:1.1.1'
7 | }
8 | }
9 | apply plugin: 'com.android.application'
10 |
11 | dependencies {
12 | compile "com.android.support:support-v4:22.2.1"
13 | compile 'com.android.support:appcompat-v7:22.2.1'
14 | }
15 |
16 | android {
17 | compileSdkVersion 22
18 | buildToolsVersion "22.0.1"
19 |
20 | sourceSets {
21 | main {
22 | manifest.srcFile 'AndroidManifest.xml'
23 | java.srcDirs = ['src']
24 | resources.srcDirs = ['src']
25 | aidl.srcDirs = ['src']
26 | renderscript.srcDirs = ['src']
27 | res.srcDirs = ['res']
28 | assets.srcDirs = ['assets']
29 | }
30 |
31 | // Move the tests to tests/java, tests/res, etc...
32 | instrumentTest.setRoot('tests')
33 |
34 | // Move the build types to build-types/
35 | // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
36 | // This moves them out of them default location under src//... which would
37 | // conflict with src/ being used by the main source set.
38 | // Adding new build types or product flavors should be accompanied
39 | // by a similar customization.
40 | debug.setRoot('build-types/debug')
41 | release.setRoot('build-types/release')
42 | }
43 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard/1a336acbd40f639b5b48291f2fc89ac817bd7ab2/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard/1a336acbd40f639b5b48291f2fc89ac817bd7ab2/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard/1a336acbd40f639b5b48291f2fc89ac817bd7ab2/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/item_focused.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard/1a336acbd40f639b5b48291f2fc89ac817bd7ab2/res/drawable-xhdpi/item_focused.9.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/item_pressed.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard/1a336acbd40f639b5b48291f2fc89ac817bd7ab2/res/drawable-xhdpi/item_pressed.9.png
--------------------------------------------------------------------------------
/res/drawable/finish_background.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/res/drawable/selectable_item_background.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/res/drawable/shadow.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
21 |
22 |
23 |
27 |
28 |
29 |
40 |
41 |
46 |
47 |
51 |
52 |
57 |
58 |
67 |
68 |
77 |
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/res/layout/fragment_instruction.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
9 |
12 |
13 |
16 |
17 |
20 |
21 |
23 |
24 |
25 |
26 |
30 |
31 |
33 |
34 |
35 |
36 |
40 |
41 |
43 |
44 |
45 |
46 |
50 |
51 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/res/layout/fragment_page.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
19 |
20 |
21 |
22 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/res/layout/fragment_page_customer_info.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
19 |
20 |
21 |
22 |
28 |
29 |
32 |
33 |
35 |
36 |
44 |
45 |
47 |
48 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/res/layout/list_item_review.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
27 |
28 |
37 |
38 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/res/layout/toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/res/values-v21/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
--------------------------------------------------------------------------------
/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 | #4433b5e5
20 | #ff0099cc
21 | #10000000
22 |
23 |
24 |
25 | #66000000
26 | #9E9E9E
27 |
28 |
29 | #009688
30 | #F5F5F5
31 | #00796B
32 |
33 |
34 |
--------------------------------------------------------------------------------
/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | 32dp
19 | 3dp
20 | 4dp
21 |
22 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 | Wizards
19 |
20 | Next
21 | Previous
22 | Submit
23 | Review
24 |
25 | Name
26 | Email
27 | e.g. Larry
28 | Optional
29 |
30 | Are you happy with your choices?
31 | OK
32 |
33 | Herp derpsum sherpus derpler berps tee herp ter sherper der derpus terp? Merp ner, dee der perp.
34 | Sherpus ter berp derpler derperker pee herpler. Le ner derpus terpus, der ter herpy? Ner terp serp herpem berps herpy der ter.
35 |
36 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
14 |
15 |
18 |
19 |
24 |
25 |
37 |
38 |
49 |
50 |
56 |
57 |
64 |
65 |
72 |
73 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager;
18 |
19 | import com.example.android.wizardpager.wizard.model.AbstractWizardModel;
20 | import com.example.android.wizardpager.wizard.model.ModelCallbacks;
21 | import com.example.android.wizardpager.wizard.model.Page;
22 | import com.example.android.wizardpager.wizard.ui.PageFragmentCallbacks;
23 | import com.example.android.wizardpager.wizard.ui.ReviewFragment;
24 | import com.example.android.wizardpager.wizard.ui.StepPagerStrip;
25 |
26 | import android.app.AlertDialog;
27 | import android.app.Dialog;
28 | import android.os.Bundle;
29 | import android.support.v4.app.DialogFragment;
30 | import android.support.v4.app.Fragment;
31 | import android.support.v4.app.FragmentActivity;
32 | import android.support.v4.app.FragmentManager;
33 | import android.support.v4.app.FragmentStatePagerAdapter;
34 | import android.support.v4.view.ViewPager;
35 | import android.support.v7.app.ActionBarActivity;
36 | import android.support.v7.widget.Toolbar;
37 | import android.util.TypedValue;
38 | import android.view.View;
39 | import android.view.ViewGroup;
40 | import android.widget.Button;
41 |
42 | import java.util.List;
43 |
44 | public class MainActivity extends ActionBarActivity implements
45 | PageFragmentCallbacks,
46 | ReviewFragment.Callbacks,
47 | ModelCallbacks {
48 | private ViewPager mPager;
49 | private MyPagerAdapter mPagerAdapter;
50 |
51 | private boolean mEditingAfterReview;
52 |
53 | private AbstractWizardModel mWizardModel = new SandwichWizardModel(this);
54 |
55 | private boolean mConsumePageSelectedEvent;
56 |
57 | private Button mNextButton;
58 | private Button mPrevButton;
59 |
60 | private List mCurrentPageSequence;
61 | private StepPagerStrip mStepPagerStrip;
62 |
63 | public Toolbar toolbar;
64 |
65 | public void onCreate(Bundle savedInstanceState) {
66 | super.onCreate(savedInstanceState);
67 | setContentView(R.layout.activity_main);
68 |
69 | toolbar = (Toolbar) findViewById(R.id.toolbar);
70 | setSupportActionBar(toolbar);
71 |
72 | if (savedInstanceState != null) {
73 | mWizardModel.load(savedInstanceState.getBundle("model"));
74 | }
75 |
76 |
77 |
78 | mWizardModel.registerListener(this);
79 |
80 | mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager());
81 | mPager = (ViewPager) findViewById(R.id.pager);
82 | mPager.setAdapter(mPagerAdapter);
83 | mStepPagerStrip = (StepPagerStrip) findViewById(R.id.strip);
84 | mStepPagerStrip.setOnPageSelectedListener(new StepPagerStrip.OnPageSelectedListener() {
85 | @Override
86 | public void onPageStripSelected(int position) {
87 | position = Math.min(mPagerAdapter.getCount() - 1, position);
88 | if (mPager.getCurrentItem() != position) {
89 | mPager.setCurrentItem(position);
90 | }
91 | }
92 | });
93 |
94 | mNextButton = (Button) findViewById(R.id.next_button);
95 | mPrevButton = (Button) findViewById(R.id.prev_button);
96 |
97 | mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
98 | @Override
99 | public void onPageSelected(int position) {
100 | mStepPagerStrip.setCurrentPage(position);
101 |
102 | if (mConsumePageSelectedEvent) {
103 | mConsumePageSelectedEvent = false;
104 | return;
105 | }
106 |
107 | mEditingAfterReview = false;
108 | updateBottomBar();
109 | }
110 | });
111 |
112 | mNextButton.setOnClickListener(new View.OnClickListener() {
113 | @Override
114 | public void onClick(View view) {
115 | if (mPager.getCurrentItem() == mCurrentPageSequence.size()) {
116 | DialogFragment dg = new DialogFragment() {
117 | @Override
118 | public Dialog onCreateDialog(Bundle savedInstanceState) {
119 | return new AlertDialog.Builder(getActivity())
120 | .setMessage(R.string.submit_confirm_message)
121 | .setPositiveButton(R.string.submit_confirm_button, null)
122 | .setNegativeButton(android.R.string.cancel, null)
123 | .create();
124 | }
125 | };
126 | dg.show(getSupportFragmentManager(), "place_order_dialog");
127 | } else {
128 | if (mEditingAfterReview) {
129 | mPager.setCurrentItem(mPagerAdapter.getCount() - 1);
130 | } else {
131 | mPager.setCurrentItem(mPager.getCurrentItem() + 1);
132 | }
133 | }
134 | }
135 | });
136 |
137 | mPrevButton.setOnClickListener(new View.OnClickListener() {
138 | @Override
139 | public void onClick(View view) {
140 | mPager.setCurrentItem(mPager.getCurrentItem() - 1);
141 | }
142 | });
143 |
144 | onPageTreeChanged();
145 | updateBottomBar();
146 | }
147 |
148 | @Override
149 | public void onPageTreeChanged() {
150 | mCurrentPageSequence = mWizardModel.getCurrentPageSequence();
151 | recalculateCutOffPage();
152 | mStepPagerStrip.setPageCount(mCurrentPageSequence.size() + 1); // + 1 = review step
153 | mPagerAdapter.notifyDataSetChanged();
154 | updateBottomBar();
155 | }
156 |
157 | private void updateBottomBar() {
158 | int position = mPager.getCurrentItem();
159 | if (position == mCurrentPageSequence.size()) {
160 | mNextButton.setText(R.string.finish);
161 | mNextButton.setBackgroundResource(R.drawable.finish_background);
162 | //mNextButton.setTextAppearance(this, R.style.TextAppearanceFinish);
163 | } else {
164 | mNextButton.setText(mEditingAfterReview
165 | ? R.string.review
166 | : R.string.next);
167 | mNextButton.setBackgroundResource(R.drawable.selectable_item_background);
168 | TypedValue v = new TypedValue();
169 | getTheme().resolveAttribute(android.R.attr.textAppearanceMedium, v, true);
170 | //mNextButton.setTextAppearance(this, v.resourceId);
171 | mNextButton.setEnabled(position != mPagerAdapter.getCutOffPage());
172 | }
173 |
174 | mPrevButton.setVisibility(position <= 0 ? View.INVISIBLE : View.VISIBLE);
175 | }
176 |
177 | @Override
178 | protected void onDestroy() {
179 | super.onDestroy();
180 | mWizardModel.unregisterListener(this);
181 | }
182 |
183 | @Override
184 | protected void onSaveInstanceState(Bundle outState) {
185 | super.onSaveInstanceState(outState);
186 | outState.putBundle("model", mWizardModel.save());
187 | }
188 |
189 | @Override
190 | public AbstractWizardModel onGetModel() {
191 | return mWizardModel;
192 | }
193 |
194 | @Override
195 | public void onEditScreenAfterReview(String key) {
196 | for (int i = mCurrentPageSequence.size() - 1; i >= 0; i--) {
197 | if (mCurrentPageSequence.get(i).getKey().equals(key)) {
198 | mConsumePageSelectedEvent = true;
199 | mEditingAfterReview = true;
200 | mPager.setCurrentItem(i);
201 | updateBottomBar();
202 | break;
203 | }
204 | }
205 | }
206 |
207 | @Override
208 | public void onPageDataChanged(Page page) {
209 | if (page.isRequired()) {
210 | if (recalculateCutOffPage()) {
211 | mPagerAdapter.notifyDataSetChanged();
212 | updateBottomBar();
213 | }
214 | }
215 | }
216 |
217 | @Override
218 | public Page onGetPage(String key) {
219 | return mWizardModel.findByKey(key);
220 | }
221 |
222 | private boolean recalculateCutOffPage() {
223 | // Cut off the pager adapter at first required page that isn't completed
224 | int cutOffPage = mCurrentPageSequence.size() + 1;
225 | for (int i = 0; i < mCurrentPageSequence.size(); i++) {
226 | Page page = mCurrentPageSequence.get(i);
227 | if (page.isRequired() && !page.isCompleted()) {
228 | cutOffPage = i;
229 | break;
230 | }
231 | }
232 |
233 | if (mPagerAdapter.getCutOffPage() != cutOffPage) {
234 | mPagerAdapter.setCutOffPage(cutOffPage);
235 | return true;
236 | }
237 |
238 | return false;
239 | }
240 |
241 | public class MyPagerAdapter extends FragmentStatePagerAdapter {
242 | private int mCutOffPage;
243 | private Fragment mPrimaryItem;
244 |
245 | public MyPagerAdapter(FragmentManager fm) {
246 | super(fm);
247 | }
248 |
249 | @Override
250 | public Fragment getItem(int i) {
251 | if (i >= mCurrentPageSequence.size()) {
252 | return new ReviewFragment();
253 | }
254 |
255 | return mCurrentPageSequence.get(i).createFragment();
256 | }
257 |
258 | @Override
259 | public int getItemPosition(Object object) {
260 | // TODO: be smarter about this
261 | if (object == mPrimaryItem) {
262 | // Re-use the current fragment (its position never changes)
263 | return POSITION_UNCHANGED;
264 | }
265 |
266 | return POSITION_NONE;
267 | }
268 |
269 | @Override
270 | public void setPrimaryItem(ViewGroup container, int position, Object object) {
271 | super.setPrimaryItem(container, position, object);
272 | mPrimaryItem = (Fragment) object;
273 | }
274 |
275 | @Override
276 | public int getCount() {
277 | if (mCurrentPageSequence == null) {
278 | return 0;
279 | }
280 | return Math.min(mCutOffPage + 1, mCurrentPageSequence.size() + 1);
281 | }
282 |
283 | public void setCutOffPage(int cutOffPage) {
284 | if (cutOffPage < 0) {
285 | cutOffPage = Integer.MAX_VALUE;
286 | }
287 | mCutOffPage = cutOffPage;
288 | }
289 |
290 | public int getCutOffPage() {
291 | return mCutOffPage;
292 | }
293 | }
294 | }
295 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/SandwichWizardModel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager;
18 |
19 | import com.example.android.wizardpager.wizard.model.AbstractWizardModel;
20 | import com.example.android.wizardpager.wizard.model.BranchPage;
21 | import com.example.android.wizardpager.wizard.model.CustomerInfoPage;
22 | import com.example.android.wizardpager.wizard.model.InstructionPage;
23 | import com.example.android.wizardpager.wizard.model.MultipleFixedChoicePage;
24 | import com.example.android.wizardpager.wizard.model.PageList;
25 | import com.example.android.wizardpager.wizard.model.SingleFixedChoicePage;
26 |
27 | import android.content.Context;
28 |
29 | public class SandwichWizardModel extends AbstractWizardModel {
30 | public SandwichWizardModel(Context context) {
31 | super(context);
32 | }
33 |
34 | @Override
35 | protected PageList onNewRootPageList() {
36 | return new PageList(
37 |
38 | // BranchPage shows all of the branches available: Branch One, Branch Two, Branch Three. Each of these branches
39 | // have their own questions and the choices of the user will be summarised in the review section at the end
40 | new BranchPage(this, "Select one options")
41 | .addBranch("Branch One",
42 | new SingleFixedChoicePage(this, "Question One")
43 | .setChoices("A", "B", "C", "D")
44 | .setRequired(true),
45 |
46 | new MultipleFixedChoicePage(this, "Question Two")
47 | .setChoices("A", "B", "C", "D",
48 | "E")
49 | )
50 |
51 | // Second branch of questions
52 | .addBranch("Branch Two",
53 | new SingleFixedChoicePage(this, "Question One")
54 | .setChoices("A", "B")
55 | .setRequired(true),
56 |
57 | new SingleFixedChoicePage(this, "Question Two")
58 | .setChoices("A", "B", "C",
59 | "D", "E", "F")
60 | .setRequired(true),
61 |
62 | new SingleFixedChoicePage(this, "Question Three")
63 | .setChoices("A", "B", "C")
64 | )
65 |
66 | // Third branch of questions
67 | .addBranch("Branch Three",
68 | new InstructionPage(this, "Info"),
69 |
70 | new SingleFixedChoicePage(this, "Question One")
71 | .setChoices("A", "B", "C")
72 | .setRequired(true)
73 | )
74 | );
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/AbstractWizardModel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | import android.content.Context;
20 | import android.os.Bundle;
21 |
22 | import java.util.ArrayList;
23 | import java.util.List;
24 |
25 | /**
26 | * Represents a wizard model, including the pages/steps in the wizard, their dependencies, and their
27 | * currently populated choices/values/selections.
28 | *
29 | * To create an actual wizard model, extend this class and implement {@link #onNewRootPageList()}.
30 | */
31 | public abstract class AbstractWizardModel implements ModelCallbacks {
32 | protected Context mContext;
33 |
34 | private List mListeners = new ArrayList();
35 | private PageList mRootPageList;
36 |
37 | public AbstractWizardModel(Context context) {
38 | mContext = context;
39 | mRootPageList = onNewRootPageList();
40 | }
41 |
42 | /**
43 | * Override this to define a new wizard model.
44 | */
45 | protected abstract PageList onNewRootPageList();
46 |
47 | @Override
48 | public void onPageDataChanged(Page page) {
49 | // can't use for each because of concurrent modification (review fragment
50 | // can get added or removed and will register itself as a listener)
51 | for (int i = 0; i < mListeners.size(); i++) {
52 | mListeners.get(i).onPageDataChanged(page);
53 | }
54 | }
55 |
56 | @Override
57 | public void onPageTreeChanged() {
58 | // can't use for each because of concurrent modification (review fragment
59 | // can get added or removed and will register itself as a listener)
60 | for (int i = 0; i < mListeners.size(); i++) {
61 | mListeners.get(i).onPageTreeChanged();
62 | }
63 | }
64 |
65 | public Page findByKey(String key) {
66 | return mRootPageList.findByKey(key);
67 | }
68 |
69 | public void load(Bundle savedValues) {
70 | for (String key : savedValues.keySet()) {
71 | mRootPageList.findByKey(key).resetData(savedValues.getBundle(key));
72 | }
73 | }
74 |
75 | public void registerListener(ModelCallbacks listener) {
76 | mListeners.add(listener);
77 | }
78 |
79 | public Bundle save() {
80 | Bundle bundle = new Bundle();
81 | for (Page page : getCurrentPageSequence()) {
82 | bundle.putBundle(page.getKey(), page.getData());
83 | }
84 | return bundle;
85 | }
86 |
87 | /**
88 | * Gets the current list of wizard steps, flattening nested (dependent) pages based on the
89 | * user's choices.
90 | */
91 | public List getCurrentPageSequence() {
92 | ArrayList flattened = new ArrayList();
93 | mRootPageList.flattenCurrentPageSequence(flattened);
94 | return flattened;
95 | }
96 |
97 | public void unregisterListener(ModelCallbacks listener) {
98 | mListeners.remove(listener);
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/BranchPage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | import com.example.android.wizardpager.wizard.ui.SingleChoiceFragment;
20 |
21 | import android.support.v4.app.Fragment;
22 | import android.text.TextUtils;
23 |
24 | import java.util.ArrayList;
25 | import java.util.List;
26 |
27 | /**
28 | * A page representing a branching point in the wizard. Depending on which choice is selected, the
29 | * next set of steps in the wizard may change.
30 | */
31 | public class BranchPage extends SingleFixedChoicePage {
32 | private List mBranches = new ArrayList();
33 |
34 | public BranchPage(ModelCallbacks callbacks, String title) {
35 | super(callbacks, title);
36 | }
37 |
38 | @Override
39 | public Page findByKey(String key) {
40 | if (getKey().equals(key)) {
41 | return this;
42 | }
43 |
44 | for (Branch branch : mBranches) {
45 | Page found = branch.childPageList.findByKey(key);
46 | if (found != null) {
47 | return found;
48 | }
49 | }
50 |
51 | return null;
52 | }
53 |
54 | @Override
55 | public void flattenCurrentPageSequence(ArrayList destination) {
56 | super.flattenCurrentPageSequence(destination);
57 | for (Branch branch : mBranches) {
58 | if (branch.choice.equals(mData.getString(Page.SIMPLE_DATA_KEY))) {
59 | branch.childPageList.flattenCurrentPageSequence(destination);
60 | break;
61 | }
62 | }
63 | }
64 |
65 | public BranchPage addBranch(String choice, Page... childPages) {
66 | PageList childPageList = new PageList(childPages);
67 | for (Page page : childPageList) {
68 | page.setParentKey(choice);
69 | }
70 | mBranches.add(new Branch(choice, childPageList));
71 | return this;
72 | }
73 |
74 | public BranchPage addBranch(String choice) {
75 | mBranches.add(new Branch(choice, new PageList()));
76 | return this;
77 | }
78 |
79 | @Override
80 | public Fragment createFragment() {
81 | return SingleChoiceFragment.create(getKey());
82 | }
83 |
84 | public String getOptionAt(int position) {
85 | return mBranches.get(position).choice;
86 | }
87 |
88 | public int getOptionCount() {
89 | return mBranches.size();
90 | }
91 |
92 | @Override
93 | public void getReviewItems(ArrayList dest) {
94 | dest.add(new ReviewItem(getTitle(), mData.getString(SIMPLE_DATA_KEY), getKey()));
95 | }
96 |
97 | @Override
98 | public boolean isCompleted() {
99 | return !TextUtils.isEmpty(mData.getString(SIMPLE_DATA_KEY));
100 | }
101 |
102 | @Override
103 | public void notifyDataChanged() {
104 | mCallbacks.onPageTreeChanged();
105 | super.notifyDataChanged();
106 | }
107 |
108 | public BranchPage setValue(String value) {
109 | mData.putString(SIMPLE_DATA_KEY, value);
110 | return this;
111 | }
112 |
113 | private static class Branch {
114 | public String choice;
115 | public PageList childPageList;
116 |
117 | private Branch(String choice, PageList childPageList) {
118 | this.choice = choice;
119 | this.childPageList = childPageList;
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/CustomerInfoPage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | import com.example.android.wizardpager.wizard.ui.CustomerInfoFragment;
20 |
21 | import android.support.v4.app.Fragment;
22 | import android.text.TextUtils;
23 |
24 | import java.util.ArrayList;
25 |
26 | /**
27 | * A page asking for a name and an email.
28 | */
29 | public class CustomerInfoPage extends Page {
30 | public static final String NAME_DATA_KEY = "name";
31 | public static final String EMAIL_DATA_KEY = "email";
32 |
33 | public CustomerInfoPage(ModelCallbacks callbacks, String title) {
34 | super(callbacks, title);
35 | }
36 |
37 | @Override
38 | public Fragment createFragment() {
39 | return CustomerInfoFragment.create(getKey());
40 | }
41 |
42 | @Override
43 | public void getReviewItems(ArrayList dest) {
44 | dest.add(new ReviewItem("Your name", mData.getString(NAME_DATA_KEY), getKey(), -1));
45 | dest.add(new ReviewItem("Your email", mData.getString(EMAIL_DATA_KEY), getKey(), -1));
46 | }
47 |
48 | @Override
49 | public boolean isCompleted() {
50 | return !TextUtils.isEmpty(mData.getString(NAME_DATA_KEY));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/InstructionPage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | import android.support.v4.app.Fragment;
20 | import android.text.TextUtils;
21 |
22 | import com.example.android.wizardpager.wizard.ui.InstructionFragment;
23 |
24 | import java.util.ArrayList;
25 |
26 | /**
27 | * A page offering the user a number of mutually exclusive choices.
28 | */
29 | public class InstructionPage extends Page {
30 | protected ArrayList mChoices = new ArrayList();
31 |
32 | public InstructionPage(ModelCallbacks callbacks, String title) {
33 | super(callbacks, title);
34 | }
35 |
36 | @Override
37 | public Fragment createFragment() {
38 | return InstructionFragment.create(getKey());
39 | }
40 |
41 | public String getOptionAt(int position) {
42 | return mChoices.get(position);
43 | }
44 |
45 | public int getOptionCount() {
46 | return mChoices.size();
47 | }
48 |
49 | @Override
50 | public void getReviewItems(ArrayList dest) {
51 |
52 | /*
53 | The line below is commented out to prevent another ReviewItem being added to the review
54 | at the end of the wizard. If you want to enable this the value displayed will be '(None)'
55 | but you can change this value by changing the value inside mData.getString()
56 | */
57 |
58 |
59 | //dest.add(new ReviewItem(getTitle(), mData.getString(SIMPLE_DATA_KEY), getKey()));
60 | }
61 |
62 | @Override
63 | public boolean isCompleted() {
64 | return !TextUtils.isEmpty(mData.getString(SIMPLE_DATA_KEY));
65 | }
66 |
67 | public InstructionPage setValue(String value) {
68 | mData.putString(SIMPLE_DATA_KEY, value);
69 | return this;
70 | }
71 |
72 |
73 | }
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/ModelCallbacks.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | /**
20 | * Callback interface connecting {@link Page}, {@link AbstractWizardModel}, and model container
21 | * objects (e.g. {@link com.example.android.wizardpager.MainActivity}.
22 | */
23 | public interface ModelCallbacks {
24 | void onPageDataChanged(Page page);
25 | void onPageTreeChanged();
26 | }
27 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/MultipleFixedChoicePage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | import com.example.android.wizardpager.wizard.ui.MultipleChoiceFragment;
20 |
21 | import android.support.v4.app.Fragment;
22 |
23 | import java.util.ArrayList;
24 |
25 | /**
26 | * A page offering the user a number of non-mutually exclusive choices.
27 | */
28 | public class MultipleFixedChoicePage extends SingleFixedChoicePage {
29 | public MultipleFixedChoicePage(ModelCallbacks callbacks, String title) {
30 | super(callbacks, title);
31 | }
32 |
33 | @Override
34 | public Fragment createFragment() {
35 | return MultipleChoiceFragment.create(getKey());
36 | }
37 |
38 | @Override
39 | public void getReviewItems(ArrayList dest) {
40 | StringBuilder sb = new StringBuilder();
41 |
42 | ArrayList selections = mData.getStringArrayList(Page.SIMPLE_DATA_KEY);
43 | if (selections != null && selections.size() > 0) {
44 | for (String selection : selections) {
45 | if (sb.length() > 0) {
46 | sb.append(", ");
47 | }
48 | sb.append(selection);
49 | }
50 | }
51 |
52 | dest.add(new ReviewItem(getTitle(), sb.toString(), getKey()));
53 | }
54 |
55 | @Override
56 | public boolean isCompleted() {
57 | ArrayList selections = mData.getStringArrayList(Page.SIMPLE_DATA_KEY);
58 | return selections != null && selections.size() > 0;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/Page.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | import android.os.Bundle;
20 | import android.support.v4.app.Fragment;
21 |
22 | import java.util.ArrayList;
23 |
24 | /**
25 | * Represents a single page in the wizard.
26 | */
27 | public abstract class Page implements PageTreeNode {
28 | /**
29 | * The key into {@link #getData()} used for wizards with simple (single) values.
30 | */
31 | public static final String SIMPLE_DATA_KEY = "_";
32 |
33 | protected ModelCallbacks mCallbacks;
34 |
35 | /**
36 | * Current wizard values/selections.
37 | */
38 | protected Bundle mData = new Bundle();
39 | protected String mTitle;
40 | protected boolean mRequired = false;
41 | protected String mParentKey;
42 |
43 | protected Page(ModelCallbacks callbacks, String title) {
44 | mCallbacks = callbacks;
45 | mTitle = title;
46 | }
47 |
48 | public Bundle getData() {
49 | return mData;
50 | }
51 |
52 | public String getTitle() {
53 | return mTitle;
54 | }
55 |
56 | public boolean isRequired() {
57 | return mRequired;
58 | }
59 |
60 | void setParentKey(String parentKey) {
61 | mParentKey = parentKey;
62 | }
63 |
64 | @Override
65 | public Page findByKey(String key) {
66 | return getKey().equals(key) ? this : null;
67 | }
68 |
69 | @Override
70 | public void flattenCurrentPageSequence(ArrayList dest) {
71 | dest.add(this);
72 | }
73 |
74 | public abstract Fragment createFragment();
75 |
76 | public String getKey() {
77 | return (mParentKey != null) ? mParentKey + ":" + mTitle : mTitle;
78 | }
79 |
80 | public abstract void getReviewItems(ArrayList dest);
81 |
82 | public boolean isCompleted() {
83 | return true;
84 | }
85 |
86 | public void resetData(Bundle data) {
87 | mData = data;
88 | notifyDataChanged();
89 | }
90 |
91 | public void notifyDataChanged() {
92 | mCallbacks.onPageDataChanged(this);
93 | }
94 |
95 | public Page setRequired(boolean required) {
96 | mRequired = required;
97 | return this;
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/PageList.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | import java.util.ArrayList;
20 |
21 | /**
22 | * Represents a list of wizard pages.
23 | */
24 | public class PageList extends ArrayList implements PageTreeNode {
25 |
26 | public PageList() {
27 |
28 | }
29 |
30 | public PageList(Page... pages) {
31 | for (Page page : pages) {
32 | add(page);
33 | }
34 | }
35 |
36 | @Override
37 | public Page findByKey(String key) {
38 | for (Page childPage : this) {
39 | Page found = childPage.findByKey(key);
40 | if (found != null) {
41 | return found;
42 | }
43 | }
44 |
45 | return null;
46 | }
47 |
48 | @Override
49 | public void flattenCurrentPageSequence(ArrayList dest) {
50 | for (Page childPage : this) {
51 | childPage.flattenCurrentPageSequence(dest);
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/PageTreeNode.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | import java.util.ArrayList;
20 |
21 | /**
22 | * Represents a node in the page tree. Can either be a single page, or a page container.
23 | */
24 | public interface PageTreeNode {
25 | public Page findByKey(String key);
26 | public void flattenCurrentPageSequence(ArrayList dest);
27 | }
28 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/ReviewItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | /**
20 | * Represents a single line item on the final review page.
21 | *
22 | * @see com.example.android.wizardpager.wizard.ui.ReviewFragment
23 | */
24 | public class ReviewItem {
25 | public static final int DEFAULT_WEIGHT = 0;
26 |
27 | private int mWeight;
28 | private String mTitle;
29 | private String mDisplayValue;
30 | private String mPageKey;
31 |
32 | public ReviewItem(String title, String displayValue, String pageKey) {
33 | this(title, displayValue, pageKey, DEFAULT_WEIGHT);
34 | }
35 |
36 | public ReviewItem(String title, String displayValue, String pageKey, int weight) {
37 | mTitle = title;
38 | mDisplayValue = displayValue;
39 | mPageKey = pageKey;
40 | mWeight = weight;
41 | }
42 |
43 | public String getDisplayValue() {
44 | return mDisplayValue;
45 | }
46 |
47 | public void setDisplayValue(String displayValue) {
48 | mDisplayValue = displayValue;
49 | }
50 |
51 | public String getPageKey() {
52 | return mPageKey;
53 | }
54 |
55 | public void setPageKey(String pageKey) {
56 | mPageKey = pageKey;
57 | }
58 |
59 | public String getTitle() {
60 | return mTitle;
61 | }
62 |
63 | public void setTitle(String title) {
64 | mTitle = title;
65 | }
66 |
67 | public int getWeight() {
68 | return mWeight;
69 | }
70 |
71 | public void setWeight(int weight) {
72 | mWeight = weight;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/model/SingleFixedChoicePage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.model;
18 |
19 | import com.example.android.wizardpager.wizard.ui.SingleChoiceFragment;
20 |
21 | import android.support.v4.app.Fragment;
22 | import android.text.TextUtils;
23 |
24 | import java.util.ArrayList;
25 | import java.util.Arrays;
26 |
27 | /**
28 | * A page offering the user a number of mutually exclusive choices.
29 | */
30 | public class SingleFixedChoicePage extends Page {
31 | protected ArrayList mChoices = new ArrayList();
32 |
33 | public SingleFixedChoicePage(ModelCallbacks callbacks, String title) {
34 | super(callbacks, title);
35 | }
36 |
37 | @Override
38 | public Fragment createFragment() {
39 | return SingleChoiceFragment.create(getKey());
40 | }
41 |
42 | public String getOptionAt(int position) {
43 | return mChoices.get(position);
44 | }
45 |
46 | public int getOptionCount() {
47 | return mChoices.size();
48 | }
49 |
50 | @Override
51 | public void getReviewItems(ArrayList dest) {
52 | dest.add(new ReviewItem(getTitle(), mData.getString(SIMPLE_DATA_KEY), getKey()));
53 | }
54 |
55 | @Override
56 | public boolean isCompleted() {
57 | return !TextUtils.isEmpty(mData.getString(SIMPLE_DATA_KEY));
58 | }
59 |
60 | public SingleFixedChoicePage setChoices(String... choices) {
61 | mChoices.addAll(Arrays.asList(choices));
62 | return this;
63 | }
64 |
65 | public SingleFixedChoicePage setValue(String value) {
66 | mData.putString(SIMPLE_DATA_KEY, value);
67 | return this;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/ui/CustomerInfoFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.ui;
18 |
19 | import com.example.android.wizardpager.R;
20 | import com.example.android.wizardpager.wizard.model.CustomerInfoPage;
21 |
22 | import android.app.Activity;
23 | import android.content.Context;
24 | import android.os.Bundle;
25 | import android.support.v4.app.Fragment;
26 | import android.text.Editable;
27 | import android.text.TextWatcher;
28 | import android.view.LayoutInflater;
29 | import android.view.View;
30 | import android.view.ViewGroup;
31 | import android.view.inputmethod.InputMethodManager;
32 | import android.widget.TextView;
33 |
34 | public class CustomerInfoFragment extends Fragment {
35 | private static final String ARG_KEY = "key";
36 |
37 | private PageFragmentCallbacks mCallbacks;
38 | private String mKey;
39 | private CustomerInfoPage mPage;
40 | private TextView mNameView;
41 | private TextView mEmailView;
42 |
43 | public static CustomerInfoFragment create(String key) {
44 | Bundle args = new Bundle();
45 | args.putString(ARG_KEY, key);
46 |
47 | CustomerInfoFragment fragment = new CustomerInfoFragment();
48 | fragment.setArguments(args);
49 | return fragment;
50 | }
51 |
52 | public CustomerInfoFragment() {
53 | }
54 |
55 | @Override
56 | public void onCreate(Bundle savedInstanceState) {
57 | super.onCreate(savedInstanceState);
58 |
59 | Bundle args = getArguments();
60 | mKey = args.getString(ARG_KEY);
61 | mPage = (CustomerInfoPage) mCallbacks.onGetPage(mKey);
62 | }
63 |
64 | @Override
65 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
66 | Bundle savedInstanceState) {
67 | View rootView = inflater.inflate(R.layout.fragment_page_customer_info, container, false);
68 | ((TextView) rootView.findViewById(android.R.id.title)).setText(mPage.getTitle());
69 |
70 | mNameView = ((TextView) rootView.findViewById(R.id.your_name));
71 | mNameView.setText(mPage.getData().getString(CustomerInfoPage.NAME_DATA_KEY));
72 |
73 | mEmailView = ((TextView) rootView.findViewById(R.id.your_email));
74 | mEmailView.setText(mPage.getData().getString(CustomerInfoPage.EMAIL_DATA_KEY));
75 | return rootView;
76 | }
77 |
78 | @Override
79 | public void onAttach(Activity activity) {
80 | super.onAttach(activity);
81 |
82 | if (!(activity instanceof PageFragmentCallbacks)) {
83 | throw new ClassCastException("Activity must implement PageFragmentCallbacks");
84 | }
85 |
86 | mCallbacks = (PageFragmentCallbacks) activity;
87 | }
88 |
89 | @Override
90 | public void onDetach() {
91 | super.onDetach();
92 | mCallbacks = null;
93 | }
94 |
95 | @Override
96 | public void onViewCreated(View view, Bundle savedInstanceState) {
97 | super.onViewCreated(view, savedInstanceState);
98 |
99 | mNameView.addTextChangedListener(new TextWatcher() {
100 | @Override
101 | public void beforeTextChanged(CharSequence charSequence, int i, int i1,
102 | int i2) {
103 | }
104 |
105 | @Override
106 | public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
107 | }
108 |
109 | @Override
110 | public void afterTextChanged(Editable editable) {
111 | mPage.getData().putString(CustomerInfoPage.NAME_DATA_KEY,
112 | (editable != null) ? editable.toString() : null);
113 | mPage.notifyDataChanged();
114 | }
115 | });
116 |
117 | mEmailView.addTextChangedListener(new TextWatcher() {
118 | @Override
119 | public void beforeTextChanged(CharSequence charSequence, int i, int i1,
120 | int i2) {
121 | }
122 |
123 | @Override
124 | public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
125 | }
126 |
127 | @Override
128 | public void afterTextChanged(Editable editable) {
129 | mPage.getData().putString(CustomerInfoPage.EMAIL_DATA_KEY,
130 | (editable != null) ? editable.toString() : null);
131 | mPage.notifyDataChanged();
132 | }
133 | });
134 | }
135 |
136 | @Override
137 | public void setMenuVisibility(boolean menuVisible) {
138 | super.setMenuVisibility(menuVisible);
139 |
140 | // In a future update to the support library, this should override setUserVisibleHint
141 | // instead of setMenuVisibility.
142 | if (mNameView != null) {
143 | InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
144 | Context.INPUT_METHOD_SERVICE);
145 | if (!menuVisible) {
146 | imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
147 | }
148 | }
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/ui/InstructionFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.ui;
18 |
19 | import android.app.Activity;
20 | import android.os.Bundle;
21 | import android.support.v4.app.Fragment;
22 | import android.view.LayoutInflater;
23 | import android.view.View;
24 | import android.view.ViewGroup;
25 | import android.widget.TextView;
26 |
27 | import com.example.android.wizardpager.R;
28 | import com.example.android.wizardpager.wizard.model.InstructionPage;
29 | import com.example.android.wizardpager.wizard.model.Page;
30 |
31 | import java.util.ArrayList;
32 | import java.util.List;
33 |
34 | public class InstructionFragment extends Fragment {
35 | private static final String ARG_KEY = "key";
36 |
37 | private PageFragmentCallbacks mCallbacks;
38 | private List mChoices;
39 | private String mKey;
40 | private Page mPage;
41 |
42 | public static InstructionFragment create(String key) {
43 | Bundle args = new Bundle();
44 | args.putString(ARG_KEY, key);
45 |
46 | InstructionFragment fragment = new InstructionFragment();
47 | fragment.setArguments(args);
48 | return fragment;
49 | }
50 |
51 | public InstructionFragment() {
52 | }
53 |
54 | @Override
55 | public void onCreate(Bundle savedInstanceState) {
56 | super.onCreate(savedInstanceState);
57 |
58 | Bundle args = getArguments();
59 | mKey = args.getString(ARG_KEY);
60 | mPage = mCallbacks.onGetPage(mKey);
61 |
62 | InstructionPage fixedChoicePage = (InstructionPage) mPage;
63 | mChoices = new ArrayList();
64 | for (int i = 0; i < fixedChoicePage.getOptionCount(); i++) {
65 | mChoices.add(fixedChoicePage.getOptionAt(i));
66 | }
67 | }
68 |
69 | @Override
70 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
71 | Bundle savedInstanceState) {
72 | View rootView = inflater.inflate(R.layout.fragment_instruction, container, false);
73 | ((TextView) rootView.findViewById(R.id.testingID)).setText("Help");
74 |
75 |
76 | return rootView;
77 | }
78 |
79 | @Override
80 | public void onAttach(Activity activity) {
81 | super.onAttach(activity);
82 |
83 | if (!(activity instanceof PageFragmentCallbacks)) {
84 | throw new ClassCastException("Activity must implement PageFragmentCallbacks");
85 | }
86 |
87 | mCallbacks = (PageFragmentCallbacks) activity;
88 | }
89 |
90 | @Override
91 | public void onDetach() {
92 | super.onDetach();
93 | mCallbacks = null;
94 | }
95 |
96 | }
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/ui/MultipleChoiceFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.ui;
18 |
19 | import com.example.android.wizardpager.R;
20 | import com.example.android.wizardpager.wizard.model.MultipleFixedChoicePage;
21 | import com.example.android.wizardpager.wizard.model.Page;
22 |
23 | import android.app.Activity;
24 | import android.os.Bundle;
25 | import android.os.Handler;
26 | import android.support.v4.app.ListFragment;
27 | import android.util.SparseBooleanArray;
28 | import android.view.LayoutInflater;
29 | import android.view.View;
30 | import android.view.ViewGroup;
31 | import android.widget.ArrayAdapter;
32 | import android.widget.ListView;
33 | import android.widget.TextView;
34 |
35 | import java.util.ArrayList;
36 | import java.util.HashSet;
37 | import java.util.List;
38 | import java.util.Set;
39 |
40 | public class MultipleChoiceFragment extends ListFragment {
41 | private static final String ARG_KEY = "key";
42 |
43 | private PageFragmentCallbacks mCallbacks;
44 | private String mKey;
45 | private List mChoices;
46 | private Page mPage;
47 |
48 | public static MultipleChoiceFragment create(String key) {
49 | Bundle args = new Bundle();
50 | args.putString(ARG_KEY, key);
51 |
52 | MultipleChoiceFragment fragment = new MultipleChoiceFragment();
53 | fragment.setArguments(args);
54 | return fragment;
55 | }
56 |
57 | public MultipleChoiceFragment() {
58 | }
59 |
60 | @Override
61 | public void onCreate(Bundle savedInstanceState) {
62 | super.onCreate(savedInstanceState);
63 |
64 | Bundle args = getArguments();
65 | mKey = args.getString(ARG_KEY);
66 | mPage = mCallbacks.onGetPage(mKey);
67 |
68 | MultipleFixedChoicePage fixedChoicePage = (MultipleFixedChoicePage) mPage;
69 | mChoices = new ArrayList();
70 | for (int i = 0; i < fixedChoicePage.getOptionCount(); i++) {
71 | mChoices.add(fixedChoicePage.getOptionAt(i));
72 | }
73 | }
74 |
75 | @Override
76 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
77 | Bundle savedInstanceState) {
78 | View rootView = inflater.inflate(R.layout.fragment_page, container, false);
79 | ((TextView) rootView.findViewById(android.R.id.title)).setText(mPage.getTitle());
80 |
81 | final ListView listView = (ListView) rootView.findViewById(android.R.id.list);
82 | setListAdapter(new ArrayAdapter(getActivity(),
83 | android.R.layout.simple_list_item_multiple_choice,
84 | android.R.id.text1,
85 | mChoices));
86 | listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
87 |
88 | // Pre-select currently selected items.
89 | new Handler().post(new Runnable() {
90 | @Override
91 | public void run() {
92 | ArrayList selectedItems = mPage.getData().getStringArrayList(
93 | Page.SIMPLE_DATA_KEY);
94 | if (selectedItems == null || selectedItems.size() == 0) {
95 | return;
96 | }
97 |
98 | Set selectedSet = new HashSet(selectedItems);
99 |
100 | for (int i = 0; i < mChoices.size(); i++) {
101 | if (selectedSet.contains(mChoices.get(i))) {
102 | listView.setItemChecked(i, true);
103 | }
104 | }
105 | }
106 | });
107 |
108 | return rootView;
109 | }
110 |
111 | @Override
112 | public void onAttach(Activity activity) {
113 | super.onAttach(activity);
114 |
115 | if (!(activity instanceof PageFragmentCallbacks)) {
116 | throw new ClassCastException("Activity must implement PageFragmentCallbacks");
117 | }
118 |
119 | mCallbacks = (PageFragmentCallbacks) activity;
120 | }
121 |
122 | @Override
123 | public void onDetach() {
124 | super.onDetach();
125 | mCallbacks = null;
126 | }
127 |
128 | @Override
129 | public void onListItemClick(ListView l, View v, int position, long id) {
130 | SparseBooleanArray checkedPositions = getListView().getCheckedItemPositions();
131 | ArrayList selections = new ArrayList();
132 | for (int i = 0; i < checkedPositions.size(); i++) {
133 | if (checkedPositions.valueAt(i)) {
134 | selections.add(getListAdapter().getItem(checkedPositions.keyAt(i)).toString());
135 | }
136 | }
137 |
138 | mPage.getData().putStringArrayList(Page.SIMPLE_DATA_KEY, selections);
139 | mPage.notifyDataChanged();
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/ui/PageFragmentCallbacks.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.ui;
18 |
19 | import com.example.android.wizardpager.wizard.model.Page;
20 |
21 | public interface PageFragmentCallbacks {
22 | Page onGetPage(String key);
23 | }
24 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/ui/ReviewFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.ui;
18 |
19 | import com.example.android.wizardpager.R;
20 | import com.example.android.wizardpager.wizard.model.AbstractWizardModel;
21 | import com.example.android.wizardpager.wizard.model.ModelCallbacks;
22 | import com.example.android.wizardpager.wizard.model.Page;
23 | import com.example.android.wizardpager.wizard.model.ReviewItem;
24 |
25 | import android.app.Activity;
26 | import android.os.Bundle;
27 | import android.support.v4.app.ListFragment;
28 | import android.text.TextUtils;
29 | import android.view.LayoutInflater;
30 | import android.view.View;
31 | import android.view.ViewGroup;
32 | import android.widget.BaseAdapter;
33 | import android.widget.ListView;
34 | import android.widget.TextView;
35 |
36 | import java.util.ArrayList;
37 | import java.util.Collections;
38 | import java.util.Comparator;
39 | import java.util.List;
40 |
41 | public class ReviewFragment extends ListFragment implements ModelCallbacks {
42 | private Callbacks mCallbacks;
43 | private AbstractWizardModel mWizardModel;
44 | private List mCurrentReviewItems;
45 |
46 | private ReviewAdapter mReviewAdapter;
47 |
48 | public ReviewFragment() {
49 | }
50 |
51 | @Override
52 | public void onCreate(Bundle savedInstanceState) {
53 | super.onCreate(savedInstanceState);
54 | mReviewAdapter = new ReviewAdapter();
55 | }
56 |
57 | @Override
58 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
59 | Bundle savedInstanceState) {
60 | View rootView = inflater.inflate(R.layout.fragment_page, container, false);
61 |
62 | TextView titleView = (TextView) rootView.findViewById(android.R.id.title);
63 | titleView.setText(R.string.review);
64 | titleView.setTextColor(getResources().getColor(R.color.step_pager_selected_tab_color));
65 |
66 | ListView listView = (ListView) rootView.findViewById(android.R.id.list);
67 | setListAdapter(mReviewAdapter);
68 | listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
69 | return rootView;
70 | }
71 |
72 | @Override
73 | public void onAttach(Activity activity) {
74 | super.onAttach(activity);
75 |
76 | if (!(activity instanceof Callbacks)) {
77 | throw new ClassCastException("Activity must implement fragment's callbacks");
78 | }
79 |
80 | mCallbacks = (Callbacks) activity;
81 |
82 | mWizardModel = mCallbacks.onGetModel();
83 | mWizardModel.registerListener(this);
84 | onPageTreeChanged();
85 | }
86 |
87 | @Override
88 | public void onPageTreeChanged() {
89 | onPageDataChanged(null);
90 | }
91 |
92 | @Override
93 | public void onDetach() {
94 | super.onDetach();
95 | mCallbacks = null;
96 |
97 | mWizardModel.unregisterListener(this);
98 | }
99 |
100 | @Override
101 | public void onPageDataChanged(Page changedPage) {
102 | ArrayList reviewItems = new ArrayList();
103 | for (Page page : mWizardModel.getCurrentPageSequence()) {
104 | page.getReviewItems(reviewItems);
105 | }
106 | Collections.sort(reviewItems, new Comparator() {
107 | @Override
108 | public int compare(ReviewItem a, ReviewItem b) {
109 | return a.getWeight() > b.getWeight() ? +1 : a.getWeight() < b.getWeight() ? -1 : 0;
110 | }
111 | });
112 | mCurrentReviewItems = reviewItems;
113 |
114 | if (mReviewAdapter != null) {
115 | mReviewAdapter.notifyDataSetInvalidated();
116 | }
117 | }
118 |
119 | @Override
120 | public void onListItemClick(ListView l, View v, int position, long id) {
121 | mCallbacks.onEditScreenAfterReview(mCurrentReviewItems.get(position).getPageKey());
122 | }
123 |
124 | public interface Callbacks {
125 | AbstractWizardModel onGetModel();
126 | void onEditScreenAfterReview(String pageKey);
127 | }
128 |
129 | private class ReviewAdapter extends BaseAdapter {
130 | @Override
131 | public boolean hasStableIds() {
132 | return true;
133 | }
134 |
135 | @Override
136 | public int getItemViewType(int position) {
137 | return 0;
138 | }
139 |
140 | @Override
141 | public int getViewTypeCount() {
142 | return 1;
143 | }
144 |
145 | @Override
146 | public boolean areAllItemsEnabled() {
147 | return true;
148 | }
149 |
150 | @Override
151 | public Object getItem(int position) {
152 | return mCurrentReviewItems.get(position);
153 | }
154 |
155 | @Override
156 | public long getItemId(int position) {
157 | return mCurrentReviewItems.get(position).hashCode();
158 | }
159 |
160 | @Override
161 | public View getView(int position, View view, ViewGroup container) {
162 | LayoutInflater inflater = LayoutInflater.from(getActivity());
163 | View rootView = inflater.inflate(R.layout.list_item_review, container, false);
164 |
165 | ReviewItem reviewItem = mCurrentReviewItems.get(position);
166 | String value = reviewItem.getDisplayValue();
167 | if (TextUtils.isEmpty(value)) {
168 | value = "(None)";
169 | }
170 | ((TextView) rootView.findViewById(android.R.id.text1)).setText(reviewItem.getTitle());
171 | ((TextView) rootView.findViewById(android.R.id.text2)).setText(value);
172 | return rootView;
173 | }
174 |
175 | @Override
176 | public int getCount() {
177 | return mCurrentReviewItems.size();
178 | }
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/ui/SingleChoiceFragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.ui;
18 |
19 | import com.example.android.wizardpager.R;
20 | import com.example.android.wizardpager.wizard.model.Page;
21 | import com.example.android.wizardpager.wizard.model.SingleFixedChoicePage;
22 |
23 | import android.app.Activity;
24 | import android.os.Bundle;
25 | import android.os.Handler;
26 | import android.support.v4.app.ListFragment;
27 | import android.view.LayoutInflater;
28 | import android.view.View;
29 | import android.view.ViewGroup;
30 | import android.widget.ArrayAdapter;
31 | import android.widget.ListView;
32 | import android.widget.TextView;
33 |
34 | import java.util.ArrayList;
35 | import java.util.List;
36 |
37 | public class SingleChoiceFragment extends ListFragment {
38 | private static final String ARG_KEY = "key";
39 |
40 | private PageFragmentCallbacks mCallbacks;
41 | private List mChoices;
42 | private String mKey;
43 | private Page mPage;
44 |
45 | public static SingleChoiceFragment create(String key) {
46 | Bundle args = new Bundle();
47 | args.putString(ARG_KEY, key);
48 |
49 | SingleChoiceFragment fragment = new SingleChoiceFragment();
50 | fragment.setArguments(args);
51 | return fragment;
52 | }
53 |
54 | public SingleChoiceFragment() {
55 | }
56 |
57 | @Override
58 | public void onCreate(Bundle savedInstanceState) {
59 | super.onCreate(savedInstanceState);
60 |
61 | Bundle args = getArguments();
62 | mKey = args.getString(ARG_KEY);
63 | mPage = mCallbacks.onGetPage(mKey);
64 |
65 | SingleFixedChoicePage fixedChoicePage = (SingleFixedChoicePage) mPage;
66 | mChoices = new ArrayList();
67 | for (int i = 0; i < fixedChoicePage.getOptionCount(); i++) {
68 | mChoices.add(fixedChoicePage.getOptionAt(i));
69 | }
70 | }
71 |
72 | @Override
73 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
74 | Bundle savedInstanceState) {
75 | View rootView = inflater.inflate(R.layout.fragment_page, container, false);
76 | ((TextView) rootView.findViewById(android.R.id.title)).setText(mPage.getTitle());
77 |
78 | final ListView listView = (ListView) rootView.findViewById(android.R.id.list);
79 | setListAdapter(new ArrayAdapter(getActivity(),
80 | android.R.layout.simple_list_item_single_choice,
81 | android.R.id.text1,
82 | mChoices));
83 | listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
84 |
85 | // Pre-select currently selected item.
86 | new Handler().post(new Runnable() {
87 | @Override
88 | public void run() {
89 | String selection = mPage.getData().getString(Page.SIMPLE_DATA_KEY);
90 | for (int i = 0; i < mChoices.size(); i++) {
91 | if (mChoices.get(i).equals(selection)) {
92 | listView.setItemChecked(i, true);
93 | break;
94 | }
95 | }
96 | }
97 | });
98 |
99 | return rootView;
100 | }
101 |
102 | @Override
103 | public void onAttach(Activity activity) {
104 | super.onAttach(activity);
105 |
106 | if (!(activity instanceof PageFragmentCallbacks)) {
107 | throw new ClassCastException("Activity must implement PageFragmentCallbacks");
108 | }
109 |
110 | mCallbacks = (PageFragmentCallbacks) activity;
111 | }
112 |
113 | @Override
114 | public void onDetach() {
115 | super.onDetach();
116 | mCallbacks = null;
117 | }
118 |
119 | @Override
120 | public void onListItemClick(ListView l, View v, int position, long id) {
121 | mPage.getData().putString(Page.SIMPLE_DATA_KEY,
122 | getListAdapter().getItem(position).toString());
123 | mPage.notifyDataChanged();
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/com/example/android/wizardpager/wizard/ui/StepPagerStrip.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 Google Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.example.android.wizardpager.wizard.ui;
18 |
19 | import com.example.android.wizardpager.R;
20 |
21 | import android.content.Context;
22 | import android.content.res.Resources;
23 | import android.content.res.TypedArray;
24 | import android.graphics.Canvas;
25 | import android.graphics.Paint;
26 | import android.graphics.RectF;
27 | import android.util.AttributeSet;
28 | import android.view.Gravity;
29 | import android.view.MotionEvent;
30 | import android.view.View;
31 |
32 | public class StepPagerStrip extends View {
33 | private static final int[] ATTRS = new int[]{
34 | android.R.attr.gravity
35 | };
36 | private int mPageCount;
37 | private int mCurrentPage;
38 |
39 | private int mGravity = Gravity.LEFT | Gravity.TOP;
40 | private float mTabWidth;
41 | private float mTabHeight;
42 | private float mTabSpacing;
43 |
44 | private Paint mPrevTabPaint;
45 | private Paint mSelectedTabPaint;
46 | private Paint mSelectedLastTabPaint;
47 | private Paint mNextTabPaint;
48 |
49 | private RectF mTempRectF = new RectF();
50 |
51 | //private Scroller mScroller;
52 |
53 | private OnPageSelectedListener mOnPageSelectedListener;
54 |
55 | public StepPagerStrip(Context context) {
56 | this(context, null, 0);
57 | }
58 |
59 | public StepPagerStrip(Context context, AttributeSet attrs) {
60 | this(context, attrs, 0);
61 | }
62 |
63 | public StepPagerStrip(Context context, AttributeSet attrs, int defStyle) {
64 | super(context, attrs, defStyle);
65 |
66 | final TypedArray a = context.obtainStyledAttributes(attrs, ATTRS);
67 | mGravity = a.getInteger(0, mGravity);
68 | a.recycle();
69 |
70 | final Resources res = getResources();
71 | mTabWidth = res.getDimensionPixelSize(R.dimen.step_pager_tab_width);
72 | mTabHeight = res.getDimensionPixelSize(R.dimen.step_pager_tab_height);
73 | mTabSpacing = res.getDimensionPixelSize(R.dimen.step_pager_tab_spacing);
74 |
75 | mPrevTabPaint = new Paint();
76 | mPrevTabPaint.setColor(res.getColor(R.color.step_pager_previous_tab_color));
77 |
78 | mSelectedTabPaint = new Paint();
79 | mSelectedTabPaint.setColor(res.getColor(R.color.step_pager_selected_tab_color));
80 |
81 | mSelectedLastTabPaint = new Paint();
82 | mSelectedLastTabPaint.setColor(res.getColor(R.color.step_pager_selected_tab_color));
83 |
84 | mNextTabPaint = new Paint();
85 | mNextTabPaint.setColor(res.getColor(R.color.step_pager_next_tab_color));
86 | }
87 |
88 | public void setOnPageSelectedListener(OnPageSelectedListener onPageSelectedListener) {
89 | mOnPageSelectedListener = onPageSelectedListener;
90 | }
91 |
92 | @Override
93 | protected void onDraw(Canvas canvas) {
94 | super.onDraw(canvas);
95 |
96 | if (mPageCount == 0) {
97 | return;
98 | }
99 |
100 | float totalWidth = mPageCount * (mTabWidth + mTabSpacing) - mTabSpacing;
101 | float totalLeft;
102 | boolean fillHorizontal = false;
103 |
104 | switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
105 | case Gravity.CENTER_HORIZONTAL:
106 | totalLeft = (getWidth() - totalWidth) / 2;
107 | break;
108 | case Gravity.RIGHT:
109 | totalLeft = getWidth() - getPaddingRight() - totalWidth;
110 | break;
111 | case Gravity.FILL_HORIZONTAL:
112 | totalLeft = getPaddingLeft();
113 | fillHorizontal = true;
114 | break;
115 | default:
116 | totalLeft = getPaddingLeft();
117 | }
118 |
119 | switch (mGravity & Gravity.VERTICAL_GRAVITY_MASK) {
120 | case Gravity.CENTER_VERTICAL:
121 | mTempRectF.top = (int) (getHeight() - mTabHeight) / 2;
122 | break;
123 | case Gravity.BOTTOM:
124 | mTempRectF.top = getHeight() - getPaddingBottom() - mTabHeight;
125 | break;
126 | default:
127 | mTempRectF.top = getPaddingTop();
128 | }
129 |
130 | mTempRectF.bottom = mTempRectF.top + mTabHeight;
131 |
132 | float tabWidth = mTabWidth;
133 | if (fillHorizontal) {
134 | tabWidth = (getWidth() - getPaddingRight() - getPaddingLeft()
135 | - (mPageCount - 1) * mTabSpacing) / mPageCount;
136 | }
137 |
138 | for (int i = 0; i < mPageCount; i++) {
139 | mTempRectF.left = totalLeft + (i * (tabWidth + mTabSpacing));
140 | mTempRectF.right = mTempRectF.left + tabWidth;
141 | canvas.drawRect(mTempRectF, i < mCurrentPage
142 | ? mPrevTabPaint
143 | : (i > mCurrentPage
144 | ? mNextTabPaint
145 | : (i == mPageCount - 1
146 | ? mSelectedLastTabPaint
147 | : mSelectedTabPaint)));
148 | }
149 | }
150 |
151 | @Override
152 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
153 | setMeasuredDimension(
154 | View.resolveSize(
155 | (int) (mPageCount * (mTabWidth + mTabSpacing) - mTabSpacing)
156 | + getPaddingLeft() + getPaddingRight(),
157 | widthMeasureSpec),
158 | View.resolveSize(
159 | (int) mTabHeight
160 | + getPaddingTop() + getPaddingBottom(),
161 | heightMeasureSpec));
162 | }
163 |
164 | @Override
165 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
166 | scrollCurrentPageIntoView();
167 | super.onSizeChanged(w, h, oldw, oldh);
168 | }
169 |
170 | @Override
171 | public boolean onTouchEvent(MotionEvent event) {
172 | if (mOnPageSelectedListener != null) {
173 | switch (event.getActionMasked()) {
174 | case MotionEvent.ACTION_DOWN:
175 | case MotionEvent.ACTION_MOVE:
176 | int position = hitTest(event.getX());
177 | if (position >= 0) {
178 | mOnPageSelectedListener.onPageStripSelected(position);
179 | }
180 | return true;
181 | }
182 | }
183 | return super.onTouchEvent(event);
184 | }
185 |
186 | private int hitTest(float x) {
187 | if (mPageCount == 0) {
188 | return -1;
189 | }
190 |
191 | float totalWidth = mPageCount * (mTabWidth + mTabSpacing) - mTabSpacing;
192 | float totalLeft;
193 | boolean fillHorizontal = false;
194 |
195 | switch (mGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
196 | case Gravity.CENTER_HORIZONTAL:
197 | totalLeft = (getWidth() - totalWidth) / 2;
198 | break;
199 | case Gravity.RIGHT:
200 | totalLeft = getWidth() - getPaddingRight() - totalWidth;
201 | break;
202 | case Gravity.FILL_HORIZONTAL:
203 | totalLeft = getPaddingLeft();
204 | fillHorizontal = true;
205 | break;
206 | default:
207 | totalLeft = getPaddingLeft();
208 | }
209 |
210 | float tabWidth = mTabWidth;
211 | if (fillHorizontal) {
212 | tabWidth = (getWidth() - getPaddingRight() - getPaddingLeft()
213 | - (mPageCount - 1) * mTabSpacing) / mPageCount;
214 | }
215 |
216 | float totalRight = totalLeft + (mPageCount * (tabWidth + mTabSpacing));
217 | if (x >= totalLeft && x <= totalRight && totalRight > totalLeft) {
218 | return (int) (((x - totalLeft) / (totalRight - totalLeft)) * mPageCount);
219 | } else {
220 | return -1;
221 | }
222 | }
223 |
224 | public void setCurrentPage(int currentPage) {
225 | mCurrentPage = currentPage;
226 | invalidate();
227 | scrollCurrentPageIntoView();
228 |
229 | // TODO: Set content description appropriately
230 | }
231 |
232 | private void scrollCurrentPageIntoView() {
233 | // TODO: only works with left gravity for now
234 | //
235 | // float widthToActive = getPaddingLeft() + (mCurrentPage + 1) * (mTabWidth + mTabSpacing)
236 | // - mTabSpacing;
237 | // int viewWidth = getWidth();
238 | //
239 | // int startScrollX = getScrollX();
240 | // int destScrollX = (widthToActive > viewWidth) ? (int) (widthToActive - viewWidth) : 0;
241 | //
242 | // if (mScroller == null) {
243 | // mScroller = new Scroller(getContext());
244 | // }
245 | //
246 | // mScroller.abortAnimation();
247 | // mScroller.startScroll(startScrollX, 0, destScrollX - startScrollX, 0);
248 | // postInvalidate();
249 | }
250 |
251 | public void setPageCount(int count) {
252 | mPageCount = count;
253 | invalidate();
254 |
255 | // TODO: Set content description appropriately
256 | }
257 |
258 | public static interface OnPageSelectedListener {
259 | void onPageStripSelected(int position);
260 | }
261 |
262 | //
263 | // @Override
264 | // public void computeScroll() {
265 | // super.computeScroll();
266 | // if (mScroller.computeScrollOffset()) {
267 | // setScrollX(mScroller.getCurrX());
268 | // }
269 | // }
270 | }
271 |
--------------------------------------------------------------------------------