├── .gitignore ├── .idea ├── (2).name ├── .name ├── compiler (2).xml ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings (2).xml ├── encodings.xml ├── gradle.xml ├── misc (2).xml ├── misc.xml ├── modules (2).xml ├── modules.xml ├── scopes │ └── scope_settings.xml ├── vcs (2).xml ├── vcs.xml └── workspace (2).xml ├── Android-Material-Wizard-Drawer.iml ├── README.md ├── app ├── .gitignore ├── app.iml ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── iftw │ │ └── materialnavigation │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── iftw │ │ └── materialnavigation │ │ ├── HealthIssueFragment.java │ │ ├── MainActivity.java │ │ ├── drawer │ │ ├── NavigationDrawerAdapter.java │ │ ├── NavigationDrawerCallbacks.java │ │ ├── NavigationDrawerFragment.java │ │ └── NavigationItem.java │ │ ├── service │ │ └── InterfaceMapping.java │ │ └── wizard │ │ ├── PresentWizardModel.java │ │ ├── model │ │ ├── AbstractWizardModel.java │ │ ├── BranchPage.java │ │ ├── CustomerInfoPage.java │ │ ├── ModelCallbacks.java │ │ ├── MultipleFixedChoicePage.java │ │ ├── Page.java │ │ ├── PageList.java │ │ ├── PageTreeNode.java │ │ ├── ReviewItem.java │ │ └── SingleFixedChoicePage.java │ │ └── ui │ │ ├── CustomerInfoFragment.java │ │ ├── MultipleChoiceFragment.java │ │ ├── PageFragmentCallbacks.java │ │ ├── PresentWizardModel.java │ │ ├── ReviewFragment.java │ │ ├── SingleChoiceFragment.java │ │ └── StepPagerStrip.java │ └── res │ ├── drawable-hdpi │ └── ic_menu_check.png │ ├── drawable-mdpi │ └── ic_menu_check.png │ ├── drawable-xhdpi │ └── ic_menu_check.png │ ├── drawable-xxhdpi │ ├── ic_menu_check.png │ └── selectable_item_background.xml │ ├── drawable │ ├── avatar.png │ ├── row_selector.xml │ └── wallpaper.png │ ├── layout │ ├── activity_main.xml │ ├── activity_report_health.xml │ ├── drawer_row.xml │ ├── fragment_main.xml │ ├── fragment_navigation_drawer.xml │ ├── fragment_page.xml │ ├── fragment_page_customer_info.xml │ ├── list_item_review.xml │ └── toolbar_default.xml │ ├── menu │ └── main.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── values-v21 │ └── styles.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | /local.properties 3 | /.idea/workspace.xml 4 | /.idea/libraries 5 | .DS_Store 6 | /build 7 | -------------------------------------------------------------------------------- /.idea/ (2).name: -------------------------------------------------------------------------------- 1 | MaterialNavigation -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | Android-Material-Wizard-Drawer -------------------------------------------------------------------------------- /.idea/compiler (2).xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings (2).xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc (2).xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Abstraction issues 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 47 | 48 | 49 | 67 | 74 | 75 | 88 | 89 | 90 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 112 | 113 | localhost 114 | 5050 115 | 116 | 117 | 118 | 119 | 120 | 121 | Android API 15 Platform 122 | 123 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Abstraction issues 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 47 | 48 | 49 | 67 | 74 | 75 | 88 | 89 | 90 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 112 | 113 | localhost 114 | 5050 115 | 116 | 117 | 118 | 119 | 120 | 121 | 1.7 122 | 123 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /.idea/modules (2).xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/scopes/scope_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs (2).xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Android-Material-Wizard-Drawer.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android Material Wizard Drawer 2 | An Android template with a Material wizard and a Material navigation drawer. 3 | 4 | 5 | ![Material Navigation GIF](http://i.imgur.com/D9e6Qbw.gif) 6 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/app.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | applicationId "com.iftw.materialnavigation" 9 | minSdkVersion 14 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | compile 'com.android.support:appcompat-v7:22.0.0' 25 | compile 'com.android.support:support-v4:22.0.0' 26 | compile 'com.android.support:recyclerview-v7:22.0.0' 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\MOS182\Documents\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/iftw/materialnavigation/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.iftw.materialnavigation; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/HealthIssueFragment.java: -------------------------------------------------------------------------------- 1 | package com.iftw.materialnavigation; 2 | 3 | 4 | import android.app.Activity; 5 | import android.app.AlertDialog; 6 | import android.app.Dialog; 7 | import android.os.Bundle; 8 | import android.support.v4.app.DialogFragment; 9 | import android.support.v4.app.Fragment; 10 | import android.support.v4.app.FragmentManager; 11 | import android.support.v4.app.FragmentStatePagerAdapter; 12 | import android.support.v4.app.ListFragment; 13 | import android.support.v4.view.ViewPager; 14 | import android.view.LayoutInflater; 15 | import android.view.View; 16 | import android.view.ViewGroup; 17 | import android.widget.Button; 18 | 19 | import com.iftw.materialnavigation.service.InterfaceMapping; 20 | import com.iftw.materialnavigation.wizard.PresentWizardModel; 21 | import com.iftw.materialnavigation.wizard.model.AbstractWizardModel; 22 | import com.iftw.materialnavigation.wizard.model.ModelCallbacks; 23 | import com.iftw.materialnavigation.wizard.model.Page; 24 | import com.iftw.materialnavigation.wizard.ui.PageFragmentCallbacks; 25 | import com.iftw.materialnavigation.wizard.ui.ReviewFragment; 26 | import com.iftw.materialnavigation.wizard.ui.StepPagerStrip; 27 | 28 | import java.util.List; 29 | 30 | /** 31 | * A simple {@link Fragment} subclass. 32 | */ 33 | public class HealthIssueFragment extends Fragment implements 34 | PageFragmentCallbacks, 35 | ReviewFragment.Callbacks, 36 | ModelCallbacks { 37 | 38 | private ViewPager mPager; 39 | private MyPagerAdapter mPagerAdapter; 40 | 41 | private boolean mEditingAfterReview; 42 | 43 | private AbstractWizardModel mWizardModel = new PresentWizardModel(getActivity()); 44 | 45 | private boolean mConsumePageSelectedEvent; 46 | 47 | private Button mNextButton; 48 | private Button mPrevButton; 49 | 50 | private List mCurrentPageSequence; 51 | private StepPagerStrip mStepPagerStrip; 52 | 53 | public HealthIssueFragment() { 54 | // Required empty public constructor 55 | InterfaceMapping.getInstance().setFragment(this); 56 | } 57 | 58 | 59 | MainActivity activity; 60 | @Override 61 | public void onAttach(Activity activity) { 62 | this.activity = (MainActivity)activity; 63 | super.onAttach(activity); 64 | } 65 | 66 | @Override 67 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 68 | Bundle savedInstanceState) { 69 | View view = inflater.inflate(R.layout.activity_report_health, null); 70 | 71 | if (savedInstanceState != null) { 72 | mWizardModel.load(savedInstanceState.getBundle("model")); 73 | } 74 | 75 | mWizardModel.registerListener(this); 76 | 77 | mPagerAdapter = new MyPagerAdapter(activity.getSupportFragmentManager()); 78 | mPager = (ViewPager) view.findViewById(R.id.pager); 79 | mPager.setAdapter(mPagerAdapter); 80 | mStepPagerStrip = (StepPagerStrip) view.findViewById(R.id.strip); 81 | mStepPagerStrip.setOnPageSelectedListener(new StepPagerStrip.OnPageSelectedListener() { 82 | @Override 83 | public void onPageStripSelected(int position) { 84 | position = Math.min(mPagerAdapter.getCount() - 1, position); 85 | if (mPager.getCurrentItem() != position) { 86 | mPager.setCurrentItem(position); 87 | } 88 | } 89 | }); 90 | 91 | mNextButton = (Button) view.findViewById(R.id.next_button); 92 | mPrevButton = (Button) view.findViewById(R.id.prev_button); 93 | 94 | mPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { 95 | @Override 96 | public void onPageSelected(int position) { 97 | mStepPagerStrip.setCurrentPage(position); 98 | 99 | if (mConsumePageSelectedEvent) { 100 | mConsumePageSelectedEvent = false; 101 | return; 102 | } 103 | 104 | mEditingAfterReview = false; 105 | updateBottomBar(); 106 | } 107 | }); 108 | 109 | mNextButton.setOnClickListener(new View.OnClickListener() { 110 | @Override 111 | public void onClick(View view) { 112 | if (mPager.getCurrentItem() == mCurrentPageSequence.size()) { 113 | DialogFragment dg = new DialogFragment() { 114 | @Override 115 | public Dialog onCreateDialog(Bundle savedInstanceState) { 116 | return new AlertDialog.Builder(getActivity()) 117 | .setMessage("Are you happy with your choices") 118 | .setPositiveButton("Yes", null) 119 | .setNegativeButton("No", null) 120 | .create(); 121 | } 122 | }; 123 | dg.show(activity.getSupportFragmentManager(), "place_order_dialog"); 124 | } else { 125 | if (mEditingAfterReview) { 126 | mPager.setCurrentItem(mPagerAdapter.getCount() - 1); 127 | } else { 128 | mPager.setCurrentItem(mPager.getCurrentItem() + 1); 129 | } 130 | } 131 | } 132 | }); 133 | 134 | mPrevButton.setOnClickListener(new View.OnClickListener() { 135 | @Override 136 | public void onClick(View view) { 137 | mPager.setCurrentItem(mPager.getCurrentItem() - 1); 138 | } 139 | }); 140 | 141 | onPageTreeChanged(); 142 | updateBottomBar(); 143 | 144 | return view; 145 | } 146 | 147 | @Override 148 | public void onPageTreeChanged() { 149 | mCurrentPageSequence = mWizardModel.getCurrentPageSequence(); 150 | recalculateCutOffPage(); 151 | mStepPagerStrip.setPageCount(mCurrentPageSequence.size() + 1); // + 1 = review step 152 | mPagerAdapter.notifyDataSetChanged(); 153 | updateBottomBar(); 154 | } 155 | 156 | private void updateBottomBar() { 157 | int position = mPager.getCurrentItem(); 158 | if (position == mCurrentPageSequence.size()) { 159 | mNextButton.setText("Submit"); 160 | } else { 161 | mNextButton.setText(mEditingAfterReview 162 | ? "Review" 163 | : "Next"); 164 | } 165 | 166 | mPrevButton.setVisibility(position <= 0 ? View.INVISIBLE : View.VISIBLE); 167 | } 168 | 169 | @Override 170 | public void onDestroy() { 171 | super.onDestroy(); 172 | mWizardModel.unregisterListener(this); 173 | } 174 | 175 | @Override 176 | public void onSaveInstanceState(Bundle outState) { 177 | super.onSaveInstanceState(outState); 178 | outState.putBundle("model", mWizardModel.save()); 179 | } 180 | 181 | @Override 182 | public AbstractWizardModel onGetModel() { 183 | return mWizardModel; 184 | } 185 | 186 | @Override 187 | public void onEditScreenAfterReview(String key) { 188 | for (int i = mCurrentPageSequence.size() - 1; i >= 0; i--) { 189 | if (mCurrentPageSequence.get(i).getKey().equals(key)) { 190 | mConsumePageSelectedEvent = true; 191 | mEditingAfterReview = true; 192 | mPager.setCurrentItem(i); 193 | updateBottomBar(); 194 | break; 195 | } 196 | } 197 | } 198 | 199 | @Override 200 | public void onPageDataChanged(Page page) { 201 | if (page.isRequired()) { 202 | if (recalculateCutOffPage()) { 203 | mPagerAdapter.notifyDataSetChanged(); 204 | updateBottomBar(); 205 | } 206 | } 207 | } 208 | 209 | @Override 210 | public Page onGetPage(String key) { 211 | return mWizardModel.findByKey(key); 212 | } 213 | 214 | private boolean recalculateCutOffPage() { 215 | // Cut off the pager adapter at first required page that isn't completed 216 | int cutOffPage = mCurrentPageSequence.size() + 1; 217 | for (int i = 0; i < mCurrentPageSequence.size(); i++) { 218 | Page page = mCurrentPageSequence.get(i); 219 | if (page.isRequired() && !page.isCompleted()) { 220 | cutOffPage = i; 221 | break; 222 | } 223 | } 224 | 225 | if (mPagerAdapter.getCutOffPage() != cutOffPage) { 226 | mPagerAdapter.setCutOffPage(cutOffPage); 227 | return true; 228 | } 229 | 230 | return false; 231 | } 232 | 233 | public class MyPagerAdapter extends FragmentStatePagerAdapter { 234 | private int mCutOffPage; 235 | private Fragment mPrimaryItem; 236 | 237 | public MyPagerAdapter(FragmentManager fm) { 238 | super(fm); 239 | } 240 | 241 | @Override 242 | public ListFragment getItem(int i) { 243 | if (i >= mCurrentPageSequence.size()) { 244 | return new ReviewFragment(); 245 | } 246 | 247 | return mCurrentPageSequence.get(i).createFragment(); 248 | } 249 | 250 | @Override 251 | public int getItemPosition(Object object) { 252 | // TODO: be smarter about this 253 | if (object == mPrimaryItem) { 254 | // Re-use the current fragment (its position never changes) 255 | return POSITION_UNCHANGED; 256 | } 257 | 258 | return POSITION_NONE; 259 | } 260 | 261 | @Override 262 | public void setPrimaryItem(ViewGroup container, int position, Object object) { 263 | super.setPrimaryItem(container, position, object); 264 | mPrimaryItem = (Fragment) object; 265 | } 266 | 267 | @Override 268 | public int getCount() { 269 | if (mCurrentPageSequence == null) { 270 | return 0; 271 | } 272 | return Math.min(mCutOffPage + 1, mCurrentPageSequence.size() + 1); 273 | } 274 | 275 | public void setCutOffPage(int cutOffPage) { 276 | if (cutOffPage < 0) { 277 | cutOffPage = Integer.MAX_VALUE; 278 | } 279 | mCutOffPage = cutOffPage; 280 | } 281 | 282 | public int getCutOffPage() { 283 | return mCutOffPage; 284 | } 285 | } 286 | 287 | } 288 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.iftw.materialnavigation; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.v4.app.Fragment; 6 | import android.support.v4.widget.DrawerLayout; 7 | import android.support.v7.app.ActionBarActivity; 8 | import android.support.v7.widget.Toolbar; 9 | import android.view.LayoutInflater; 10 | import android.view.Menu; 11 | import android.view.MenuItem; 12 | import android.view.View; 13 | import android.view.ViewGroup; 14 | import android.widget.Toast; 15 | import android.support.v4.app.FragmentManager; 16 | 17 | import com.iftw.materialnavigation.drawer.NavigationDrawerCallbacks; 18 | import com.iftw.materialnavigation.drawer.NavigationDrawerFragment; 19 | 20 | 21 | public class MainActivity extends ActionBarActivity 22 | implements NavigationDrawerCallbacks { 23 | 24 | /** 25 | * Fragment managing the behaviors, interactions and presentation of the navigation drawer. 26 | */ 27 | private NavigationDrawerFragment mNavigationDrawerFragment; 28 | private Toolbar mToolbar; 29 | private CharSequence mTitle; 30 | 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_main); 35 | mToolbar = (Toolbar) findViewById(R.id.toolbar_actionbar); 36 | setSupportActionBar(mToolbar); 37 | 38 | mNavigationDrawerFragment = (NavigationDrawerFragment) 39 | getFragmentManager().findFragmentById(R.id.fragment_drawer); 40 | 41 | // Set up the drawer. 42 | mNavigationDrawerFragment.setup(R.id.fragment_drawer, (DrawerLayout) findViewById(R.id.drawer), mToolbar); 43 | } 44 | 45 | @Override 46 | public void onNavigationDrawerItemSelected(int position) { 47 | // update the main content by replacing fragments 48 | Toast.makeText(this, "Menu item selected -> " + position, Toast.LENGTH_SHORT).show(); 49 | 50 | Fragment fragmentToReplace = PlaceholderFragment.newInstance(position + 1); 51 | switch(position){ 52 | case 0: 53 | // Report Health Issue 54 | fragmentToReplace = new HealthIssueFragment(); 55 | break; 56 | case 1: 57 | // Profile Fragment 58 | break; 59 | case 2: 60 | // Instructions 61 | break; 62 | 63 | } 64 | FragmentManager fragmentManager = getSupportFragmentManager(); 65 | fragmentManager.beginTransaction() 66 | .replace(R.id.container, fragmentToReplace) 67 | .commit(); 68 | } 69 | 70 | public void onSectionAttached(int number) { 71 | switch (number) { 72 | case 1: 73 | mTitle = "Report Health Issue"; 74 | break; 75 | case 2: 76 | mTitle = "Profile"; 77 | break; 78 | case 3: 79 | mTitle = "Tutorial"; 80 | break; 81 | } 82 | } 83 | 84 | 85 | @Override 86 | public void onBackPressed() { 87 | if (mNavigationDrawerFragment.isDrawerOpen()) 88 | mNavigationDrawerFragment.closeDrawer(); 89 | else 90 | super.onBackPressed(); 91 | } 92 | 93 | 94 | @Override 95 | public boolean onCreateOptionsMenu(Menu menu) { 96 | if (!mNavigationDrawerFragment.isDrawerOpen()) { 97 | // Only show items in the action bar relevant to this screen 98 | // if the drawer is not showing. Otherwise, let the drawer 99 | // decide what to show in the action bar. 100 | getMenuInflater().inflate(R.menu.main, menu); 101 | return true; 102 | } 103 | return super.onCreateOptionsMenu(menu); 104 | } 105 | 106 | 107 | @Override 108 | public boolean onOptionsItemSelected(MenuItem item) { 109 | // Handle action bar item clicks here. The action bar will 110 | // automatically handle clicks on the Home/Up button, so long 111 | // as you specify a parent activity in AndroidManifest.xml. 112 | int id = item.getItemId(); 113 | 114 | //noinspection SimplifiableIfStatement 115 | if (id == R.id.action_settings) { 116 | return true; 117 | } 118 | 119 | return super.onOptionsItemSelected(item); 120 | } 121 | 122 | /** 123 | * A placeholder fragment containing a simple view. 124 | */ 125 | public static class PlaceholderFragment extends Fragment { 126 | /** 127 | * The fragment argument representing the section number for this 128 | * fragment. 129 | */ 130 | private static final String ARG_SECTION_NUMBER = "section_number"; 131 | 132 | /** 133 | * Returns a new instance of this fragment for the given section 134 | * number. 135 | */ 136 | public static PlaceholderFragment newInstance(int sectionNumber) { 137 | PlaceholderFragment fragment = new PlaceholderFragment(); 138 | Bundle args = new Bundle(); 139 | args.putInt(ARG_SECTION_NUMBER, sectionNumber); 140 | fragment.setArguments(args); 141 | return fragment; 142 | } 143 | 144 | public PlaceholderFragment() { 145 | } 146 | 147 | @Override 148 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 149 | Bundle savedInstanceState) { 150 | View rootView = inflater.inflate(R.layout.fragment_main, container, false); 151 | return rootView; 152 | } 153 | 154 | @Override 155 | public void onAttach(Activity activity) { 156 | super.onAttach(activity); 157 | ((MainActivity) activity).onSectionAttached( 158 | getArguments().getInt(ARG_SECTION_NUMBER)); 159 | } 160 | } 161 | 162 | } 163 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/drawer/NavigationDrawerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.iftw.materialnavigation.drawer; 2 | 3 | 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import com.iftw.materialnavigation.R; 11 | 12 | import java.util.List; 13 | 14 | 15 | public class NavigationDrawerAdapter extends RecyclerView.Adapter { 16 | 17 | private List mData; 18 | private NavigationDrawerCallbacks mNavigationDrawerCallbacks; 19 | private View mSelectedView; 20 | private int mSelectedPosition; 21 | 22 | public NavigationDrawerAdapter(List data) { 23 | mData = data; 24 | } 25 | 26 | public NavigationDrawerCallbacks getNavigationDrawerCallbacks() { 27 | return mNavigationDrawerCallbacks; 28 | } 29 | 30 | public void setNavigationDrawerCallbacks(NavigationDrawerCallbacks navigationDrawerCallbacks) { 31 | mNavigationDrawerCallbacks = navigationDrawerCallbacks; 32 | } 33 | 34 | @Override 35 | public NavigationDrawerAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 36 | View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.drawer_row, viewGroup, false); 37 | final ViewHolder viewHolder = new ViewHolder(v); 38 | viewHolder.itemView.setClickable(true); 39 | viewHolder.itemView.setOnClickListener(new View.OnClickListener() { 40 | @Override 41 | public void onClick(View v) { 42 | if (mSelectedView != null) { 43 | mSelectedView.setSelected(false); 44 | } 45 | mSelectedPosition = viewHolder.getAdapterPosition(); 46 | v.setSelected(true); 47 | mSelectedView = v; 48 | if (mNavigationDrawerCallbacks != null) 49 | mNavigationDrawerCallbacks.onNavigationDrawerItemSelected(viewHolder.getAdapterPosition()); 50 | } 51 | } 52 | ); 53 | viewHolder.itemView.setBackgroundResource(R.drawable.row_selector); 54 | return viewHolder; 55 | } 56 | 57 | @Override 58 | public void onBindViewHolder(NavigationDrawerAdapter.ViewHolder viewHolder, int i) { 59 | viewHolder.textView.setText(mData.get(i).getText()); 60 | viewHolder.textView.setCompoundDrawablesWithIntrinsicBounds(mData.get(i).getDrawable(), null, null, null); 61 | if (mSelectedPosition == i) { 62 | if (mSelectedView != null) { 63 | mSelectedView.setSelected(false); 64 | } 65 | mSelectedPosition = i; 66 | mSelectedView = viewHolder.itemView; 67 | mSelectedView.setSelected(true); 68 | } 69 | } 70 | 71 | 72 | public void selectPosition(int position) { 73 | mSelectedPosition = position; 74 | notifyItemChanged(position); 75 | } 76 | 77 | @Override 78 | public int getItemCount() { 79 | return mData != null ? mData.size() : 0; 80 | } 81 | 82 | public static class ViewHolder extends RecyclerView.ViewHolder { 83 | public TextView textView; 84 | 85 | public ViewHolder(View itemView) { 86 | super(itemView); 87 | textView = (TextView) itemView.findViewById(R.id.item_name); 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/drawer/NavigationDrawerCallbacks.java: -------------------------------------------------------------------------------- 1 | package com.iftw.materialnavigation.drawer; 2 | 3 | public interface NavigationDrawerCallbacks { 4 | void onNavigationDrawerItemSelected(int position); 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/drawer/NavigationDrawerFragment.java: -------------------------------------------------------------------------------- 1 | package com.iftw.materialnavigation.drawer; 2 | 3 | import android.app.Activity; 4 | import android.app.Fragment; 5 | import android.content.SharedPreferences; 6 | import android.content.res.Configuration; 7 | import android.os.Bundle; 8 | import android.preference.PreferenceManager; 9 | import android.support.v7.app.ActionBarDrawerToggle; 10 | import android.support.v4.widget.DrawerLayout; 11 | import android.support.v7.widget.LinearLayoutManager; 12 | import android.support.v7.widget.RecyclerView; 13 | import android.support.v7.widget.Toolbar; 14 | import android.view.LayoutInflater; 15 | import android.view.View; 16 | import android.view.ViewGroup; 17 | 18 | import com.iftw.materialnavigation.R; 19 | 20 | import java.util.ArrayList; 21 | import java.util.List; 22 | 23 | /** 24 | * Fragment used for managing interactions for and presentation of a navigation drawer. 25 | * See the 26 | * design guidelines for a complete explanation of the behaviors implemented here. 27 | */ 28 | public class NavigationDrawerFragment extends Fragment implements NavigationDrawerCallbacks { 29 | 30 | /** 31 | * Remember the position of the selected item. 32 | */ 33 | private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position"; 34 | 35 | /** 36 | * Per the design guidelines, you should show the drawer on launch until the user manually 37 | * expands it. This shared preference tracks this. 38 | */ 39 | private static final String PREF_USER_LEARNED_DRAWER = "navigation_drawer_learned"; 40 | 41 | /** 42 | * A pointer to the current callbacks instance (the Activity). 43 | */ 44 | private NavigationDrawerCallbacks mCallbacks; 45 | 46 | /** 47 | * Helper component that ties the action bar to the navigation drawer. 48 | */ 49 | private ActionBarDrawerToggle mActionBarDrawerToggle; 50 | 51 | private DrawerLayout mDrawerLayout; 52 | private RecyclerView mDrawerList; 53 | private View mFragmentContainerView; 54 | 55 | private int mCurrentSelectedPosition = 0; 56 | private boolean mFromSavedInstanceState; 57 | private boolean mUserLearnedDrawer; 58 | 59 | @Override 60 | public void onCreate(Bundle savedInstanceState) { 61 | super.onCreate(savedInstanceState); 62 | 63 | // Read in the flag indicating whether or not the user has demonstrated awareness of the 64 | // drawer. See PREF_USER_LEARNED_DRAWER for details. 65 | SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); 66 | mUserLearnedDrawer = sp.getBoolean(PREF_USER_LEARNED_DRAWER, false); 67 | 68 | if (savedInstanceState != null) { 69 | mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION); 70 | mFromSavedInstanceState = true; 71 | } 72 | } 73 | 74 | @Override 75 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 76 | Bundle savedInstanceState) { 77 | View view = inflater.inflate(R.layout.fragment_navigation_drawer, container, false); 78 | mDrawerList = (RecyclerView) view.findViewById(R.id.drawerList); 79 | LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); 80 | layoutManager.setOrientation(LinearLayoutManager.VERTICAL); 81 | mDrawerList.setLayoutManager(layoutManager); 82 | mDrawerList.setHasFixedSize(true); 83 | 84 | final List navigationItems = getMenu(); 85 | NavigationDrawerAdapter adapter = new NavigationDrawerAdapter(navigationItems); 86 | adapter.setNavigationDrawerCallbacks(this); 87 | mDrawerList.setAdapter(adapter); 88 | selectItem(mCurrentSelectedPosition); 89 | return view; 90 | } 91 | 92 | public boolean isDrawerOpen() { 93 | return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView); 94 | } 95 | 96 | public ActionBarDrawerToggle getActionBarDrawerToggle() { 97 | return mActionBarDrawerToggle; 98 | } 99 | 100 | public DrawerLayout getDrawerLayout() { 101 | return mDrawerLayout; 102 | } 103 | 104 | @Override 105 | public void onNavigationDrawerItemSelected(int position) { 106 | selectItem(position); 107 | } 108 | 109 | public List getMenu() { 110 | List items = new ArrayList(); 111 | items.add(new NavigationItem("item 1", getResources().getDrawable(R.drawable.ic_menu_check))); 112 | items.add(new NavigationItem("item 2", getResources().getDrawable(R.drawable.ic_menu_check))); 113 | items.add(new NavigationItem("item 3", getResources().getDrawable(R.drawable.ic_menu_check))); 114 | return items; 115 | } 116 | 117 | /** 118 | * Users of this fragment must call this method to set up the navigation drawer interactions. 119 | * 120 | * @param fragmentId The android:id of this fragment in its activity's layout. 121 | * @param drawerLayout The DrawerLayout containing this fragment's UI. 122 | * @param toolbar The Toolbar of the activity. 123 | */ 124 | public void setup(int fragmentId, DrawerLayout drawerLayout, Toolbar toolbar) { 125 | mFragmentContainerView = getActivity().findViewById(fragmentId); 126 | mDrawerLayout = drawerLayout; 127 | 128 | mDrawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.myPrimaryDarkColor)); 129 | 130 | mActionBarDrawerToggle = new ActionBarDrawerToggle(getActivity(), mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) { 131 | @Override 132 | public void onDrawerClosed(View drawerView) { 133 | super.onDrawerClosed(drawerView); 134 | if (!isAdded()) return; 135 | 136 | getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu() 137 | } 138 | 139 | @Override 140 | public void onDrawerOpened(View drawerView) { 141 | super.onDrawerOpened(drawerView); 142 | if (!isAdded()) return; 143 | if (!mUserLearnedDrawer) { 144 | mUserLearnedDrawer = true; 145 | SharedPreferences sp = PreferenceManager 146 | .getDefaultSharedPreferences(getActivity()); 147 | sp.edit().putBoolean(PREF_USER_LEARNED_DRAWER, true).apply(); 148 | } 149 | getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu() 150 | } 151 | }; 152 | 153 | // If the user hasn't 'learned' about the drawer, open it to introduce them to the drawer, 154 | // per the navigation drawer design guidelines. 155 | if (!mUserLearnedDrawer && !mFromSavedInstanceState) { 156 | mDrawerLayout.openDrawer(mFragmentContainerView); 157 | } 158 | 159 | // Defer code dependent on restoration of previous instance state. 160 | mDrawerLayout.post(new Runnable() { 161 | @Override 162 | public void run() { 163 | mActionBarDrawerToggle.syncState(); 164 | } 165 | }); 166 | 167 | mDrawerLayout.setDrawerListener(mActionBarDrawerToggle); 168 | } 169 | 170 | private void selectItem(int position) { 171 | mCurrentSelectedPosition = position; 172 | if (mDrawerLayout != null) { 173 | mDrawerLayout.closeDrawer(mFragmentContainerView); 174 | } 175 | if (mCallbacks != null) { 176 | mCallbacks.onNavigationDrawerItemSelected(position); 177 | } 178 | ((NavigationDrawerAdapter) mDrawerList.getAdapter()).selectPosition(position); 179 | } 180 | 181 | public void openDrawer() { 182 | mDrawerLayout.openDrawer(mFragmentContainerView); 183 | } 184 | 185 | public void closeDrawer() { 186 | mDrawerLayout.closeDrawer(mFragmentContainerView); 187 | } 188 | 189 | @Override 190 | public void onAttach(Activity activity) { 191 | super.onAttach(activity); 192 | try { 193 | mCallbacks = (NavigationDrawerCallbacks) activity; 194 | } catch (ClassCastException e) { 195 | throw new ClassCastException("Activity must implement NavigationDrawerCallbacks."); 196 | } 197 | } 198 | 199 | @Override 200 | public void onDetach() { 201 | super.onDetach(); 202 | mCallbacks = null; 203 | } 204 | 205 | @Override 206 | public void onSaveInstanceState(Bundle outState) { 207 | super.onSaveInstanceState(outState); 208 | outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition); 209 | } 210 | 211 | @Override 212 | public void onConfigurationChanged(Configuration newConfig) { 213 | super.onConfigurationChanged(newConfig); 214 | // Forward the new configuration the drawer toggle component. 215 | mActionBarDrawerToggle.onConfigurationChanged(newConfig); 216 | } 217 | 218 | } 219 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/drawer/NavigationItem.java: -------------------------------------------------------------------------------- 1 | package com.iftw.materialnavigation.drawer; 2 | 3 | 4 | import android.graphics.drawable.Drawable; 5 | 6 | /** 7 | * Created by poliveira on 24/10/2014. 8 | */ 9 | public class NavigationItem { 10 | private String mText; 11 | private Drawable mDrawable; 12 | 13 | public NavigationItem(String text, Drawable drawable) { 14 | mText = text; 15 | mDrawable = drawable; 16 | } 17 | 18 | public String getText() { 19 | return mText; 20 | } 21 | 22 | public void setText(String text) { 23 | mText = text; 24 | } 25 | 26 | public Drawable getDrawable() { 27 | return mDrawable; 28 | } 29 | 30 | public void setDrawable(Drawable drawable) { 31 | mDrawable = drawable; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/service/InterfaceMapping.java: -------------------------------------------------------------------------------- 1 | package com.iftw.materialnavigation.service; 2 | 3 | import com.iftw.materialnavigation.HealthIssueFragment; 4 | 5 | /** 6 | * Created by Petronela on 4/11/2015. 7 | */ 8 | public class InterfaceMapping { 9 | private static InterfaceMapping instance; 10 | private HealthIssueFragment fragment; 11 | 12 | private InterfaceMapping() { 13 | 14 | } 15 | 16 | public static InterfaceMapping getInstance() { 17 | if (instance == null) 18 | instance = new InterfaceMapping(); 19 | return instance; 20 | } 21 | 22 | public void setFragment(HealthIssueFragment fragment) { 23 | this.fragment = fragment; 24 | } 25 | 26 | public HealthIssueFragment getFragment() { 27 | return fragment; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/wizard/PresentWizardModel.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.iftw.materialnavigation.wizard; 18 | 19 | import android.content.Context; 20 | 21 | import com.iftw.materialnavigation.wizard.model.AbstractWizardModel; 22 | import com.iftw.materialnavigation.wizard.model.BranchPage; 23 | import com.iftw.materialnavigation.wizard.model.MultipleFixedChoicePage; 24 | import com.iftw.materialnavigation.wizard.model.PageList; 25 | import com.iftw.materialnavigation.wizard.model.SingleFixedChoicePage; 26 | 27 | public class PresentWizardModel extends AbstractWizardModel { 28 | public PresentWizardModel(Context context) { 29 | super(context); 30 | } 31 | 32 | @Override 33 | protected PageList onNewRootPageList() { 34 | return new PageList( 35 | 36 | // BranchPage shows all of the branches available: Branch One, Branch Two, Branch Three. Each of these branches 37 | // have their own questions and the choices of the user will be summarised in the review section at the end 38 | new BranchPage(this, "Select one options") 39 | .addBranch("Branch One", 40 | new SingleFixedChoicePage(this, "Question One") 41 | .setChoices("A", "B", "C", "D") 42 | .setRequired(true), 43 | 44 | new MultipleFixedChoicePage(this, "Question Two") 45 | .setChoices("A", "B", "C", "D", 46 | "E") 47 | 48 | 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 SingleFixedChoicePage(this, "Question One") 69 | .setChoices("A", "B", "C") 70 | .setRequired(true) 71 | 72 | ) 73 | 74 | .setRequired(true) 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.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 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.model; 18 | 19 | import android.support.v4.app.ListFragment; 20 | import android.text.TextUtils; 21 | 22 | import com.iftw.materialnavigation.wizard.ui.SingleChoiceFragment; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | 28 | /** 29 | * A page representing a branching point in the wizard. Depending on which choice is selected, the 30 | * next set of steps in the wizard may change. 31 | */ 32 | public class BranchPage extends SingleFixedChoicePage { 33 | private List mBranches = new ArrayList(); 34 | 35 | public BranchPage(ModelCallbacks callbacks, String title) { 36 | super(callbacks, title); 37 | } 38 | 39 | @Override 40 | public Page findByKey(String key) { 41 | if (getKey().equals(key)) { 42 | return this; 43 | } 44 | 45 | for (Branch branch : mBranches) { 46 | Page found = branch.childPageList.findByKey(key); 47 | if (found != null) { 48 | return found; 49 | } 50 | } 51 | 52 | return null; 53 | } 54 | 55 | @Override 56 | public void flattenCurrentPageSequence(ArrayList destination) { 57 | super.flattenCurrentPageSequence(destination); 58 | for (Branch branch : mBranches) { 59 | if (branch.choice.equals(mData.getString(Page.SIMPLE_DATA_KEY))) { 60 | branch.childPageList.flattenCurrentPageSequence(destination); 61 | break; 62 | } 63 | } 64 | } 65 | 66 | public BranchPage addBranch(String choice, Page... childPages) { 67 | PageList childPageList = new PageList(childPages); 68 | for (Page page : childPageList) { 69 | page.setParentKey(choice); 70 | } 71 | mBranches.add(new Branch(choice, childPageList)); 72 | return this; 73 | } 74 | 75 | public BranchPage addBranch(String choice) { 76 | mBranches.add(new Branch(choice, new PageList())); 77 | return this; 78 | } 79 | 80 | @Override 81 | public ListFragment createFragment() { 82 | return SingleChoiceFragment.create(getKey()); 83 | } 84 | 85 | public String getOptionAt(int position) { 86 | return mBranches.get(position).choice; 87 | } 88 | 89 | public int getOptionCount() { 90 | return mBranches.size(); 91 | } 92 | 93 | @Override 94 | public void getReviewItems(ArrayList dest) { 95 | dest.add(new ReviewItem(getTitle(), mData.getString(SIMPLE_DATA_KEY), getKey())); 96 | } 97 | 98 | @Override 99 | public boolean isCompleted() { 100 | return !TextUtils.isEmpty(mData.getString(SIMPLE_DATA_KEY)); 101 | } 102 | 103 | @Override 104 | public void notifyDataChanged() { 105 | mCallbacks.onPageTreeChanged(); 106 | super.notifyDataChanged(); 107 | } 108 | 109 | public BranchPage setValue(String value) { 110 | mData.putString(SIMPLE_DATA_KEY, value); 111 | return this; 112 | } 113 | 114 | private static class Branch { 115 | public String choice; 116 | public PageList childPageList; 117 | 118 | private Branch(String choice, PageList childPageList) { 119 | this.choice = choice; 120 | this.childPageList = childPageList; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.model; 18 | 19 | import android.support.v4.app.ListFragment; 20 | import android.text.TextUtils; 21 | 22 | import com.iftw.materialnavigation.wizard.ui.CustomerInfoFragment; 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 ListFragment 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 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.model; 18 | 19 | /** 20 | * Callback interface connecting {@link Page}, {@link AbstractWizardModel}, and model container 21 | * objects. 22 | */ 23 | public interface ModelCallbacks { 24 | void onPageDataChanged(Page page); 25 | void onPageTreeChanged(); 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.model; 18 | 19 | import android.support.v4.app.ListFragment; 20 | 21 | import com.iftw.materialnavigation.wizard.ui.MultipleChoiceFragment; 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 ListFragment 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 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.model; 18 | 19 | import android.os.Bundle; 20 | import android.support.v4.app.ListFragment; 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 ListFragment 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 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.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 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.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 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.model; 18 | 19 | /** 20 | * Represents a single line item on the final review page. 21 | * 22 | * @see 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 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.model; 18 | 19 | import android.support.v4.app.ListFragment; 20 | import android.text.TextUtils; 21 | 22 | import com.iftw.materialnavigation.wizard.ui.SingleChoiceFragment; 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 ListFragment 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 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.ui; 18 | 19 | import android.app.Activity; 20 | import android.content.Context; 21 | import android.os.Bundle; 22 | import android.support.v4.app.ListFragment; 23 | import android.text.Editable; 24 | import android.text.TextWatcher; 25 | import android.view.LayoutInflater; 26 | import android.view.View; 27 | import android.view.ViewGroup; 28 | import android.view.inputmethod.InputMethodManager; 29 | import android.widget.TextView; 30 | 31 | import com.iftw.materialnavigation.R; 32 | import com.iftw.materialnavigation.wizard.model.CustomerInfoPage; 33 | 34 | public class CustomerInfoFragment extends ListFragment { 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 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.ui; 18 | 19 | import android.app.Activity; 20 | import android.os.Bundle; 21 | import android.os.Handler; 22 | import android.support.v4.app.ListFragment; 23 | import android.util.SparseBooleanArray; 24 | import android.view.LayoutInflater; 25 | import android.view.View; 26 | import android.view.ViewGroup; 27 | import android.widget.ArrayAdapter; 28 | import android.widget.ListView; 29 | import android.widget.TextView; 30 | 31 | import com.iftw.materialnavigation.R; 32 | import com.iftw.materialnavigation.service.InterfaceMapping; 33 | import com.iftw.materialnavigation.wizard.model.MultipleFixedChoicePage; 34 | import com.iftw.materialnavigation.wizard.model.Page; 35 | 36 | import java.util.ArrayList; 37 | import java.util.HashSet; 38 | import java.util.List; 39 | import java.util.Set; 40 | 41 | public class MultipleChoiceFragment extends ListFragment { 42 | private static final String ARG_KEY = "key"; 43 | 44 | // private PageFragmentCallbacks mCallbacks; 45 | private String mKey; 46 | private List mChoices; 47 | private Page mPage; 48 | 49 | public static MultipleChoiceFragment create(String key) { 50 | Bundle args = new Bundle(); 51 | args.putString(ARG_KEY, key); 52 | 53 | MultipleChoiceFragment fragment = new MultipleChoiceFragment(); 54 | fragment.setArguments(args); 55 | return fragment; 56 | } 57 | 58 | public MultipleChoiceFragment() { 59 | } 60 | 61 | @Override 62 | public void onCreate(Bundle savedInstanceState) { 63 | super.onCreate(savedInstanceState); 64 | 65 | Bundle args = getArguments(); 66 | mKey = args.getString(ARG_KEY); 67 | mPage = InterfaceMapping.getInstance().getFragment().onGetPage(mKey);//mCallbacks.onGetPage(mKey); 68 | 69 | MultipleFixedChoicePage fixedChoicePage = (MultipleFixedChoicePage) mPage; 70 | mChoices = new ArrayList(); 71 | for (int i = 0; i < fixedChoicePage.getOptionCount(); i++) { 72 | mChoices.add(fixedChoicePage.getOptionAt(i)); 73 | } 74 | } 75 | 76 | @Override 77 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 78 | Bundle savedInstanceState) { 79 | View rootView = inflater.inflate(R.layout.fragment_page, container, false); 80 | ((TextView) rootView.findViewById(android.R.id.title)).setText(mPage.getTitle()); 81 | 82 | final ListView listView = (ListView) rootView.findViewById(android.R.id.list); 83 | setListAdapter(new ArrayAdapter(getActivity(), 84 | android.R.layout.simple_list_item_multiple_choice, 85 | android.R.id.text1, 86 | mChoices)); 87 | listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE); 88 | 89 | // Pre-select currently selected items. 90 | new Handler().post(new Runnable() { 91 | @Override 92 | public void run() { 93 | ArrayList selectedItems = mPage.getData().getStringArrayList( 94 | Page.SIMPLE_DATA_KEY); 95 | if (selectedItems == null || selectedItems.size() == 0) { 96 | return; 97 | } 98 | 99 | Set selectedSet = new HashSet(selectedItems); 100 | 101 | for (int i = 0; i < mChoices.size(); i++) { 102 | if (selectedSet.contains(mChoices.get(i))) { 103 | listView.setItemChecked(i, true); 104 | } 105 | } 106 | } 107 | }); 108 | 109 | return rootView; 110 | } 111 | 112 | @Override 113 | public void onAttach(Activity activity) { 114 | super.onAttach(activity); 115 | // 116 | // if (!(activity instanceof PageFragmentCallbacks)) { 117 | // throw new ClassCastException("Activity must implement PageFragmentCallbacks"); 118 | // } 119 | // 120 | // mCallbacks = (PageFragmentCallbacks) activity; 121 | } 122 | 123 | @Override 124 | public void onDetach() { 125 | super.onDetach(); 126 | // mCallbacks = null; 127 | } 128 | 129 | @Override 130 | public void onListItemClick(ListView l, View v, int position, long id) { 131 | SparseBooleanArray checkedPositions = getListView().getCheckedItemPositions(); 132 | ArrayList selections = new ArrayList(); 133 | for (int i = 0; i < checkedPositions.size(); i++) { 134 | if (checkedPositions.valueAt(i)) { 135 | selections.add(getListAdapter().getItem(checkedPositions.keyAt(i)).toString()); 136 | } 137 | } 138 | 139 | mPage.getData().putStringArrayList(Page.SIMPLE_DATA_KEY, selections); 140 | mPage.notifyDataChanged(); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.ui; 18 | 19 | public interface PageFragmentCallbacks { 20 | com.iftw.materialnavigation.wizard.model.Page onGetPage(String key); 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/wizard/ui/PresentWizardModel.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.iftw.materialnavigation.wizard.ui; 18 | 19 | import android.content.Context; 20 | 21 | import com.iftw.materialnavigation.wizard.model.AbstractWizardModel; 22 | import com.iftw.materialnavigation.wizard.model.BranchPage; 23 | import com.iftw.materialnavigation.wizard.model.MultipleFixedChoicePage; 24 | import com.iftw.materialnavigation.wizard.model.PageList; 25 | import com.iftw.materialnavigation.wizard.model.SingleFixedChoicePage; 26 | 27 | public class PresentWizardModel extends AbstractWizardModel { 28 | public PresentWizardModel(Context context) { 29 | super(context); 30 | } 31 | 32 | @Override 33 | protected PageList onNewRootPageList() { 34 | return new PageList( 35 | 36 | // BranchPage shows all of the branches available: Branch One, Branch Two, Branch Three. Each of these branches 37 | // have their own questions and the choices of the user will be summarised in the review section at the end 38 | new BranchPage(this, "Select 1 options") 39 | .addBranch("Branch One", 40 | new SingleFixedChoicePage(this, "Question One") 41 | .setChoices("A", "B", "C", "D") 42 | .setRequired(true), 43 | 44 | new MultipleFixedChoicePage(this, "Question Two") 45 | .setChoices("A", "B", "C", "D", 46 | "E") 47 | 48 | /*new BranchPage(this, "Toasted?") 49 | .addBranch("Yes", 50 | new SingleFixedChoicePage(this, "Toast time") 51 | .setChoices("30 seconds", "1 minute", "2 minutes")) 52 | .addBranch("No") 53 | .setValue("No") 54 | */ 55 | ) 56 | 57 | // Second branch of questions 58 | .addBranch("Branch Two", 59 | new SingleFixedChoicePage(this, "Question One") 60 | .setChoices("A", "B") 61 | .setRequired(true), 62 | 63 | new SingleFixedChoicePage(this, "Question Two") 64 | .setChoices("A", "B", "C", 65 | "D", "E", "F") 66 | .setRequired(true), 67 | 68 | new SingleFixedChoicePage(this, "Question Three") 69 | .setChoices("A", "B", "C") 70 | ) 71 | 72 | // Third branch of questions 73 | .addBranch("Branch Three", 74 | new SingleFixedChoicePage(this, "Question One") 75 | .setChoices("A", "B", "C") 76 | .setRequired(true) 77 | ) 78 | 79 | .setRequired(true) 80 | 81 | //new CustomerInfoPage(this, "Your info") 82 | //.setRequired(true) 83 | ); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.ui; 18 | 19 | import android.app.Activity; 20 | import android.os.Bundle; 21 | import android.support.v4.app.ListFragment; 22 | import android.text.TextUtils; 23 | import android.view.LayoutInflater; 24 | import android.view.View; 25 | import android.view.ViewGroup; 26 | import android.widget.BaseAdapter; 27 | import android.widget.ListView; 28 | import android.widget.TextView; 29 | 30 | import com.iftw.materialnavigation.R; 31 | import com.iftw.materialnavigation.service.InterfaceMapping; 32 | import com.iftw.materialnavigation.wizard.model.AbstractWizardModel; 33 | import com.iftw.materialnavigation.wizard.model.ModelCallbacks; 34 | import com.iftw.materialnavigation.wizard.model.Page; 35 | import com.iftw.materialnavigation.wizard.model.ReviewItem; 36 | 37 | import java.util.ArrayList; 38 | import java.util.Collections; 39 | import java.util.Comparator; 40 | import java.util.List; 41 | 42 | public class ReviewFragment extends ListFragment implements ModelCallbacks { 43 | // private Callbacks mCallbacks; 44 | private AbstractWizardModel mWizardModel; 45 | private List mCurrentReviewItems; 46 | 47 | private ReviewAdapter mReviewAdapter; 48 | 49 | public ReviewFragment() { 50 | } 51 | 52 | @Override 53 | public void onCreate(Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | mReviewAdapter = new ReviewAdapter(); 56 | } 57 | 58 | @Override 59 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 60 | Bundle savedInstanceState) { 61 | View rootView = inflater.inflate(R.layout.fragment_page, container, false); 62 | 63 | TextView titleView = (TextView) rootView.findViewById(android.R.id.title); 64 | titleView.setText("Review"); 65 | titleView.setTextColor(getResources().getColor(R.color.step_pager_selected_tab_color)); 66 | 67 | ListView listView = (ListView) rootView.findViewById(android.R.id.list); 68 | setListAdapter(mReviewAdapter); 69 | listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 70 | return rootView; 71 | } 72 | 73 | @Override 74 | public void onAttach(Activity activity) { 75 | super.onAttach(activity); 76 | 77 | // if (!(activity instanceof Callbacks)) { 78 | // throw new ClassCastException("Activity must implement fragment's callbacks"); 79 | // } 80 | 81 | // mCallbacks = (Callbacks) activity; 82 | 83 | // mWizardModel = mCallbacks.onGetModel(); 84 | mWizardModel = InterfaceMapping.getInstance().getFragment().onGetModel(); 85 | mWizardModel.registerListener(this); 86 | onPageTreeChanged(); 87 | } 88 | 89 | @Override 90 | public void onPageTreeChanged() { 91 | onPageDataChanged(null); 92 | } 93 | 94 | @Override 95 | public void onDetach() { 96 | super.onDetach(); 97 | // mCallbacks = null; 98 | 99 | mWizardModel.unregisterListener(this); 100 | } 101 | 102 | @Override 103 | public void onPageDataChanged(Page changedPage) { 104 | ArrayList reviewItems = new ArrayList(); 105 | for (Page page : mWizardModel.getCurrentPageSequence()) { 106 | page.getReviewItems(reviewItems); 107 | } 108 | Collections.sort(reviewItems, new Comparator() { 109 | @Override 110 | public int compare(ReviewItem a, ReviewItem b) { 111 | return a.getWeight() > b.getWeight() ? +1 : a.getWeight() < b.getWeight() ? -1 : 0; 112 | } 113 | }); 114 | mCurrentReviewItems = reviewItems; 115 | 116 | if (mReviewAdapter != null) { 117 | mReviewAdapter.notifyDataSetInvalidated(); 118 | } 119 | } 120 | 121 | @Override 122 | public void onListItemClick(ListView l, View v, int position, long id) { 123 | // mCallbacks.onEditScreenAfterReview(mCurrentReviewItems.get(position).getPageKey()); 124 | InterfaceMapping.getInstance().getFragment().onEditScreenAfterReview(mCurrentReviewItems.get(position).getPageKey()); 125 | } 126 | 127 | public interface Callbacks { 128 | AbstractWizardModel onGetModel(); 129 | void onEditScreenAfterReview(String pageKey); 130 | } 131 | 132 | private class ReviewAdapter extends BaseAdapter { 133 | @Override 134 | public boolean hasStableIds() { 135 | return true; 136 | } 137 | 138 | @Override 139 | public int getItemViewType(int position) { 140 | return 0; 141 | } 142 | 143 | @Override 144 | public int getViewTypeCount() { 145 | return 1; 146 | } 147 | 148 | @Override 149 | public boolean areAllItemsEnabled() { 150 | return true; 151 | } 152 | 153 | @Override 154 | public Object getItem(int position) { 155 | return mCurrentReviewItems.get(position); 156 | } 157 | 158 | @Override 159 | public long getItemId(int position) { 160 | return mCurrentReviewItems.get(position).hashCode(); 161 | } 162 | 163 | @Override 164 | public View getView(int position, View view, ViewGroup container) { 165 | LayoutInflater inflater = LayoutInflater.from(getActivity()); 166 | View rootView = inflater.inflate(R.layout.list_item_review, container, false); 167 | 168 | ReviewItem reviewItem = mCurrentReviewItems.get(position); 169 | String value = reviewItem.getDisplayValue(); 170 | if (TextUtils.isEmpty(value)) { 171 | value = "(None)"; 172 | } 173 | ((TextView) rootView.findViewById(android.R.id.text1)).setText(reviewItem.getTitle()); 174 | ((TextView) rootView.findViewById(android.R.id.text2)).setText(value); 175 | return rootView; 176 | } 177 | 178 | @Override 179 | public int getCount() { 180 | return mCurrentReviewItems.size(); 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.ui; 18 | 19 | import android.app.Activity; 20 | import android.os.Bundle; 21 | import android.os.Handler; 22 | import android.support.v4.app.ListFragment; 23 | import android.view.LayoutInflater; 24 | import android.view.View; 25 | import android.view.ViewGroup; 26 | import android.widget.ArrayAdapter; 27 | import android.widget.ListView; 28 | import android.widget.TextView; 29 | 30 | import com.iftw.materialnavigation.R; 31 | import com.iftw.materialnavigation.service.InterfaceMapping; 32 | import com.iftw.materialnavigation.wizard.model.Page; 33 | import com.iftw.materialnavigation.wizard.model.SingleFixedChoicePage; 34 | 35 | import java.util.ArrayList; 36 | import java.util.List; 37 | 38 | public class SingleChoiceFragment extends ListFragment { 39 | private static final String ARG_KEY = "key"; 40 | 41 | private PageFragmentCallbacks mCallbacks; 42 | private List mChoices; 43 | private String mKey; 44 | private Page mPage; 45 | 46 | public static SingleChoiceFragment create(String key) { 47 | Bundle args = new Bundle(); 48 | args.putString(ARG_KEY, key); 49 | 50 | SingleChoiceFragment fragment = new SingleChoiceFragment(); 51 | fragment.setArguments(args); 52 | return fragment; 53 | } 54 | 55 | public SingleChoiceFragment() { 56 | } 57 | 58 | @Override 59 | public void onCreate(Bundle savedInstanceState) { 60 | super.onCreate(savedInstanceState); 61 | 62 | Bundle args = getArguments(); 63 | mKey = args.getString(ARG_KEY); 64 | // mPage = mCallbacks.onGetPage(mKey); 65 | mPage = InterfaceMapping.getInstance().getFragment().onGetPage(mKey); 66 | 67 | SingleFixedChoicePage fixedChoicePage = (SingleFixedChoicePage) mPage; 68 | mChoices = new ArrayList(); 69 | for (int i = 0; i < fixedChoicePage.getOptionCount(); i++) { 70 | mChoices.add(fixedChoicePage.getOptionAt(i)); 71 | } 72 | } 73 | 74 | @Override 75 | public View onCreateView(LayoutInflater inflater, ViewGroup container, 76 | Bundle savedInstanceState) { 77 | View rootView = inflater.inflate(R.layout.fragment_page, container, false); 78 | ((TextView) rootView.findViewById(android.R.id.title)).setText(mPage.getTitle()); 79 | 80 | final ListView listView = (ListView) rootView.findViewById(android.R.id.list); 81 | setListAdapter(new ArrayAdapter(getActivity(), 82 | android.R.layout.simple_list_item_single_choice, 83 | android.R.id.text1, 84 | mChoices)); 85 | listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); 86 | 87 | // Pre-select currently selected item. 88 | new Handler().post(new Runnable() { 89 | @Override 90 | public void run() { 91 | String selection = mPage.getData().getString(Page.SIMPLE_DATA_KEY); 92 | for (int i = 0; i < mChoices.size(); i++) { 93 | if (mChoices.get(i).equals(selection)) { 94 | listView.setItemChecked(i, true); 95 | break; 96 | } 97 | } 98 | } 99 | }); 100 | 101 | return rootView; 102 | } 103 | 104 | @Override 105 | public void onAttach(Activity activity) { 106 | super.onAttach(activity); 107 | 108 | // if (!(activity instanceof PageFragmentCallbacks)) { 109 | // throw new ClassCastException("Activity must implement PageFragmentCallbacks"); 110 | // } 111 | 112 | // mCallbacks = (PageFragmentCallbacks) activity; 113 | // mCallbacks = InterfaceMapping.getInstance().getFragment().on 114 | } 115 | 116 | @Override 117 | public void onDetach() { 118 | super.onDetach(); 119 | // mCallbacks = null; 120 | } 121 | 122 | @Override 123 | public void onListItemClick(ListView l, View v, int position, long id) { 124 | mPage.getData().putString(Page.SIMPLE_DATA_KEY, 125 | getListAdapter().getItem(position).toString()); 126 | mPage.notifyDataChanged(); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /app/src/main/java/com/iftw/materialnavigation/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.iftw.materialnavigation.wizard.ui; 18 | 19 | import android.content.Context; 20 | import android.content.res.Resources; 21 | import android.content.res.TypedArray; 22 | import android.graphics.Canvas; 23 | import android.graphics.Paint; 24 | import android.graphics.RectF; 25 | import android.util.AttributeSet; 26 | import android.view.Gravity; 27 | import android.view.MotionEvent; 28 | import android.view.View; 29 | 30 | import com.iftw.materialnavigation.R; 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 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_menu_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard-Drawer/b7937a5f9c6f704a7b50325ee952eb4346c8f89f/app/src/main/res/drawable-hdpi/ic_menu_check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_menu_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard-Drawer/b7937a5f9c6f704a7b50325ee952eb4346c8f89f/app/src/main/res/drawable-mdpi/ic_menu_check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_menu_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard-Drawer/b7937a5f9c6f704a7b50325ee952eb4346c8f89f/app/src/main/res/drawable-xhdpi/ic_menu_check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_menu_check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard-Drawer/b7937a5f9c6f704a7b50325ee952eb4346c8f89f/app/src/main/res/drawable-xxhdpi/ic_menu_check.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/selectable_item_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard-Drawer/b7937a5f9c6f704a7b50325ee952eb4346c8f89f/app/src/main/res/drawable/avatar.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/row_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/wallpaper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarkOSullivan94/Android-Material-Wizard-Drawer/b7937a5f9c6f704a7b50325ee952eb4346c8f89f/app/src/main/res/drawable/wallpaper.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 11 | 12 | 18 | 19 | 21 | 22 | 23 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_report_health.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 17 | 18 | 23 | 24 | 28 | 29 | 34 | 35 |