├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── art ├── demo1.gif ├── demo2.gif ├── demo3.gif ├── demo4.gif ├── demo5.gif ├── demo6.gif └── icon.png ├── build.gradle ├── demo ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── ogaclejapan │ │ └── smarttablayout │ │ └── demo │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── ogaclejapan │ │ └── smarttablayout │ │ └── demo │ │ ├── Demo.java │ │ ├── DemoActivity.java │ │ ├── DemoFragment.java │ │ ├── MainActivity.java │ │ └── TintableImageView.java │ └── res │ ├── color │ ├── custom_tab.xml │ └── custom_tab_icon.xml │ ├── drawable-hdpi │ ├── ic_flash_on_white_24dp.png │ ├── ic_home_white_24dp.png │ ├── ic_launcher.png │ ├── ic_people_white_24dp.png │ └── ic_search_white_24dp.png │ ├── drawable-mdpi │ ├── ic_flash_on_white_24dp.png │ ├── ic_home_white_24dp.png │ ├── ic_launcher.png │ ├── ic_people_white_24dp.png │ └── ic_search_white_24dp.png │ ├── drawable-xhdpi │ ├── ic_flash_on_white_24dp.png │ ├── ic_home_white_24dp.png │ ├── ic_launcher.png │ ├── ic_person_white_24dp.png │ └── ic_search_white_24dp.png │ ├── drawable-xxhdpi │ ├── ic_flash_on_white_24dp.png │ ├── ic_home_white_24dp.png │ ├── ic_launcher.png │ ├── ic_person_white_24dp.png │ └── ic_search_white_24dp.png │ ├── drawable-xxxhdpi │ ├── ic_flash_on_white_24dp.png │ ├── ic_home_white_24dp.png │ ├── ic_launcher.png │ ├── ic_person_white_24dp.png │ └── ic_search_white_24dp.png │ ├── drawable │ ├── custom_circle.xml │ └── custom_tab.xml │ ├── layout │ ├── activity_demo.xml │ ├── activity_main.xml │ ├── custom_tab.xml │ ├── custom_tab_circle.xml │ ├── custom_tab_icon.xml │ ├── demo_always_in_center.xml │ ├── demo_basic.xml │ ├── demo_custom_tab_colors.xml │ ├── demo_custom_tab_icons.xml │ ├── demo_custom_tab_text.xml │ ├── demo_distribute_evenly.xml │ ├── demo_indicator_trick1.xml │ ├── demo_indicator_trick2.xml │ ├── demo_smart_indicator.xml │ └── fragment_demo.xml │ ├── menu │ ├── menu_demo.xml │ └── menu_main.xml │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── ids.xml │ ├── strings.xml │ └── styles.xml ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── LICENSE ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── ogaclejapan │ │ └── smarttablayout │ │ └── ApplicationTest.java │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── ogaclejapan │ │ └── smarttablayout │ │ ├── SmartTabIndicationInterpolator.java │ │ ├── SmartTabLayout.java │ │ └── SmartTabStrip.java │ └── res │ └── values │ └── attrs.xml ├── settings.gradle ├── utils-v13 ├── .gitignore ├── LICENSE ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── ogaclejapan │ └── smarttablayout │ └── utils │ ├── PagerItem.java │ ├── PagerItems.java │ ├── ViewPagerItem.java │ ├── ViewPagerItemAdapter.java │ ├── ViewPagerItems.java │ └── v13 │ ├── Bundler.java │ ├── FragmentPagerItem.java │ ├── FragmentPagerItemAdapter.java │ ├── FragmentPagerItems.java │ └── FragmentStatePagerItemAdapter.java └── utils-v4 ├── .gitignore ├── LICENSE ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml └── java └── com └── ogaclejapan └── smarttablayout └── utils ├── PagerItem.java ├── PagerItems.java ├── ViewPagerItem.java ├── ViewPagerItemAdapter.java ├── ViewPagerItems.java └── v4 ├── Bundler.java ├── FragmentPagerItem.java ├── FragmentPagerItemAdapter.java ├── FragmentPagerItems.java └── FragmentStatePagerItemAdapter.java /.gitignore: -------------------------------------------------------------------------------- 1 | # https://github.com/github/gitignore 2 | # https://github.com/hsz/idea-gitignore 3 | 4 | 5 | ### JetBrains template 6 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 7 | 8 | *.iml 9 | 10 | ## Directory-based project format: 11 | .idea/ 12 | # if you remove the above rule, at least ignore the following: 13 | 14 | # User-specific stuff: 15 | # .idea/workspace.xml 16 | # .idea/tasks.xml 17 | # .idea/dictionaries 18 | 19 | # Sensitive or high-churn files: 20 | # .idea/dataSources.ids 21 | # .idea/dataSources.xml 22 | # .idea/sqlDataSources.xml 23 | # .idea/dynamic.xml 24 | # .idea/uiDesigner.xml 25 | 26 | # Gradle: 27 | # .idea/gradle.xml 28 | # .idea/libraries 29 | 30 | # Mongo Explorer plugin: 31 | # .idea/mongoSettings.xml 32 | 33 | ## File-based project format: 34 | *.ipr 35 | *.iws 36 | 37 | ## Plugin-specific files: 38 | 39 | # IntelliJ 40 | /out/ 41 | 42 | # mpeltonen/sbt-idea plugin 43 | .idea_modules/ 44 | 45 | # JIRA plugin 46 | atlassian-ide-plugin.xml 47 | 48 | # Crashlytics plugin (for Android Studio and IntelliJ) 49 | com_crashlytics_export_strings.xml 50 | crashlytics.properties 51 | crashlytics-build.properties 52 | 53 | 54 | ### Android template 55 | # Built application files 56 | *.apk 57 | *.ap_ 58 | 59 | # Files for the Dalvik VM 60 | *.dex 61 | 62 | # Java class files 63 | *.class 64 | 65 | # Generated files 66 | bin/ 67 | gen/ 68 | 69 | # Gradle files 70 | .gradle/ 71 | build/ 72 | /*/build/ 73 | 74 | # Local configuration file (sdk path, etc) 75 | local.properties 76 | 77 | # Proguard folder generated by Eclipse 78 | proguard/ 79 | 80 | # Log Files 81 | *.log 82 | 83 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Version 1.1.3 2 | 3 | * Allow to set the background on default tab #13 4 | 5 | # Version 1.1.2 6 | 7 | * Added setter for tab text colors #10 8 | * Allow to set a String title dynamically on PagerItems. #7 9 | 10 | # Version 1.1.1 11 | 12 | * Enable the format of ‘reference’ for defaultTextColor to support ColorStateList #3 13 | 14 | # Version 1.1.0 15 | 16 | * Supported Icon Tab. #1 17 | 18 | 19 | # Version 1.0.0 20 | 21 | * Initial release. 22 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | If you would like to contribute code to SmartTabLayout you can do so through GitHub by 4 | forking the repository and sending a pull request. 5 | 6 | When submitting code, please make every effort to follow existing conventions 7 | and style in order to keep the code as readable as possible. 8 | 9 | ## Coding Style 10 | 11 | * Use the AndroidModernStyle of [Android Code Styles](https://github.com/ogaclejapan/android-code-styles) repository 12 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright (C) 2015 ogaclejapan 191 | Copyright (C) 2013 The Android Open Source Project 192 | 193 | Licensed under the Apache License, Version 2.0 (the "License"); 194 | you may not use this file except in compliance with the License. 195 | You may obtain a copy of the License at 196 | 197 | http://www.apache.org/licenses/LICENSE-2.0 198 | 199 | Unless required by applicable law or agreed to in writing, software 200 | distributed under the License is distributed on an "AS IS" BASIS, 201 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 202 | See the License for the specific language governing permissions and 203 | limitations under the License. 204 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SmartTabLayout 2 | [![Maven Central][maven_central_badge_svg]][maven_central_badge_app] [![Android Arsenal][android_arsenal_badge_svg]][android_arsenal_badge_link] [![Android Weekly][android_weekly_badge_svg]][android_weekly_badge_link] 3 | 4 | ![icon][demo_icon] 5 | 6 | A custom ViewPager title strip which gives continuous feedback to the user when scrolling. 7 | 8 | This library has been added some features and utilities based on [android-SlidingTabBasic][google_slidingtabbasic] project of Google Samples. 9 | 10 | 11 | ![SmartTabLayout Demo1][demo1_gif] ![SmartTabLayout Demo2][demo2_gif] 12 | ![SmartTabLayout Demo3][demo3_gif] ![SmartTabLayout Demo4][demo4_gif] 13 | ![SmartTabLayout Demo5][demo5_gif] ![SmartTabLayout Demo6][demo6_gif] 14 | 15 | 16 | Try out the sample application on the Play Store. 17 | 18 | [![Get it on Google Play][googleplay_store_badge]][demo_app] 19 | 20 | # Usage 21 | 22 | _(For a working implementation of this project see the demo/ folder.)_ 23 | 24 | Add the dependency to your build.gradle. 25 | 26 | ``` 27 | dependencies { 28 | compile 'com.ogaclejapan.smarttablayout:library:1.1.3@aar' 29 | 30 | //Optional: see how to use the utility. 31 | compile 'com.ogaclejapan.smarttablayout:utils-v4:1.1.3@aar' 32 | 33 | //Optional: see how to use the utility. 34 | compile 'com.ogaclejapan.smarttablayout:utils-v13:1.1.3@aar' 35 | } 36 | ``` 37 | 38 | Include the SmartTabLayout widget in your layout. 39 | This should usually be placed above the ViewPager it represents. 40 | 41 | ```xml 42 | 43 | 65 | 66 | 72 | 73 | ``` 74 | 75 | In your onCreate method (or onCreateView for a fragment), bind the widget to the ViewPager. 76 | (If you use a utility together, you can easily add items to PagerAdapter) 77 | 78 | e.g. ViewPager of v4.Fragment 79 | 80 | ```java 81 | 82 | FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter( 83 | getSupportFragmentManager(), FragmentPagerItems.with(this) 84 | .add(R.string.titleA, PageFragment.class) 85 | .add(R.string.titleB, PageFragment.class) 86 | .create()); 87 | 88 | ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager); 89 | viewPager.setAdapter(adapter); 90 | 91 | SmartTabLayout viewPagerTab = (SmartTabLayout) findViewById(R.id.viewpagertab); 92 | viewPagerTab.setViewPager(viewPager); 93 | 94 | ``` 95 | 96 | (Optional) If you use an OnPageChangeListener with your view pager you should set it in the widget rather than on the pager directly. 97 | 98 | ```java 99 | 100 | viewPagerTab.setOnPageChangeListener(mPageChangeListener); 101 | 102 | ``` 103 | 104 | (Optional) Using the FragmentPagerItemAdapter of utility, you will be able to get a position in the Fragment side. 105 | 106 | ```java 107 | 108 | int position = FragmentPagerItem.getPosition(getArguments()); 109 | 110 | ``` 111 | 112 | This position will help to implement the parallax scrolling header that contains the ViewPager :P 113 | 114 | # Attributes 115 | 116 | There are several attributes you can set: 117 | 118 | | attr | description | 119 | |:---|:---| 120 | | stl_indicatorAlwaysInCenter | If set to true, active tab is always displayed in center (Like Newsstand google app), default false | 121 | | stl_indicatorInFront | Draw the indicator in front of the underline, default false | 122 | | stl_indicatorInterpolation | Behavior of the indicator: 'linear' or 'smart' | 123 | | stl_indicatorColor | Color of the indicator | 124 | | stl_indicatorColors | Multiple colors of the indicator, can set the color for each tab | 125 | | stl_indicatorThickness | Thickness of the indicator | 126 | | stl_indicatorCornerRadius | Radius of rounded corner the indicator | 127 | | stl_underlineColor | Color of the bottom line | 128 | | stl_underlineThickness | Thickness of the bottom line | 129 | | stl_dividerColor | Color of the dividers between tabs | 130 | | stl_dividerColors | Multiple colors of the dividers between tabs, can set the color for each tab | 131 | | stl_dividerThickness | Thickness of the divider | 132 | | stl_defaultTabBackground | Background drawable of each tab. In general it set the StateListDrawable | 133 | | stl_defaultTabTextAllCaps | If set to true, all tab titles will be upper case, default true | 134 | | stl_defaultTabTextColor | Text color of the tab that was included by default | 135 | | stl_defaultTabTextSize | Text size of the tab that was included by default | 136 | | stl_defaultTabTextHorizontalPadding | Text layout padding of the tab that was included by default | 137 | | stl_defaultTabTextMinWidth | Minimum width of tab | 138 | | stl_customTabTextLayoutId | Layout ID defined custom tab. If you do not specify a layout, use the default tab | 139 | | stl_customTabTextViewId | Text view ID in a custom tab layout. If you do not define with customTabTextLayoutId, does not work | 140 | | stl_distributeEvenly | If set to true, each tab is given the same weight, default false | 141 | 142 | 143 | *__Notes:__ Both 'stl_indicatorAlwaysInCenter' and 'stl_distributeEvenly' if it is set to true, it will throw UnsupportedOperationException.* 144 | 145 | # How to customize the tab 146 | 147 | The customization of tab There are three ways. 148 | 149 | * Customize the attribute 150 | * SmartTabLayout#setCustomTabView(int layoutResId, int textViewId) 151 | * SmartTabLayout#setCustomTabView(TabProvider provider) 152 | 153 | If set the TabProvider, can build a view for each tab. 154 | 155 | ```java 156 | 157 | public class SmartTabLayout extends HorizontalScrollView { 158 | 159 | //... 160 | 161 | /** 162 | * Create the custom tabs in the tab layout. Set with 163 | * {@link #setCustomTabView(com.ogaclejapan.smarttablayout.SmartTabLayout.TabProvider)} 164 | */ 165 | public interface TabProvider { 166 | 167 | /** 168 | * @return Return the View of {@code position} for the Tabs 169 | */ 170 | View createTabView(ViewGroup container, int position, PagerAdapter adapter); 171 | 172 | } 173 | 174 | //... 175 | } 176 | 177 | ``` 178 | 179 | # How to use the utility 180 | 181 | Utility has two types available to suit the Android support library. 182 | 183 | * utils-v4 library contains the PagerAdapter implementation class for _android.support.v4.app.Fragment_ 184 | * utils-v13 library contains the PagerAdapter implementation class for _android.app.Fragment_ 185 | 186 | The two libraries have different Android support libraries that depend, 187 | but implemented functionality is the same. 188 | 189 | ## PagerAdapter for View-based Page 190 | 191 | ```java 192 | 193 | ViewPagerItemAdapter adapter = new ViewPagerItemAdapter(ViewPagerItems.with(this) 194 | .add(R.string.title, R.layout.page) 195 | .add("title", R.layout.page) 196 | .create()); 197 | 198 | viewPager.setAdapter(adapter); 199 | 200 | //... 201 | 202 | public void onPageSelected(int position) { 203 | 204 | //.instantiateItem() from until .destroyItem() is called it will be able to get the View of page. 205 | View page = adapter.getPage(position); 206 | 207 | } 208 | 209 | 210 | ``` 211 | 212 | ## PagerAdapter for Fragment-based Page 213 | 214 | Fragment-based PagerAdapter There are two implementations. 215 | Please differences refer to the library documentation for Android. 216 | 217 | * FragmentPagerItemAdapter extends FragmentPagerAdapter 218 | * FragmentStatePagerItemAdapter extends FragmentStatePagerAdapter 219 | 220 | ```java 221 | 222 | FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter( 223 | getSupportFragmentManager(), FragmentPagerItems.with(this) 224 | .add(R.string.title, PageFragment.class), 225 | .add(R.string.title, WithArgumentsPageFragment.class, new Bundler().putString("key", "value").get()), 226 | .add("title", PageFragment.class) 227 | .create()); 228 | 229 | viewPager.setAdapter(adapter); 230 | 231 | //... 232 | 233 | public void onPageSelected(int position) { 234 | 235 | //.instantiateItem() from until .destoryItem() is called it will be able to get the Fragment of page. 236 | Fragment page = adapter.getPage(position); 237 | 238 | } 239 | 240 | ``` 241 | 242 | 243 | # Apps Using SmartTabLayout 244 | 245 | * [Qiitanium][qiitanium] 246 | 247 | 248 | # LICENSE 249 | 250 | ``` 251 | Copyright (C) 2015 ogaclejapan 252 | Copyright (C) 2013 The Android Open Source Project 253 | 254 | Licensed under the Apache License, Version 2.0 (the "License"); 255 | you may not use this file except in compliance with the License. 256 | You may obtain a copy of the License at 257 | 258 | http://www.apache.org/licenses/LICENSE-2.0 259 | 260 | Unless required by applicable law or agreed to in writing, software 261 | distributed under the License is distributed on an "AS IS" BASIS, 262 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 263 | See the License for the specific language governing permissions and 264 | limitations under the License. 265 | ``` 266 | 267 | [demo1_gif]: https://raw.githubusercontent.com/ogaclejapan/SmartTabLayout/master/art/demo1.gif 268 | [demo2_gif]: https://raw.githubusercontent.com/ogaclejapan/SmartTabLayout/master/art/demo2.gif 269 | [demo3_gif]: https://raw.githubusercontent.com/ogaclejapan/SmartTabLayout/master/art/demo3.gif 270 | [demo4_gif]: https://raw.githubusercontent.com/ogaclejapan/SmartTabLayout/master/art/demo4.gif 271 | [demo5_gif]: https://raw.githubusercontent.com/ogaclejapan/SmartTabLayout/master/art/demo5.gif 272 | [demo6_gif]: https://raw.githubusercontent.com/ogaclejapan/SmartTabLayout/master/art/demo6.gif 273 | [demo_app]: https://play.google.com/store/apps/details?id=com.ogaclejapan.smarttablayout.demo 274 | [demo_icon]: https://raw.githubusercontent.com/ogaclejapan/SmartTabLayout/master/art/icon.png 275 | [googleplay_store_badge]: https://developer.android.com/images/brand/en_generic_rgb_wo_60.png 276 | [maven_central_badge_svg]: https://maven-badges.herokuapp.com/maven-central/com.ogaclejapan.smarttablayout/library/badge.svg?style=flat 277 | [maven_central_badge_app]: https://maven-badges.herokuapp.com/maven-central/com.ogaclejapan.smarttablayout/library 278 | [android_arsenal_badge_svg]: https://img.shields.io/badge/Android%20Arsenal-SmartTabLayout-brightgreen.svg?style=flat 279 | [android_arsenal_badge_link]: http://android-arsenal.com/details/1/1683 280 | [android_weekly_badge_svg]: https://img.shields.io/badge/AndroidWeekly-%23148-blue.svg 281 | [android_weekly_badge_link]: http://androidweekly.net/issues/issue-148 282 | [qiitanium]: https://github.com/ogaclejapan/Qiitanium 283 | [google_slidingtabbasic]: https://github.com/googlesamples/android-SlidingTabsBasic 284 | -------------------------------------------------------------------------------- /art/demo1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/art/demo1.gif -------------------------------------------------------------------------------- /art/demo2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/art/demo2.gif -------------------------------------------------------------------------------- /art/demo3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/art/demo3.gif -------------------------------------------------------------------------------- /art/demo4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/art/demo4.gif -------------------------------------------------------------------------------- /art/demo5.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/art/demo5.gif -------------------------------------------------------------------------------- /art/demo6.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/art/demo6.gif -------------------------------------------------------------------------------- /art/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/art/icon.png -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.1.3' 9 | classpath 'com.github.dcendents:android-maven-plugin:1.2' 10 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.1' 11 | classpath 'nl.javadude.gradle.plugins:license-gradle-plugin:0.11.0' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | 20 | version = VERSION_NAME 21 | group = GROUP 22 | 23 | repositories { 24 | jcenter() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /demo/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion COMPILE_SDK_VERSION as int 5 | buildToolsVersion BUILD_TOOLS_VERSION 6 | 7 | defaultConfig { 8 | minSdkVersion 10 9 | targetSdkVersion COMPILE_SDK_VERSION as int 10 | versionCode VERSION_CODE as int 11 | versionName VERSION_NAME 12 | } 13 | 14 | def secretFile = file("${rootDir}/secret.gradle") 15 | if (secretFile.exists()) { 16 | apply from: secretFile.absolutePath 17 | signingConfigs { 18 | release { 19 | storeFile project.ext.storeFile 20 | storePassword project.ext.storePassword 21 | keyAlias project.ext.keyAlias 22 | keyPassword project.ext.keyPassword 23 | } 24 | } 25 | } 26 | 27 | buildTypes { 28 | release { 29 | if (secretFile.exists()) { 30 | signingConfig signingConfigs.release 31 | } 32 | minifyEnabled false 33 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 34 | } 35 | } 36 | } 37 | 38 | dependencies { 39 | compile project(':library') 40 | compile project(':utils-v4') 41 | compile 'com.android.support:appcompat-v7:22.0.0' 42 | } 43 | -------------------------------------------------------------------------------- /demo/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 /Users/msk/Library/Android/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 | -------------------------------------------------------------------------------- /demo/src/androidTest/java/com/ogaclejapan/smarttablayout/demo/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.ogaclejapan.smarttablayout.demo; 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 | } -------------------------------------------------------------------------------- /demo/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /demo/src/main/java/com/ogaclejapan/smarttablayout/demo/Demo.java: -------------------------------------------------------------------------------- 1 | package com.ogaclejapan.smarttablayout.demo; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.support.v4.view.PagerAdapter; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.ImageView; 10 | 11 | import com.ogaclejapan.smarttablayout.SmartTabLayout; 12 | 13 | public enum Demo { 14 | 15 | BASIC(R.string.demo_title_basic, R.layout.demo_basic), 16 | 17 | SMART_INDICATOR(R.string.demo_title_smart_indicator, R.layout.demo_smart_indicator), 18 | 19 | DISTRIBUTE_EVENLY(R.string.demo_title_distribute_evenly, R.layout.demo_distribute_evenly) { 20 | @Override 21 | public int[] tabs() { 22 | return tab3(); 23 | } 24 | }, 25 | 26 | ALWAYS_IN_CENTER(R.string.demo_title_always_in_center, R.layout.demo_always_in_center), 27 | 28 | CUSTOM_TAB(R.string.demo_title_custom_tab_text, R.layout.demo_custom_tab_text), 29 | 30 | CUSTOM_TAB_COLORS(R.string.demo_title_custom_tab_colors, R.layout.demo_custom_tab_colors), 31 | 32 | CUSTOM_TAB_ICONS(R.string.demo_title_custom_tab_icons, R.layout.demo_custom_tab_icons) { 33 | @Override 34 | public int[] tabs() { 35 | return new int[] { 36 | R.string.demo_tab_no_title, 37 | R.string.demo_tab_no_title, 38 | R.string.demo_tab_no_title, 39 | R.string.demo_tab_no_title 40 | }; 41 | } 42 | 43 | @Override 44 | public void setup(SmartTabLayout layout) { 45 | super.setup(layout); 46 | 47 | final LayoutInflater inflater = LayoutInflater.from(layout.getContext()); 48 | final Resources res = layout.getContext().getResources(); 49 | 50 | layout.setCustomTabView(new SmartTabLayout.TabProvider() { 51 | @Override 52 | public View createTabView(ViewGroup container, int position, PagerAdapter adapter) { 53 | ImageView icon = (ImageView) inflater.inflate(R.layout.custom_tab_icon, container, false); 54 | switch (position) { 55 | case 0: 56 | icon.setImageDrawable(res.getDrawable(R.drawable.ic_home_white_24dp)); 57 | break; 58 | case 1: 59 | icon.setImageDrawable(res.getDrawable(R.drawable.ic_search_white_24dp)); 60 | break; 61 | case 2: 62 | icon.setImageDrawable(res.getDrawable(R.drawable.ic_person_white_24dp)); 63 | break; 64 | case 3: 65 | icon.setImageDrawable(res.getDrawable(R.drawable.ic_flash_on_white_24dp)); 66 | break; 67 | default: 68 | throw new IllegalStateException("Invalid position: " + position); 69 | } 70 | return icon; 71 | } 72 | }); 73 | } 74 | }, 75 | 76 | INDICATOR_TRICK1(R.string.demo_title_indicator_trick1, R.layout.demo_indicator_trick1), 77 | 78 | INDICATOR_TRICK2(R.string.demo_title_indicator_trick2, R.layout.demo_indicator_trick2); 79 | 80 | public final int titleResId; 81 | public final int layoutResId; 82 | 83 | Demo(int titleResId, int layoutResId) { 84 | this.titleResId = titleResId; 85 | this.layoutResId = layoutResId; 86 | } 87 | 88 | public static int[] tab10() { 89 | return new int[] { 90 | R.string.demo_tab_1, 91 | R.string.demo_tab_2, 92 | R.string.demo_tab_3, 93 | R.string.demo_tab_4, 94 | R.string.demo_tab_5, 95 | R.string.demo_tab_6, 96 | R.string.demo_tab_7, 97 | R.string.demo_tab_8, 98 | R.string.demo_tab_9, 99 | R.string.demo_tab_10 100 | }; 101 | } 102 | 103 | public static int[] tab3() { 104 | return new int[] { 105 | R.string.demo_tab_8, 106 | R.string.demo_tab_9, 107 | R.string.demo_tab_10 108 | }; 109 | } 110 | 111 | public void startActivity(Context context) { 112 | DemoActivity.startActivity(context, this); 113 | } 114 | 115 | public void setup(final SmartTabLayout layout) { 116 | //Do nothing. 117 | } 118 | 119 | public int[] tabs() { 120 | return tab10(); 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /demo/src/main/java/com/ogaclejapan/smarttablayout/demo/DemoActivity.java: -------------------------------------------------------------------------------- 1 | package com.ogaclejapan.smarttablayout.demo; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.os.Bundle; 6 | import android.support.v4.view.ViewPager; 7 | import android.support.v7.app.ActionBarActivity; 8 | import android.support.v7.widget.Toolbar; 9 | import android.view.LayoutInflater; 10 | import android.view.ViewGroup; 11 | 12 | import com.ogaclejapan.smarttablayout.SmartTabLayout; 13 | import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItem; 14 | import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItemAdapter; 15 | import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItems; 16 | 17 | public class DemoActivity extends ActionBarActivity { 18 | 19 | private static final String KEY_DEMO = "demo"; 20 | 21 | public static void startActivity(Context context, Demo demo) { 22 | Intent intent = new Intent(context, DemoActivity.class); 23 | intent.putExtra(KEY_DEMO, demo.name()); 24 | context.startActivity(intent); 25 | } 26 | 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState) { 29 | super.onCreate(savedInstanceState); 30 | setContentView(R.layout.activity_demo); 31 | 32 | Demo demo = getDemo(); 33 | 34 | Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); 35 | toolbar.setTitle(demo.titleResId); 36 | setSupportActionBar(toolbar); 37 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 38 | 39 | ViewGroup tab = (ViewGroup) findViewById(R.id.tab); 40 | tab.addView(LayoutInflater.from(this).inflate(demo.layoutResId, tab, false)); 41 | 42 | ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager); 43 | SmartTabLayout viewPagerTab = (SmartTabLayout) findViewById(R.id.viewpagertab); 44 | demo.setup(viewPagerTab); 45 | 46 | FragmentPagerItems pages = new FragmentPagerItems(this); 47 | for (int titleResId : demo.tabs()) { 48 | pages.add(FragmentPagerItem.of(getString(titleResId), DemoFragment.class)); 49 | } 50 | 51 | FragmentPagerItemAdapter adapter = new FragmentPagerItemAdapter( 52 | getSupportFragmentManager(), pages); 53 | 54 | viewPager.setAdapter(adapter); 55 | viewPagerTab.setViewPager(viewPager); 56 | 57 | } 58 | 59 | private Demo getDemo() { 60 | return Demo.valueOf(getIntent().getStringExtra(KEY_DEMO)); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /demo/src/main/java/com/ogaclejapan/smarttablayout/demo/DemoFragment.java: -------------------------------------------------------------------------------- 1 | package com.ogaclejapan.smarttablayout.demo; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.app.Fragment; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import com.ogaclejapan.smarttablayout.utils.v4.FragmentPagerItem; 12 | 13 | public class DemoFragment extends Fragment { 14 | 15 | @Override 16 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 17 | @Nullable Bundle savedInstanceState) { 18 | return inflater.inflate(R.layout.fragment_demo, container, false); 19 | } 20 | 21 | @Override 22 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 23 | super.onViewCreated(view, savedInstanceState); 24 | int position = FragmentPagerItem.getPosition(getArguments()); 25 | TextView title = (TextView) view.findViewById(R.id.item_title); 26 | title.setText(String.valueOf(position)); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /demo/src/main/java/com/ogaclejapan/smarttablayout/demo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.ogaclejapan.smarttablayout.demo; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.support.v7.app.ActionBarActivity; 7 | import android.view.Menu; 8 | import android.view.MenuItem; 9 | import android.view.View; 10 | import android.widget.AbsListView; 11 | import android.widget.AdapterView; 12 | import android.widget.ArrayAdapter; 13 | import android.widget.ListView; 14 | 15 | public class MainActivity extends ActionBarActivity implements AbsListView.OnItemClickListener { 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_main); 21 | ListView listView = (ListView) findViewById(R.id.list); 22 | listView.setOnItemClickListener(this); 23 | 24 | ArrayAdapter demoAdapter = new ArrayAdapter(this, 25 | android.R.layout.simple_list_item_1); 26 | 27 | for (Demo demo : Demo.values()) { 28 | demoAdapter.add(getString(demo.titleResId)); 29 | } 30 | 31 | listView.setAdapter(demoAdapter); 32 | } 33 | 34 | @Override 35 | public boolean onCreateOptionsMenu(Menu menu) { 36 | getMenuInflater().inflate(R.menu.menu_main, menu); 37 | return super.onCreateOptionsMenu(menu); 38 | } 39 | 40 | @Override 41 | public boolean onOptionsItemSelected(MenuItem item) { 42 | switch (item.getItemId()) { 43 | case R.id.menu_github: 44 | openGitHub(); 45 | return true; 46 | default: 47 | return super.onOptionsItemSelected(item); 48 | } 49 | } 50 | 51 | @Override 52 | public void onItemClick(AdapterView parent, View view, int position, long id) { 53 | Demo demo = Demo.values()[position]; 54 | demo.startActivity(this); 55 | } 56 | 57 | private void openGitHub() { 58 | Uri uri = Uri.parse(getString(R.string.app_github_url)); 59 | Intent intent = new Intent(Intent.ACTION_VIEW, uri); 60 | startActivity(intent); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /demo/src/main/java/com/ogaclejapan/smarttablayout/demo/TintableImageView.java: -------------------------------------------------------------------------------- 1 | package com.ogaclejapan.smarttablayout.demo; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | import android.content.res.TypedArray; 6 | import android.util.AttributeSet; 7 | import android.widget.ImageView; 8 | 9 | /** 10 | * https://gist.github.com/tylerchesley/5d15d859be4f3ce31213 11 | */ 12 | public class TintableImageView extends ImageView { 13 | 14 | private ColorStateList tint; 15 | 16 | public TintableImageView(Context context) { 17 | super(context); 18 | } 19 | 20 | public TintableImageView(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | init(context, attrs, 0); 23 | } 24 | 25 | public TintableImageView(Context context, AttributeSet attrs, int defStyle) { 26 | super(context, attrs, defStyle); 27 | init(context, attrs, defStyle); 28 | } 29 | 30 | private void init(Context context, AttributeSet attrs, int defStyle) { 31 | TypedArray a = context.obtainStyledAttributes( 32 | attrs, R.styleable.TintableImageView, defStyle, 0); 33 | tint = a.getColorStateList( 34 | R.styleable.TintableImageView_tint); 35 | a.recycle(); 36 | } 37 | 38 | @Override 39 | protected void drawableStateChanged() { 40 | super.drawableStateChanged(); 41 | if (tint != null && tint.isStateful()) { 42 | updateTintColor(); 43 | } 44 | } 45 | 46 | public void setColorFilter(ColorStateList tint) { 47 | this.tint = tint; 48 | super.setColorFilter(tint.getColorForState(getDrawableState(), 0)); 49 | } 50 | 51 | private void updateTintColor() { 52 | int color = tint.getColorForState(getDrawableState(), 0); 53 | setColorFilter(color); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /demo/src/main/res/color/custom_tab.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo/src/main/res/color/custom_tab_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/ic_flash_on_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-hdpi/ic_flash_on_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/ic_home_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-hdpi/ic_home_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/ic_people_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-hdpi/ic_people_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-hdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-hdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-mdpi/ic_flash_on_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-mdpi/ic_flash_on_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-mdpi/ic_home_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-mdpi/ic_home_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-mdpi/ic_people_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-mdpi/ic_people_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-mdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-mdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xhdpi/ic_flash_on_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xhdpi/ic_flash_on_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xhdpi/ic_home_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xhdpi/ic_home_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xhdpi/ic_person_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xhdpi/ic_person_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xhdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xhdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxhdpi/ic_flash_on_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxhdpi/ic_flash_on_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxhdpi/ic_home_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxhdpi/ic_home_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxhdpi/ic_person_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxhdpi/ic_person_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxhdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxxhdpi/ic_flash_on_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxxhdpi/ic_flash_on_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxxhdpi/ic_home_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxxhdpi/ic_home_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxxhdpi/ic_person_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxxhdpi/ic_person_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/demo/src/main/res/drawable-xxxhdpi/ic_search_white_24dp.png -------------------------------------------------------------------------------- /demo/src/main/res/drawable/custom_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 10 | -------------------------------------------------------------------------------- /demo/src/main/res/drawable/custom_tab.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_demo.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 15 | 16 | 24 | 25 | 26 | 27 | 32 | 33 | 34 | 35 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 14 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/custom_tab.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/custom_tab_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/custom_tab_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo_always_in_center.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo_basic.xml: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo_custom_tab_colors.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo_custom_tab_icons.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo_custom_tab_text.xml: -------------------------------------------------------------------------------- 1 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo_distribute_evenly.xml: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo_indicator_trick1.xml: -------------------------------------------------------------------------------- 1 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo_indicator_trick2.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/demo_smart_indicator.xml: -------------------------------------------------------------------------------- 1 | 16 | -------------------------------------------------------------------------------- /demo/src/main/res/layout/fragment_demo.xml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 16 | 17 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /demo/src/main/res/menu/menu_demo.xml: -------------------------------------------------------------------------------- 1 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /demo/src/main/res/menu/menu_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /demo/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /demo/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3C515C 4 | #142E3C 5 | #40C4FF 6 | #FFFFFFFF 7 | #33000000 8 | #00000000 9 | 10 | #FFFFFFFF 11 | #4DFFFFFF 12 | 13 | #FFFFFFFF 14 | #FF63727B 15 | 16 | #03A9F4 17 | #00BCD4 18 | #009688 19 | #4CAF50 20 | #8BC34A 21 | 22 | 23 | @color/light_blue_500 24 | @color/cyan_500 25 | @color/teal_500 26 | @color/green_500 27 | @color/light_green_500 28 | 29 | 30 | -------------------------------------------------------------------------------- /demo/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 48dp 3 | 4 | -------------------------------------------------------------------------------- /demo/src/main/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SmartTabLayout 5 | GitHub 6 | 7 | Settings 8 | 9 | Basic 10 | Smart Indicator 11 | Distribute Evenly 12 | Always In Center 13 | Custom Tab Text 14 | Custom Tab Colors 15 | Custom Tab Icons 16 | Indicator Thickness Trick 1 17 | Indicator Thickness Trick 2 18 | 19 | Cupcake 20 | Donut 21 | Eclair 22 | Froyo 23 | Gingerbread 24 | Honeycomb 25 | Ice Cream Sandwich 26 | Jelly Bean 27 | KitKat 28 | Lollipop 29 | 30 | No Title 31 | 32 | 33 | -------------------------------------------------------------------------------- /demo/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | VERSION_NAME=1.1.3 2 | VERSION_CODE=5 3 | BUILD_TOOLS_VERSION=22 4 | COMPILE_SDK_VERSION=22 5 | 6 | GROUP=com.ogaclejapan.smarttablayout 7 | ARTIFACT_NAME=SmartTabLayout 8 | ARTIFACT_DESCRIPTION=A custom ViewPager title strip which gives continuous feedback to the user when scrolling 9 | SITE_URL=https://github.com/ogaclejapan/SmartTabLayout 10 | ISSUE_SYSTEM=github 11 | ISSUE_URL=https://github.com/ogaclejapan/SmartTabLayout/issues 12 | SCM_URL=https://github.com/ogaclejapan/SmartTabLayout 13 | SCM_CONNECTION=scm:git@github.com:ogaclejapan/SmartTabLayout.git 14 | SCM_DEV_CONNECTION=scm:git@github.com:ogaclejapan/SmartTabLayout.git 15 | LICENCE_NAME=The Apache Software License, Version 2.0 16 | LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 17 | LICENCE_DIST=repo 18 | DEVELOPER_ID=ogaclejapan 19 | DEVELOPER_NAME=Masaki Ogata 20 | DEVELOPER_EMAIL=ogaclejapan@gmail.com 21 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ThomasWang2014/SmartTablayout/e3d6992123cd307de89ffc76c2fb68a93c99eb71/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Apr 10 15:27:10 PDT 2013 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) ${year} ${name} 2 | Copyright (C) 2013 The Android Open Source Project 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 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | apply plugin: 'com.jfrog.bintray' 4 | apply plugin: 'license' 5 | 6 | android { 7 | compileSdkVersion COMPILE_SDK_VERSION as int 8 | buildToolsVersion BUILD_TOOLS_VERSION 9 | resourcePrefix 'stl_' 10 | 11 | defaultConfig { 12 | minSdkVersion 4 13 | targetSdkVersion COMPILE_SDK_VERSION as int 14 | versionCode VERSION_CODE as int 15 | versionName VERSION_NAME 16 | 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | lintOptions { 25 | abortOnError false 26 | } 27 | } 28 | 29 | dependencies { 30 | compile "com.android.support:support-v4:22.0.0" 31 | } 32 | 33 | license { 34 | 35 | sourceSets { 36 | main.java.srcDirs = android.sourceSets.main.java.srcDirs 37 | main.resources.srcDirs = android.sourceSets.main.resources.srcDirs 38 | } 39 | 40 | ext.year = Calendar.getInstance().get(Calendar.YEAR) 41 | ext.name = DEVELOPER_ID 42 | 43 | } 44 | 45 | install { 46 | repositories.mavenInstaller { 47 | // This generates POM.xml with proper parameters 48 | pom { 49 | project { 50 | packaging 'aar' 51 | 52 | name ARTIFACT_NAME 53 | description ARTIFACT_DESCRIPTION 54 | url SITE_URL 55 | 56 | licenses { 57 | license { 58 | name LICENCE_NAME 59 | url LICENCE_URL 60 | distribution LICENCE_DIST 61 | } 62 | } 63 | 64 | developers { 65 | developer { 66 | id DEVELOPER_ID 67 | name DEVELOPER_NAME 68 | email DEVELOPER_EMAIL 69 | } 70 | } 71 | issueManagement { 72 | system ISSUE_SYSTEM 73 | url ISSUE_URL 74 | } 75 | 76 | scm { 77 | connection SCM_CONNECTION 78 | developerConnection SCM_DEV_CONNECTION 79 | url SCM_URL 80 | 81 | } 82 | } 83 | } 84 | } 85 | } 86 | 87 | afterEvaluate { project -> 88 | 89 | task sourcesJar(type: Jar) { 90 | from android.sourceSets.main.java.srcDirs 91 | classifier = 'sources' 92 | } 93 | 94 | task javadoc(type: Javadoc) { 95 | failOnError false 96 | source = android.sourceSets.main.java.srcDirs 97 | options { 98 | links "http://docs.oracle.com/javase/7/docs/api/" 99 | linksOffline "http://d.android.com/reference", System.getenv("ANDROID_HOME") + "/docs/reference" 100 | } 101 | classpath += project.android.libraryVariants.toList().first().javaCompile.classpath 102 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 103 | 104 | } 105 | 106 | task javadocJar(type: Jar, dependsOn: javadoc) { 107 | classifier = 'javadoc' 108 | from javadoc.destinationDir 109 | } 110 | 111 | artifacts { 112 | archives javadocJar 113 | archives sourcesJar 114 | } 115 | 116 | } 117 | 118 | def getNexusUser() { 119 | return hasProperty('NEXUS_USER') ? NEXUS_USER : "" 120 | } 121 | 122 | def getNexusPassword() { 123 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" 124 | } 125 | 126 | def getBintrayUser() { 127 | return hasProperty('BINTRAY_USER') ? BINTRAY_USER : "" 128 | } 129 | 130 | def getBintrayApiKey() { 131 | return hasProperty('BINTRAY_APIKEY') ? BINTRAY_APIKEY : "" 132 | } 133 | 134 | def getGpgPassphrase() { 135 | return hasProperty('BINTRAY_GPG_PASSPHRASE') ? BINTRAY_GPG_PASSPHRASE : "" 136 | } 137 | 138 | bintray { 139 | 140 | user = bintrayUser 141 | key = bintrayApiKey 142 | 143 | configurations = ['archives'] 144 | 145 | dryRun = false 146 | publish = true 147 | 148 | pkg { 149 | repo = "maven" 150 | name = ARTIFACT_NAME 151 | desc = ARTIFACT_DESCRIPTION 152 | websiteUrl = SITE_URL 153 | issueTrackerUrl = ISSUE_URL 154 | vcsUrl = SCM_URL 155 | licenses = ["Apache-2.0"] 156 | labels = ['android'] 157 | publicDownloadNumbers = true 158 | 159 | version { 160 | gpg { 161 | sign = true 162 | passphrase = gpgPassphrase 163 | } 164 | 165 | mavenCentralSync { 166 | sync = true 167 | user = nexusUser 168 | password = nexusPassword 169 | } 170 | 171 | } 172 | 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /library/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 /Users/msk/Library/Android/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 | -------------------------------------------------------------------------------- /library/src/androidTest/java/com/ogaclejapan/smarttablayout/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.ogaclejapan.smarttablayout; 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 | } -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabIndicationInterpolator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 3 | * Copyright (C) 2013 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.ogaclejapan.smarttablayout; 18 | 19 | import android.view.animation.AccelerateInterpolator; 20 | import android.view.animation.DecelerateInterpolator; 21 | import android.view.animation.Interpolator; 22 | 23 | public abstract class SmartTabIndicationInterpolator { 24 | 25 | public static final SmartTabIndicationInterpolator SMART = new SmartIndicationInterpolator(); 26 | public static final SmartTabIndicationInterpolator LINEAR = new LinearIndicationInterpolator(); 27 | 28 | static final int ID_SMART = 0; 29 | static final int ID_LINEAR = 1; 30 | 31 | public static SmartTabIndicationInterpolator of(int id) { 32 | switch (id) { 33 | case ID_SMART: 34 | return SMART; 35 | case ID_LINEAR: 36 | return LINEAR; 37 | default: 38 | throw new IllegalArgumentException("Unknown id: " + id); 39 | } 40 | } 41 | 42 | public abstract float getLeftEdge(float offset); 43 | 44 | public abstract float getRightEdge(float offset); 45 | 46 | public float getThickness(float offset) { 47 | return 1f; //Always the same thickness by default 48 | } 49 | 50 | public static class SmartIndicationInterpolator extends SmartTabIndicationInterpolator { 51 | 52 | private static final float DEFAULT_INDICATOR_INTERPOLATION_FACTOR = 3.0f; 53 | 54 | private final Interpolator leftEdgeInterpolator; 55 | private final Interpolator rightEdgeInterpolator; 56 | 57 | public SmartIndicationInterpolator() { 58 | this(DEFAULT_INDICATOR_INTERPOLATION_FACTOR); 59 | } 60 | 61 | public SmartIndicationInterpolator(float factor) { 62 | leftEdgeInterpolator = new AccelerateInterpolator(factor); 63 | rightEdgeInterpolator = new DecelerateInterpolator(factor); 64 | } 65 | 66 | @Override 67 | public float getLeftEdge(float offset) { 68 | return leftEdgeInterpolator.getInterpolation(offset); 69 | } 70 | 71 | @Override 72 | public float getRightEdge(float offset) { 73 | return rightEdgeInterpolator.getInterpolation(offset); 74 | } 75 | 76 | @Override 77 | public float getThickness(float offset) { 78 | return 1f / (1.0f - getLeftEdge(offset) + getRightEdge(offset)); 79 | } 80 | 81 | } 82 | 83 | public static class LinearIndicationInterpolator extends SmartTabIndicationInterpolator { 84 | 85 | @Override 86 | public float getLeftEdge(float offset) { 87 | return offset; 88 | } 89 | 90 | @Override 91 | public float getRightEdge(float offset) { 92 | return offset; 93 | } 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabLayout.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 3 | * Copyright (C) 2013 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.ogaclejapan.smarttablayout; 18 | 19 | import android.content.Context; 20 | import android.content.res.ColorStateList; 21 | import android.content.res.TypedArray; 22 | import android.graphics.Typeface; 23 | import android.os.Build; 24 | import android.support.v4.view.PagerAdapter; 25 | import android.support.v4.view.ViewPager; 26 | import android.util.AttributeSet; 27 | import android.util.DisplayMetrics; 28 | import android.util.TypedValue; 29 | import android.view.Gravity; 30 | import android.view.LayoutInflater; 31 | import android.view.View; 32 | import android.view.ViewGroup; 33 | import android.widget.HorizontalScrollView; 34 | import android.widget.LinearLayout; 35 | import android.widget.TextView; 36 | 37 | /** 38 | * To be used with ViewPager to provide a tab indicator component which give constant feedback as 39 | * to 40 | * the user's scroll progress. 41 | *

42 | * To use the component, simply add it to your view hierarchy. Then in your 43 | * {@link android.app.Activity} or {@link android.app.Fragment}, {@link 44 | * android.support.v4.app.Fragment} call 45 | * {@link #setViewPager(android.support.v4.view.ViewPager)} providing it the ViewPager this layout 46 | * is being used for. 47 | *

48 | * The colors can be customized in two ways. The first and simplest is to provide an array of 49 | * colors 50 | * via {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)}. The 51 | * alternative is via the {@link TabColorizer} interface which provides you complete control over 52 | * which color is used for any individual position. 53 | *

54 | * The views used as tabs can be customized by calling {@link #setCustomTabView(int, int)}, 55 | * providing the layout ID of your custom layout. 56 | *

57 | * Forked from Google Samples > SlidingTabsBasic > 58 | * SlidingTabLayout 59 | */ 60 | public class SmartTabLayout extends HorizontalScrollView { 61 | 62 | private static final boolean DEFAULT_DISTRIBUTE_EVENLY = false; 63 | private static final int TITLE_OFFSET_DIPS = 24; 64 | private static final int TAB_VIEW_PADDING_DIPS = 16; 65 | private static final boolean TAB_VIEW_TEXT_ALL_CAPS = true; 66 | private static final int TAB_VIEW_TEXT_SIZE_SP = 12; 67 | private static final int TAB_VIEW_TEXT_COLOR = 0xFC000000; 68 | private static final int TAB_VIEW_TEXT_MIN_WIDTH = 0; 69 | 70 | protected final SmartTabStrip tabStrip; 71 | private int titleOffset; 72 | private int tabViewBackgroundResId; 73 | private boolean tabViewTextAllCaps; 74 | private ColorStateList tabViewTextColors; 75 | private float tabViewTextSize; 76 | private int tabViewTextHorizontalPadding; 77 | private int tabViewTextMinWidth; 78 | private ViewPager viewPager; 79 | private ViewPager.OnPageChangeListener viewPagerPageChangeListener; 80 | private TabProvider tabProvider; 81 | private boolean distributeEvenly; 82 | 83 | public SmartTabLayout(Context context) { 84 | this(context, null); 85 | } 86 | 87 | public SmartTabLayout(Context context, AttributeSet attrs) { 88 | this(context, attrs, 0); 89 | } 90 | 91 | public SmartTabLayout(Context context, AttributeSet attrs, int defStyle) { 92 | super(context, attrs, defStyle); 93 | 94 | // Disable the Scroll Bar 95 | setHorizontalScrollBarEnabled(false); 96 | // Make sure that the Tab Strips fills this View 97 | setFillViewport(true); 98 | 99 | final DisplayMetrics dm = getResources().getDisplayMetrics(); 100 | final float density = dm.density; 101 | 102 | int tabBackgroundResId = NO_ID; 103 | boolean textAllCaps = TAB_VIEW_TEXT_ALL_CAPS; 104 | ColorStateList textColors; 105 | float textSize = TypedValue.applyDimension( 106 | TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP, dm); 107 | int textHorizontalPadding = (int) (TAB_VIEW_PADDING_DIPS * density); 108 | int textMinWidth = (int) (TAB_VIEW_TEXT_MIN_WIDTH * density); 109 | boolean distributeEvenly = DEFAULT_DISTRIBUTE_EVENLY; 110 | int customTabLayoutId = NO_ID; 111 | int customTabTextViewId = NO_ID; 112 | 113 | TypedArray a = context.obtainStyledAttributes( 114 | attrs, R.styleable.stl_SmartTabLayout, defStyle, 0); 115 | tabBackgroundResId = a.getResourceId( 116 | R.styleable.stl_SmartTabLayout_stl_defaultTabBackground, tabBackgroundResId); 117 | textAllCaps = a.getBoolean( 118 | R.styleable.stl_SmartTabLayout_stl_defaultTabTextAllCaps, textAllCaps); 119 | textColors = a.getColorStateList( 120 | R.styleable.stl_SmartTabLayout_stl_defaultTabTextColor); 121 | textSize = a.getDimension( 122 | R.styleable.stl_SmartTabLayout_stl_defaultTabTextSize, textSize); 123 | textHorizontalPadding = a.getDimensionPixelSize( 124 | R.styleable.stl_SmartTabLayout_stl_defaultTabTextHorizontalPadding, textHorizontalPadding); 125 | textMinWidth = a.getDimensionPixelSize( 126 | R.styleable.stl_SmartTabLayout_stl_defaultTabTextMinWidth, textMinWidth); 127 | customTabLayoutId = a.getResourceId( 128 | R.styleable.stl_SmartTabLayout_stl_customTabTextLayoutId, customTabLayoutId); 129 | customTabTextViewId = a.getResourceId( 130 | R.styleable.stl_SmartTabLayout_stl_customTabTextViewId, customTabTextViewId); 131 | distributeEvenly = a.getBoolean( 132 | R.styleable.stl_SmartTabLayout_stl_distributeEvenly, distributeEvenly); 133 | a.recycle(); 134 | 135 | this.titleOffset = (int) (TITLE_OFFSET_DIPS * density); 136 | this.tabViewBackgroundResId = tabBackgroundResId; 137 | this.tabViewTextAllCaps = textAllCaps; 138 | this.tabViewTextColors = (textColors != null) 139 | ? textColors 140 | : ColorStateList.valueOf(TAB_VIEW_TEXT_COLOR); 141 | this.tabViewTextSize = textSize; 142 | this.tabViewTextHorizontalPadding = textHorizontalPadding; 143 | this.tabViewTextMinWidth = textMinWidth; 144 | this.distributeEvenly = distributeEvenly; 145 | 146 | if (customTabLayoutId != NO_ID) { 147 | setCustomTabView(customTabLayoutId, customTabTextViewId); 148 | } 149 | 150 | this.tabStrip = new SmartTabStrip(context, attrs); 151 | 152 | if (distributeEvenly && tabStrip.isIndicatorAlwaysInCenter()) { 153 | throw new UnsupportedOperationException( 154 | "'distributeEvenly' and 'indicatorAlwaysInCenter' both use does not support"); 155 | } 156 | 157 | addView(tabStrip, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); 158 | 159 | } 160 | 161 | @Override 162 | protected void onSizeChanged(int w, int h, int oldw, int oldh) { 163 | super.onSizeChanged(w, h, oldw, oldh); 164 | if (tabStrip.isIndicatorAlwaysInCenter() && getChildCount() > 0) { 165 | int left = (w - tabStrip.getChildMeasuredWidthAt(0)) / 2; 166 | int right = (w - tabStrip.getChildMeasuredWidthAt(getChildCount() - 1)) / 2; 167 | setPadding(left, getPaddingTop(), right, getPaddingBottom()); 168 | setClipToPadding(false); 169 | } 170 | } 171 | 172 | /** 173 | * Set the behavior of the Indicator scrolling feedback. 174 | * 175 | * @param interpolator {@link com.ogaclejapan.smarttablayout.SmartTabIndicationInterpolator} 176 | */ 177 | public void setIndicationInterpolator(SmartTabIndicationInterpolator interpolator) { 178 | tabStrip.setIndicationInterpolator(interpolator); 179 | } 180 | 181 | /** 182 | * Set the custom {@link TabColorizer} to be used. 183 | * 184 | * If you only require simple customisation then you can use 185 | * {@link #setSelectedIndicatorColors(int...)} and {@link #setDividerColors(int...)} to achieve 186 | * similar effects. 187 | */ 188 | public void setCustomTabColorizer(TabColorizer tabColorizer) { 189 | tabStrip.setCustomTabColorizer(tabColorizer); 190 | } 191 | 192 | /** 193 | * Set the color used for styling the tab text. This will need to be called prior to calling 194 | * {@link #setViewPager(android.support.v4.view.ViewPager)} otherwise it will not get set 195 | * 196 | * @param color to use for tab text 197 | */ 198 | public void setDefaultTabTextColor(int color) { 199 | tabViewTextColors = ColorStateList.valueOf(color); 200 | } 201 | 202 | /** 203 | * Sets the colors used for styling the tab text. This will need to be called prior to calling 204 | * {@link #setViewPager(android.support.v4.view.ViewPager)} otherwise it will not get set 205 | * 206 | * @param colors ColorStateList to use for tab text 207 | */ 208 | public void setDefaultTabTextColor(ColorStateList colors) { 209 | tabViewTextColors = colors; 210 | } 211 | 212 | /** 213 | * Set the same weight for tab 214 | */ 215 | public void setDistributeEvenly(boolean distributeEvenly) { 216 | this.distributeEvenly = distributeEvenly; 217 | } 218 | 219 | /** 220 | * Sets the colors to be used for indicating the selected tab. These colors are treated as a 221 | * circular array. Providing one color will mean that all tabs are indicated with the same color. 222 | */ 223 | public void setSelectedIndicatorColors(int... colors) { 224 | tabStrip.setSelectedIndicatorColors(colors); 225 | } 226 | 227 | /** 228 | * Sets the colors to be used for tab dividers. These colors are treated as a circular array. 229 | * Providing one color will mean that all tabs are indicated with the same color. 230 | */ 231 | public void setDividerColors(int... colors) { 232 | tabStrip.setDividerColors(colors); 233 | } 234 | 235 | /** 236 | * Set the {@link ViewPager.OnPageChangeListener}. When using {@link SmartTabLayout} you are 237 | * required to set any {@link ViewPager.OnPageChangeListener} through this method. This is so 238 | * that the layout can update it's scroll position correctly. 239 | * 240 | * @see ViewPager#setOnPageChangeListener(ViewPager.OnPageChangeListener) 241 | */ 242 | public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { 243 | viewPagerPageChangeListener = listener; 244 | } 245 | 246 | /** 247 | * Set the custom layout to be inflated for the tab views. 248 | * 249 | * @param layoutResId Layout id to be inflated 250 | * @param textViewId id of the {@link android.widget.TextView} in the inflated view 251 | */ 252 | public void setCustomTabView(int layoutResId, int textViewId) { 253 | tabProvider = new SimpleTabProvider(getContext(), layoutResId, textViewId); 254 | } 255 | 256 | /** 257 | * Set the custom layout to be inflated for the tab views. 258 | * 259 | * @param provider {@link TabProvider} 260 | */ 261 | public void setCustomTabView(TabProvider provider) { 262 | tabProvider = provider; 263 | } 264 | 265 | /** 266 | * Sets the associated view pager. Note that the assumption here is that the pager content 267 | * (number of tabs and tab titles) does not change after this call has been made. 268 | */ 269 | public void setViewPager(ViewPager viewPager) { 270 | tabStrip.removeAllViews(); 271 | 272 | this.viewPager = viewPager; 273 | if (viewPager != null && viewPager.getAdapter() != null) { 274 | viewPager.setOnPageChangeListener(new InternalViewPagerListener()); 275 | populateTabStrip(); 276 | } 277 | } 278 | 279 | /** 280 | * Returns the view at the specified position in the tabs. 281 | * 282 | * @param position the position at which to get the view from 283 | * @return the view at the specified position or null if the position does not exist within the 284 | * tabs 285 | */ 286 | public View getTabAt(int position) { 287 | return tabStrip.getChildAt(position); 288 | } 289 | 290 | /** 291 | * Create a default view to be used for tabs. This is called if a custom tab view is not set via 292 | * {@link #setCustomTabView(int, int)}. 293 | */ 294 | protected TextView createDefaultTabView(CharSequence title) { 295 | TextView textView = new TextView(getContext()); 296 | textView.setGravity(Gravity.CENTER); 297 | textView.setText(title); 298 | textView.setTextColor(tabViewTextColors); 299 | textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, tabViewTextSize); 300 | textView.setTypeface(Typeface.DEFAULT_BOLD); 301 | textView.setLayoutParams(new LinearLayout.LayoutParams( 302 | LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT)); 303 | 304 | if (tabViewBackgroundResId != NO_ID) { 305 | textView.setBackgroundResource(tabViewBackgroundResId); 306 | } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 307 | // If we're running on Honeycomb or newer, then we can use the Theme's 308 | // selectableItemBackground to ensure that the View has a pressed state 309 | TypedValue outValue = new TypedValue(); 310 | getContext().getTheme().resolveAttribute(android.R.attr.selectableItemBackground, 311 | outValue, true); 312 | textView.setBackgroundResource(outValue.resourceId); 313 | } 314 | 315 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 316 | // If we're running on ICS or newer, enable all-caps to match the Action Bar tab style 317 | textView.setAllCaps(tabViewTextAllCaps); 318 | } 319 | 320 | textView.setPadding( 321 | tabViewTextHorizontalPadding, 0, 322 | tabViewTextHorizontalPadding, 0); 323 | 324 | if (tabViewTextMinWidth > 0) { 325 | textView.setMinWidth(tabViewTextMinWidth); 326 | } 327 | 328 | return textView; 329 | } 330 | 331 | @Override 332 | protected void onScrollChanged(int l, int t, int oldl, int oldt) { 333 | super.onScrollChanged(l, t, oldl, oldt); 334 | } 335 | 336 | private void populateTabStrip() { 337 | final PagerAdapter adapter = viewPager.getAdapter(); 338 | final OnClickListener tabClickListener = new TabClickListener(); 339 | 340 | for (int i = 0; i < adapter.getCount(); i++) { 341 | 342 | final View tabView = (tabProvider == null) 343 | ? createDefaultTabView(adapter.getPageTitle(i)) 344 | : tabProvider.createTabView(tabStrip, i, adapter); 345 | 346 | if (tabView == null) { 347 | throw new IllegalStateException("tabView is null."); 348 | } 349 | 350 | if (distributeEvenly) { 351 | LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) tabView.getLayoutParams(); 352 | lp.width = 0; 353 | lp.weight = 1; 354 | } 355 | 356 | tabView.setOnClickListener(tabClickListener); 357 | tabStrip.addView(tabView); 358 | 359 | if (i == viewPager.getCurrentItem()) { 360 | tabView.setSelected(true); 361 | } 362 | 363 | } 364 | } 365 | 366 | @Override 367 | protected void onAttachedToWindow() { 368 | super.onAttachedToWindow(); 369 | 370 | if (viewPager != null) { 371 | scrollToTab(viewPager.getCurrentItem(), 0); 372 | } 373 | } 374 | 375 | private void scrollToTab(int tabIndex, int positionOffset) { 376 | final int tabStripChildCount = tabStrip.getChildCount(); 377 | if (tabStripChildCount == 0 || tabIndex < 0 || tabIndex >= tabStripChildCount) { 378 | return; 379 | } 380 | 381 | View selectedChild = tabStrip.getChildAt(tabIndex); 382 | if (selectedChild != null) { 383 | int targetScrollX = selectedChild.getLeft() + positionOffset; 384 | if (tabStrip.isIndicatorAlwaysInCenter()) { 385 | targetScrollX -= (tabStrip.getChildWidthAt(0) - selectedChild.getWidth()) / 2; 386 | } else if (tabIndex > 0 || positionOffset > 0) { 387 | // If we're not at the first child and are mid-scroll, make sure we obey the offset 388 | targetScrollX -= titleOffset; 389 | } 390 | 391 | scrollTo(targetScrollX, 0); 392 | } 393 | } 394 | 395 | /** 396 | * Allows complete control over the colors drawn in the tab layout. Set with 397 | * {@link #setCustomTabColorizer(TabColorizer)}. 398 | */ 399 | public interface TabColorizer { 400 | 401 | /** 402 | * @return return the color of the indicator used when {@code position} is selected. 403 | */ 404 | int getIndicatorColor(int position); 405 | 406 | /** 407 | * @return return the color of the divider drawn to the right of {@code position}. 408 | */ 409 | int getDividerColor(int position); 410 | 411 | } 412 | 413 | /** 414 | * Create the custom tabs in the tab layout. Set with 415 | * {@link #setCustomTabView(com.ogaclejapan.smarttablayout.SmartTabLayout.TabProvider)} 416 | */ 417 | public interface TabProvider { 418 | 419 | /** 420 | * @return Return the View of {@code position} for the Tabs 421 | */ 422 | View createTabView(ViewGroup container, int position, PagerAdapter adapter); 423 | 424 | } 425 | 426 | private static class SimpleTabProvider implements TabProvider { 427 | 428 | private final LayoutInflater inflater; 429 | private final int tabViewLayoutId; 430 | private final int tabViewTextViewId; 431 | 432 | private SimpleTabProvider(Context context, int layoutResId, int textViewId) { 433 | inflater = LayoutInflater.from(context); 434 | tabViewLayoutId = layoutResId; 435 | tabViewTextViewId = textViewId; 436 | } 437 | 438 | @Override 439 | public View createTabView(ViewGroup container, int position, PagerAdapter adapter) { 440 | View tabView = null; 441 | TextView tabTitleView = null; 442 | 443 | if (tabViewLayoutId != NO_ID) { 444 | tabView = inflater.inflate(tabViewLayoutId, container, false); 445 | } 446 | 447 | if (tabViewTextViewId != NO_ID && tabView != null) { 448 | tabTitleView = (TextView) tabView.findViewById(tabViewTextViewId); 449 | } 450 | 451 | if (tabTitleView == null && TextView.class.isInstance(tabView)) { 452 | tabTitleView = (TextView) tabView; 453 | } 454 | 455 | if (tabTitleView != null) { 456 | tabTitleView.setText(adapter.getPageTitle(position)); 457 | } 458 | 459 | return tabView; 460 | } 461 | 462 | } 463 | 464 | private class InternalViewPagerListener implements ViewPager.OnPageChangeListener { 465 | 466 | private int scrollState; 467 | 468 | @Override 469 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 470 | int tabStripChildCount = tabStrip.getChildCount(); 471 | if ((tabStripChildCount == 0) || (position < 0) || (position >= tabStripChildCount)) { 472 | return; 473 | } 474 | 475 | tabStrip.onViewPagerPageChanged(position, positionOffset); 476 | 477 | View selectedTitle = tabStrip.getChildAt(position); 478 | int extraOffset = (selectedTitle != null) 479 | ? (int) (positionOffset * selectedTitle.getWidth()) 480 | : 0; 481 | 482 | if (0f < positionOffset && positionOffset < 1f 483 | && tabStrip.isIndicatorAlwaysInCenter()) { 484 | int current = tabStrip.getChildWidthAt(position) / 2; 485 | int next = tabStrip.getChildWidthAt(position + 1) / 2; 486 | extraOffset = Math.round(positionOffset * (current + next)); 487 | } 488 | 489 | scrollToTab(position, extraOffset); 490 | 491 | if (viewPagerPageChangeListener != null) { 492 | viewPagerPageChangeListener.onPageScrolled(position, positionOffset, 493 | positionOffsetPixels); 494 | } 495 | } 496 | 497 | @Override 498 | public void onPageScrollStateChanged(int state) { 499 | scrollState = state; 500 | 501 | if (viewPagerPageChangeListener != null) { 502 | viewPagerPageChangeListener.onPageScrollStateChanged(state); 503 | } 504 | } 505 | 506 | @Override 507 | public void onPageSelected(int position) { 508 | if (scrollState == ViewPager.SCROLL_STATE_IDLE) { 509 | tabStrip.onViewPagerPageChanged(position, 0f); 510 | scrollToTab(position, 0); 511 | } 512 | 513 | for (int i = 0, size = tabStrip.getChildCount(); i < size; i++) { 514 | tabStrip.getChildAt(i).setSelected(position == i); 515 | } 516 | 517 | if (viewPagerPageChangeListener != null) { 518 | viewPagerPageChangeListener.onPageSelected(position); 519 | } 520 | } 521 | 522 | } 523 | 524 | private class TabClickListener implements OnClickListener { 525 | @Override 526 | public void onClick(View v) { 527 | for (int i = 0; i < tabStrip.getChildCount(); i++) { 528 | if (v == tabStrip.getChildAt(i)) { 529 | viewPager.setCurrentItem(i); 530 | return; 531 | } 532 | } 533 | } 534 | } 535 | 536 | } 537 | -------------------------------------------------------------------------------- /library/src/main/java/com/ogaclejapan/smarttablayout/SmartTabStrip.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 3 | * Copyright (C) 2013 The Android Open Source Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.ogaclejapan.smarttablayout; 18 | 19 | import android.content.Context; 20 | import android.content.res.TypedArray; 21 | import android.graphics.Canvas; 22 | import android.graphics.Color; 23 | import android.graphics.Paint; 24 | import android.graphics.RectF; 25 | import android.util.AttributeSet; 26 | import android.util.TypedValue; 27 | import android.view.View; 28 | import android.widget.LinearLayout; 29 | 30 | /** 31 | *

32 | * Forked from Google Samples > SlidingTabsBasic > 33 | * SlidingTabStrip 34 | */ 35 | class SmartTabStrip extends LinearLayout { 36 | 37 | private static final int DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS = 2; 38 | private static final byte DEFAULT_BOTTOM_BORDER_COLOR_ALPHA = 0x26; 39 | private static final int SELECTED_INDICATOR_THICKNESS_DIPS = 8; 40 | private static final int DEFAULT_SELECTED_INDICATOR_COLOR = 0xFF33B5E5; 41 | private static final float DEFAULT_INDICATOR_CORNER_RADIUS = 0f; 42 | private static final int DEFAULT_DIVIDER_THICKNESS_DIPS = 1; 43 | private static final byte DEFAULT_DIVIDER_COLOR_ALPHA = 0x20; 44 | private static final float DEFAULT_DIVIDER_HEIGHT = 0.5f; 45 | private static final boolean DEFAULT_INDICATOR_IN_CENTER = false; 46 | private static final boolean DEFAULT_INDICATOR_IN_FRONT = false; 47 | 48 | private final int bottomBorderThickness; 49 | private final Paint bottomBorderPaint; 50 | private final RectF indicatorRectF = new RectF(); 51 | private final boolean indicatorAlwaysInCenter; 52 | private final boolean indicatorInFront; 53 | private final int indicatorThickness; 54 | private final float indicatorCornerRadius; 55 | private final Paint indicatorPaint; 56 | private final Paint dividerPaint; 57 | private final float dividerHeight; 58 | private final SimpleTabColorizer defaultTabColorizer; 59 | 60 | private int lastPosition; 61 | private int selectedPosition; 62 | private float selectionOffset; 63 | private SmartTabIndicationInterpolator indicationInterpolator; 64 | private SmartTabLayout.TabColorizer customTabColorizer; 65 | 66 | SmartTabStrip(Context context, AttributeSet attrs) { 67 | super(context); 68 | setWillNotDraw(false); 69 | 70 | final float density = getResources().getDisplayMetrics().density; 71 | 72 | TypedValue outValue = new TypedValue(); 73 | context.getTheme().resolveAttribute(android.R.attr.colorForeground, outValue, true); 74 | final int themeForegroundColor = outValue.data; 75 | 76 | boolean indicatorInFront = DEFAULT_INDICATOR_IN_FRONT; 77 | boolean indicatorAlwaysInCenter = DEFAULT_INDICATOR_IN_CENTER; 78 | int indicationInterpolatorId = SmartTabIndicationInterpolator.ID_SMART; 79 | int indicatorColor = DEFAULT_SELECTED_INDICATOR_COLOR; 80 | int indicatorColorsId = NO_ID; 81 | int indicatorThickness = (int) (SELECTED_INDICATOR_THICKNESS_DIPS * density); 82 | float indicatorCornerRadius = DEFAULT_INDICATOR_CORNER_RADIUS * density; 83 | int underlineColor = setColorAlpha(themeForegroundColor, DEFAULT_BOTTOM_BORDER_COLOR_ALPHA); 84 | int underlineThickness = (int) (DEFAULT_BOTTOM_BORDER_THICKNESS_DIPS * density); 85 | int dividerColor = setColorAlpha(themeForegroundColor, DEFAULT_DIVIDER_COLOR_ALPHA); 86 | int dividerColorsId = NO_ID; 87 | int dividerThickness = (int) (DEFAULT_DIVIDER_THICKNESS_DIPS * density); 88 | 89 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.stl_SmartTabLayout); 90 | indicatorAlwaysInCenter = a.getBoolean( 91 | R.styleable.stl_SmartTabLayout_stl_indicatorAlwaysInCenter, indicatorAlwaysInCenter); 92 | indicatorInFront = a.getBoolean( 93 | R.styleable.stl_SmartTabLayout_stl_indicatorInFront, indicatorInFront); 94 | indicationInterpolatorId = a.getInt( 95 | R.styleable.stl_SmartTabLayout_stl_indicatorInterpolation, indicationInterpolatorId); 96 | indicatorColor = a.getColor( 97 | R.styleable.stl_SmartTabLayout_stl_indicatorColor, indicatorColor); 98 | indicatorColorsId = a.getResourceId( 99 | R.styleable.stl_SmartTabLayout_stl_indicatorColors, indicatorColorsId); 100 | indicatorThickness = a.getDimensionPixelSize( 101 | R.styleable.stl_SmartTabLayout_stl_indicatorThickness, indicatorThickness); 102 | indicatorCornerRadius = a.getDimension( 103 | R.styleable.stl_SmartTabLayout_stl_indicatorCornerRadius, indicatorCornerRadius); 104 | underlineColor = a.getColor( 105 | R.styleable.stl_SmartTabLayout_stl_underlineColor, underlineColor); 106 | underlineThickness = a.getDimensionPixelSize( 107 | R.styleable.stl_SmartTabLayout_stl_underlineThickness, underlineThickness); 108 | dividerColor = a.getColor( 109 | R.styleable.stl_SmartTabLayout_stl_dividerColor, dividerColor); 110 | dividerColorsId = a.getResourceId( 111 | R.styleable.stl_SmartTabLayout_stl_dividerColors, dividerColorsId); 112 | dividerThickness = a.getDimensionPixelSize( 113 | R.styleable.stl_SmartTabLayout_stl_dividerThickness, dividerThickness); 114 | a.recycle(); 115 | 116 | final int[] indicatorColors = (indicatorColorsId == NO_ID) 117 | ? new int[] { indicatorColor } 118 | : getResources().getIntArray(indicatorColorsId); 119 | 120 | final int[] dividerColors = (dividerColorsId == NO_ID) 121 | ? new int[] { dividerColor } 122 | : getResources().getIntArray(dividerColorsId); 123 | 124 | this.defaultTabColorizer = new SimpleTabColorizer(); 125 | this.defaultTabColorizer.setIndicatorColors(indicatorColors); 126 | this.defaultTabColorizer.setDividerColors(dividerColors); 127 | 128 | this.bottomBorderThickness = underlineThickness; 129 | this.bottomBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 130 | this.bottomBorderPaint.setColor(underlineColor); 131 | 132 | this.indicatorAlwaysInCenter = indicatorAlwaysInCenter; 133 | this.indicatorInFront = indicatorInFront; 134 | this.indicatorThickness = indicatorThickness; 135 | this.indicatorPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 136 | this.indicatorCornerRadius = indicatorCornerRadius; 137 | 138 | this.dividerHeight = DEFAULT_DIVIDER_HEIGHT; 139 | this.dividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 140 | this.dividerPaint.setStrokeWidth(dividerThickness); 141 | 142 | this.indicationInterpolator = SmartTabIndicationInterpolator.of(indicationInterpolatorId); 143 | } 144 | 145 | /** 146 | * Set the alpha value of the {@code color} to be the given {@code alpha} value. 147 | */ 148 | private static int setColorAlpha(int color, byte alpha) { 149 | return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color)); 150 | } 151 | 152 | /** 153 | * Blend {@code color1} and {@code color2} using the given ratio. 154 | * 155 | * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend, 156 | * 0.0 will return {@code color2}. 157 | */ 158 | private static int blendColors(int color1, int color2, float ratio) { 159 | final float inverseRation = 1f - ratio; 160 | float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRation); 161 | float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRation); 162 | float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRation); 163 | return Color.rgb((int) r, (int) g, (int) b); 164 | } 165 | 166 | void setIndicationInterpolator(SmartTabIndicationInterpolator interpolator) { 167 | indicationInterpolator = interpolator; 168 | invalidate(); 169 | } 170 | 171 | void setCustomTabColorizer(SmartTabLayout.TabColorizer customTabColorizer) { 172 | this.customTabColorizer = customTabColorizer; 173 | invalidate(); 174 | } 175 | 176 | void setSelectedIndicatorColors(int... colors) { 177 | // Make sure that the custom colorizer is removed 178 | customTabColorizer = null; 179 | defaultTabColorizer.setIndicatorColors(colors); 180 | invalidate(); 181 | } 182 | 183 | void setDividerColors(int... colors) { 184 | // Make sure that the custom colorizer is removed 185 | customTabColorizer = null; 186 | defaultTabColorizer.setDividerColors(colors); 187 | invalidate(); 188 | } 189 | 190 | void onViewPagerPageChanged(int position, float positionOffset) { 191 | selectedPosition = position; 192 | selectionOffset = positionOffset; 193 | if (positionOffset == 0f && lastPosition != selectedPosition) { 194 | lastPosition = selectedPosition; 195 | } 196 | invalidate(); 197 | } 198 | 199 | boolean isIndicatorAlwaysInCenter() { 200 | return indicatorAlwaysInCenter; 201 | } 202 | 203 | int getChildMeasuredWidthAt(int index) { 204 | return getChildAt(index).getMeasuredWidth(); 205 | } 206 | 207 | int getChildWidthAt(int index) { 208 | return getChildAt(index).getWidth(); 209 | } 210 | 211 | @Override 212 | protected void onDraw(Canvas canvas) { 213 | final int height = getHeight(); 214 | final int childCount = getChildCount(); 215 | final int dividerHeightPx = (int) (Math.min(Math.max(0f, dividerHeight), 1f) * height); 216 | final SmartTabLayout.TabColorizer tabColorizer = (customTabColorizer != null) 217 | ? customTabColorizer 218 | : defaultTabColorizer; 219 | 220 | if (indicatorInFront) { 221 | // Thin underline along the entire bottom edge 222 | canvas.drawRect(0, height - bottomBorderThickness, getWidth(), height, 223 | bottomBorderPaint); 224 | } 225 | 226 | // Thick colored underline below the current selection 227 | if (childCount > 0) { 228 | View selectedTitle = getChildAt(selectedPosition); 229 | int left = selectedTitle.getLeft(); 230 | int right = selectedTitle.getRight(); 231 | int color = tabColorizer.getIndicatorColor(selectedPosition); 232 | float thickness = indicatorThickness; 233 | 234 | if (selectionOffset > 0f && selectedPosition < (getChildCount() - 1)) { 235 | int nextColor = tabColorizer.getIndicatorColor(selectedPosition + 1); 236 | if (color != nextColor) { 237 | color = blendColors(nextColor, color, selectionOffset); 238 | } 239 | 240 | // Draw the selection partway between the tabs 241 | float leftOffset = indicationInterpolator.getLeftEdge(selectionOffset); 242 | float rightOffset = indicationInterpolator.getRightEdge(selectionOffset); 243 | float thicknessOffset = indicationInterpolator.getThickness(selectionOffset); 244 | 245 | View nextTitle = getChildAt(selectedPosition + 1); 246 | left = (int) (leftOffset * nextTitle.getLeft() + 247 | (1.0f - leftOffset) * left); 248 | right = (int) (rightOffset * nextTitle.getRight() + 249 | (1.0f - rightOffset) * right); 250 | thickness = thickness * thicknessOffset; 251 | } 252 | 253 | indicatorPaint.setColor(color); 254 | indicatorRectF.set( 255 | left, height - (indicatorThickness / 2f) - (thickness / 2f), 256 | right, height - (indicatorThickness / 2f) + (thickness / 2f)); 257 | 258 | if (indicatorCornerRadius > 0f) { 259 | canvas.drawRoundRect( 260 | indicatorRectF, indicatorCornerRadius, 261 | indicatorCornerRadius, indicatorPaint); 262 | } else { 263 | canvas.drawRect(indicatorRectF, indicatorPaint); 264 | } 265 | } 266 | 267 | if (!indicatorInFront) { 268 | // Thin underline along the entire bottom edge 269 | canvas.drawRect(0, height - bottomBorderThickness, getWidth(), height, 270 | bottomBorderPaint); 271 | } 272 | 273 | // Vertical separators between the titles 274 | int separatorTop = (height - dividerHeightPx) / 2; 275 | for (int i = 0; i < childCount - 1; i++) { 276 | View child = getChildAt(i); 277 | dividerPaint.setColor(tabColorizer.getDividerColor(i)); 278 | canvas.drawLine(child.getRight(), separatorTop, child.getRight(), 279 | separatorTop + dividerHeightPx, dividerPaint); 280 | } 281 | } 282 | 283 | private static class SimpleTabColorizer implements SmartTabLayout.TabColorizer { 284 | 285 | private int[] indicatorColors; 286 | private int[] dividerColors; 287 | 288 | @Override 289 | public final int getIndicatorColor(int position) { 290 | return indicatorColors[position % indicatorColors.length]; 291 | } 292 | 293 | @Override 294 | public final int getDividerColor(int position) { 295 | return dividerColors[position % dividerColors.length]; 296 | } 297 | 298 | void setIndicatorColors(int... colors) { 299 | indicatorColors = colors; 300 | } 301 | 302 | void setDividerColors(int... colors) { 303 | dividerColors = colors; 304 | } 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /library/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':demo', ':library', ':utils-v4', ':utils-v13' 2 | -------------------------------------------------------------------------------- /utils-v13/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /utils-v13/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) ${year} ${name} 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /utils-v13/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.jfrog.bintray' 3 | apply plugin: 'com.github.dcendents.android-maven' 4 | apply plugin: 'license' 5 | 6 | android { 7 | compileSdkVersion COMPILE_SDK_VERSION as int 8 | buildToolsVersion BUILD_TOOLS_VERSION 9 | 10 | defaultConfig { 11 | minSdkVersion 13 12 | targetSdkVersion COMPILE_SDK_VERSION as int 13 | versionCode VERSION_CODE as int 14 | versionName VERSION_NAME 15 | 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | lintOptions { 24 | abortOnError false 25 | } 26 | } 27 | 28 | dependencies { 29 | compile "com.android.support:support-v4:22.0.0" 30 | compile 'com.android.support:support-v13:22.0.0' 31 | } 32 | 33 | license { 34 | 35 | sourceSets { 36 | main.java.srcDirs = android.sourceSets.main.java.srcDirs 37 | main.resources.srcDirs = android.sourceSets.main.resources.srcDirs 38 | } 39 | 40 | ext.year = Calendar.getInstance().get(Calendar.YEAR) 41 | ext.name = DEVELOPER_ID 42 | 43 | } 44 | 45 | install { 46 | repositories.mavenInstaller { 47 | // This generates POM.xml with proper parameters 48 | pom { 49 | project { 50 | packaging 'aar' 51 | 52 | name ARTIFACT_NAME 53 | description ARTIFACT_DESCRIPTION 54 | url SITE_URL 55 | 56 | licenses { 57 | license { 58 | name LICENCE_NAME 59 | url LICENCE_URL 60 | distribution LICENCE_DIST 61 | } 62 | } 63 | 64 | developers { 65 | developer { 66 | id DEVELOPER_ID 67 | name DEVELOPER_NAME 68 | email DEVELOPER_EMAIL 69 | } 70 | } 71 | issueManagement { 72 | system ISSUE_SYSTEM 73 | url ISSUE_URL 74 | } 75 | 76 | scm { 77 | connection SCM_CONNECTION 78 | developerConnection SCM_DEV_CONNECTION 79 | url SCM_URL 80 | 81 | } 82 | } 83 | } 84 | } 85 | } 86 | 87 | afterEvaluate { project -> 88 | 89 | task sourcesJar(type: Jar) { 90 | from android.sourceSets.main.java.srcDirs 91 | classifier = 'sources' 92 | } 93 | 94 | task javadoc(type: Javadoc) { 95 | failOnError false 96 | source = android.sourceSets.main.java.srcDirs 97 | options { 98 | links "http://docs.oracle.com/javase/7/docs/api/" 99 | linksOffline "http://d.android.com/reference", System.getenv("ANDROID_HOME") + "/docs/reference" 100 | } 101 | classpath += project.android.libraryVariants.toList().first().javaCompile.classpath 102 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 103 | 104 | } 105 | 106 | task javadocJar(type: Jar, dependsOn: javadoc) { 107 | classifier = 'javadoc' 108 | from javadoc.destinationDir 109 | } 110 | 111 | artifacts { 112 | archives javadocJar 113 | archives sourcesJar 114 | } 115 | 116 | } 117 | 118 | def getNexusUser() { 119 | return hasProperty('NEXUS_USER') ? NEXUS_USER : "" 120 | } 121 | 122 | def getNexusPassword() { 123 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" 124 | } 125 | 126 | def getBintrayUser() { 127 | return hasProperty('BINTRAY_USER') ? BINTRAY_USER : "" 128 | } 129 | 130 | def getBintrayApiKey() { 131 | return hasProperty('BINTRAY_APIKEY') ? BINTRAY_APIKEY : "" 132 | } 133 | 134 | def getGpgPassphrase() { 135 | return hasProperty('BINTRAY_GPG_PASSPHRASE') ? BINTRAY_GPG_PASSPHRASE : "" 136 | } 137 | 138 | bintray { 139 | 140 | user = bintrayUser 141 | key = bintrayApiKey 142 | 143 | configurations = ['archives'] 144 | 145 | dryRun = false 146 | publish = true 147 | 148 | pkg { 149 | repo = "maven" 150 | name = ARTIFACT_NAME + "-V13Utils" 151 | desc = ARTIFACT_DESCRIPTION 152 | websiteUrl = SITE_URL 153 | issueTrackerUrl = ISSUE_URL 154 | vcsUrl = SCM_URL 155 | licenses = ["Apache-2.0"] 156 | labels = ['android'] 157 | publicDownloadNumbers = true 158 | 159 | version { 160 | gpg { 161 | sign = true 162 | passphrase = gpgPassphrase 163 | } 164 | 165 | mavenCentralSync { 166 | sync = true 167 | user = nexusUser 168 | password = nexusPassword 169 | } 170 | 171 | } 172 | 173 | } 174 | 175 | } 176 | -------------------------------------------------------------------------------- /utils-v13/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 /Users/msk/Library/Android/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 | -------------------------------------------------------------------------------- /utils-v13/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/PagerItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | public abstract class PagerItem { 19 | 20 | protected static final float DEFAULT_WIDTH = 1.f; 21 | 22 | private final CharSequence title; 23 | private final float width; 24 | 25 | protected PagerItem(CharSequence title, float width) { 26 | this.title = title; 27 | this.width = width; 28 | } 29 | 30 | public CharSequence getTitle() { 31 | return title; 32 | } 33 | 34 | public float getWidth() { 35 | return width; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/PagerItems.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | import android.content.Context; 19 | 20 | import java.util.ArrayList; 21 | 22 | public abstract class PagerItems extends ArrayList { 23 | 24 | private final Context context; 25 | 26 | protected PagerItems(Context context) { 27 | this.context = context; 28 | } 29 | 30 | public Context getContext() { 31 | return context; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/ViewPagerItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | import android.support.annotation.LayoutRes; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | 23 | public class ViewPagerItem extends PagerItem { 24 | 25 | private final int resource; 26 | 27 | protected ViewPagerItem(CharSequence title, float width, @LayoutRes int resource) { 28 | super(title, width); 29 | this.resource = resource; 30 | } 31 | 32 | public static ViewPagerItem of(CharSequence title, @LayoutRes int resource) { 33 | return of(title, DEFAULT_WIDTH, resource); 34 | } 35 | 36 | public static ViewPagerItem of(CharSequence title, float width, @LayoutRes int resource) { 37 | return new ViewPagerItem(title, width, resource); 38 | } 39 | 40 | public View initiate(LayoutInflater inflater, ViewGroup container) { 41 | return inflater.inflate(resource, container, false); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/ViewPagerItemAdapter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | import android.support.v4.util.SparseArrayCompat; 19 | import android.support.v4.view.PagerAdapter; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | 24 | import java.lang.ref.WeakReference; 25 | 26 | public class ViewPagerItemAdapter extends PagerAdapter { 27 | 28 | private final ViewPagerItems pages; 29 | private final SparseArrayCompat> holder; 30 | private final LayoutInflater inflater; 31 | 32 | public ViewPagerItemAdapter(ViewPagerItems pages) { 33 | this.pages = pages; 34 | this.holder = new SparseArrayCompat<>(pages.size()); 35 | this.inflater = LayoutInflater.from(pages.getContext()); 36 | } 37 | 38 | @Override 39 | public int getCount() { 40 | return pages.size(); 41 | } 42 | 43 | @Override 44 | public Object instantiateItem(ViewGroup container, int position) { 45 | View view = getPagerItem(position).initiate(inflater, container); 46 | container.addView(view); 47 | holder.put(position, new WeakReference(view)); 48 | return view; 49 | } 50 | 51 | @Override 52 | public void destroyItem(ViewGroup container, int position, Object object) { 53 | holder.remove(position); 54 | container.removeView((View) object); 55 | } 56 | 57 | @Override 58 | public boolean isViewFromObject(View view, Object object) { 59 | return object == view; 60 | } 61 | 62 | @Override 63 | public CharSequence getPageTitle(int position) { 64 | return getPagerItem(position).getTitle(); 65 | } 66 | 67 | @Override 68 | public float getPageWidth(int position) { 69 | return getPagerItem(position).getWidth(); 70 | } 71 | 72 | public View getPage(int position) { 73 | final WeakReference weakRefItem = holder.get(position); 74 | return (weakRefItem != null) ? weakRefItem.get() : null; 75 | } 76 | 77 | protected ViewPagerItem getPagerItem(int position) { 78 | return pages.get(position); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/ViewPagerItems.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | import android.content.Context; 19 | import android.support.annotation.LayoutRes; 20 | import android.support.annotation.StringRes; 21 | 22 | public class ViewPagerItems extends PagerItems { 23 | 24 | public ViewPagerItems(Context context) { 25 | super(context); 26 | } 27 | 28 | public static Creator with(Context context) { 29 | return new Creator(context); 30 | } 31 | 32 | public static class Creator { 33 | 34 | private final ViewPagerItems items; 35 | 36 | public Creator(Context context) { 37 | items = new ViewPagerItems(context); 38 | } 39 | 40 | public Creator add(@StringRes int title, @LayoutRes int resource) { 41 | return add(ViewPagerItem.of(items.getContext().getString(title), resource)); 42 | } 43 | 44 | public Creator add(@StringRes int title, float width, @LayoutRes int resource) { 45 | return add(ViewPagerItem.of(items.getContext().getString(title), width, resource)); 46 | } 47 | 48 | public Creator add(CharSequence title, @LayoutRes int resource) { 49 | return add(ViewPagerItem.of(title, resource)); 50 | } 51 | 52 | public Creator add(ViewPagerItem item) { 53 | items.add(item); 54 | return this; 55 | } 56 | 57 | public ViewPagerItems create() { 58 | return items; 59 | } 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/v13/Bundler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v13; 17 | 18 | import android.annotation.TargetApi; 19 | import android.app.Fragment; 20 | import android.os.Bundle; 21 | import android.os.IBinder; 22 | import android.os.Parcelable; 23 | import android.util.Size; 24 | import android.util.SizeF; 25 | import android.util.SparseArray; 26 | 27 | import java.io.Serializable; 28 | import java.util.ArrayList; 29 | 30 | public class Bundler { 31 | 32 | private final Bundle bundle; 33 | 34 | /** 35 | * Constructs a new, empty Bundle. 36 | */ 37 | public Bundler() { 38 | this(null); 39 | } 40 | 41 | private Bundler(Bundle b) { 42 | bundle = (b == null) ? new Bundle() : new Bundle(b); 43 | } 44 | 45 | /** 46 | * Constructs a Bundle containing a copy of the mappings from the given 47 | * Bundle. 48 | * 49 | * @param b a Bundle to be copied. 50 | */ 51 | public static Bundler of(Bundle b) { 52 | return new Bundler(b); 53 | } 54 | 55 | /** 56 | * Inserts all mappings from the given Bundle into this Bundle. 57 | * 58 | * @param bundle a Bundle 59 | */ 60 | public Bundler putAll(Bundle bundle) { 61 | this.bundle.putAll(bundle); 62 | return this; 63 | } 64 | 65 | /** 66 | * Inserts a byte value into the mapping of this Bundle, replacing 67 | * any existing value for the given key. 68 | * 69 | * @param key a String, or null 70 | * @param value a byte 71 | */ 72 | public Bundler putByte(String key, byte value) { 73 | bundle.putByte(key, value); 74 | return this; 75 | } 76 | 77 | /** 78 | * Inserts a char value into the mapping of this Bundle, replacing 79 | * any existing value for the given key. 80 | * 81 | * @param key a String, or null 82 | * @param value a char, or null 83 | */ 84 | public Bundler putChar(String key, char value) { 85 | bundle.putChar(key, value); 86 | return this; 87 | } 88 | 89 | /** 90 | * Inserts a short value into the mapping of this Bundle, replacing 91 | * any existing value for the given key. 92 | * 93 | * @param key a String, or null 94 | * @param value a short 95 | */ 96 | public Bundler putShort(String key, short value) { 97 | bundle.putShort(key, value); 98 | return this; 99 | } 100 | 101 | /** 102 | * Inserts a float value into the mapping of this Bundle, replacing 103 | * any existing value for the given key. 104 | * 105 | * @param key a String, or null 106 | * @param value a float 107 | */ 108 | public Bundler putFloat(String key, float value) { 109 | bundle.putFloat(key, value); 110 | return this; 111 | } 112 | 113 | /** 114 | * Inserts a CharSequence value into the mapping of this Bundle, replacing 115 | * any existing value for the given key. Either key or value may be null. 116 | * 117 | * @param key a String, or null 118 | * @param value a CharSequence, or null 119 | */ 120 | public Bundler putCharSequence(String key, CharSequence value) { 121 | bundle.putCharSequence(key, value); 122 | return this; 123 | } 124 | 125 | /** 126 | * Inserts a Parcelable value into the mapping of this Bundle, replacing 127 | * any existing value for the given key. Either key or value may be null. 128 | * 129 | * @param key a String, or null 130 | * @param value a Parcelable object, or null 131 | */ 132 | public Bundler putParcelable(String key, Parcelable value) { 133 | bundle.putParcelable(key, value); 134 | return this; 135 | } 136 | 137 | /** 138 | * Inserts a Size value into the mapping of this Bundle, replacing 139 | * any existing value for the given key. Either key or value may be null. 140 | * 141 | * @param key a String, or null 142 | * @param value a Size object, or null 143 | */ 144 | @TargetApi(21) 145 | public Bundler putSize(String key, Size value) { 146 | bundle.putSize(key, value); 147 | return this; 148 | } 149 | 150 | /** 151 | * Inserts a SizeF value into the mapping of this Bundle, replacing 152 | * any existing value for the given key. Either key or value may be null. 153 | * 154 | * @param key a String, or null 155 | * @param value a SizeF object, or null 156 | */ 157 | @TargetApi(21) 158 | public Bundler putSizeF(String key, SizeF value) { 159 | bundle.putSizeF(key, value); 160 | return this; 161 | } 162 | 163 | /** 164 | * Inserts an array of Parcelable values into the mapping of this Bundle, 165 | * replacing any existing value for the given key. Either key or value may 166 | * be null. 167 | * 168 | * @param key a String, or null 169 | * @param value an array of Parcelable objects, or null 170 | */ 171 | public Bundler putParcelableArray(String key, Parcelable[] value) { 172 | bundle.putParcelableArray(key, value); 173 | return this; 174 | } 175 | 176 | /** 177 | * Inserts a List of Parcelable values into the mapping of this Bundle, 178 | * replacing any existing value for the given key. Either key or value may 179 | * be null. 180 | * 181 | * @param key a String, or null 182 | * @param value an ArrayList of Parcelable objects, or null 183 | */ 184 | public Bundler putParcelableArrayList(String key, 185 | ArrayList value) { 186 | bundle.putParcelableArrayList(key, value); 187 | return this; 188 | } 189 | 190 | /** 191 | * Inserts a SparceArray of Parcelable values into the mapping of this 192 | * Bundle, replacing any existing value for the given key. Either key 193 | * or value may be null. 194 | * 195 | * @param key a String, or null 196 | * @param value a SparseArray of Parcelable objects, or null 197 | */ 198 | public Bundler putSparseParcelableArray(String key, 199 | SparseArray value) { 200 | bundle.putSparseParcelableArray(key, value); 201 | return this; 202 | } 203 | 204 | /** 205 | * Inserts an ArrayList value into the mapping of this Bundle, replacing 206 | * any existing value for the given key. Either key or value may be null. 207 | * 208 | * @param key a String, or null 209 | * @param value an ArrayList object, or null 210 | */ 211 | public Bundler putIntegerArrayList(String key, ArrayList value) { 212 | bundle.putIntegerArrayList(key, value); 213 | return this; 214 | } 215 | 216 | /** 217 | * Inserts an ArrayList value into the mapping of this Bundle, replacing 218 | * any existing value for the given key. Either key or value may be null. 219 | * 220 | * @param key a String, or null 221 | * @param value an ArrayList object, or null 222 | */ 223 | public Bundler putStringArrayList(String key, ArrayList value) { 224 | bundle.putStringArrayList(key, value); 225 | return this; 226 | } 227 | 228 | /** 229 | * Inserts an ArrayList value into the mapping of this Bundle, replacing 230 | * any existing value for the given key. Either key or value may be null. 231 | * 232 | * @param key a String, or null 233 | * @param value an ArrayList object, or null 234 | */ 235 | @TargetApi(8) 236 | public Bundler putCharSequenceArrayList(String key, ArrayList value) { 237 | bundle.putCharSequenceArrayList(key, value); 238 | return this; 239 | } 240 | 241 | /** 242 | * Inserts a Serializable value into the mapping of this Bundle, replacing 243 | * any existing value for the given key. Either key or value may be null. 244 | * 245 | * @param key a String, or null 246 | * @param value a Serializable object, or null 247 | */ 248 | public Bundler putSerializable(String key, Serializable value) { 249 | bundle.putSerializable(key, value); 250 | return this; 251 | } 252 | 253 | /** 254 | * Inserts a byte array value into the mapping of this Bundle, replacing 255 | * any existing value for the given key. Either key or value may be null. 256 | * 257 | * @param key a String, or null 258 | * @param value a byte array object, or null 259 | */ 260 | public Bundler putByteArray(String key, byte[] value) { 261 | bundle.putByteArray(key, value); 262 | return this; 263 | } 264 | 265 | /** 266 | * Inserts a short array value into the mapping of this Bundle, replacing 267 | * any existing value for the given key. Either key or value may be null. 268 | * 269 | * @param key a String, or null 270 | * @param value a short array object, or null 271 | */ 272 | public Bundler putShortArray(String key, short[] value) { 273 | bundle.putShortArray(key, value); 274 | return this; 275 | } 276 | 277 | /** 278 | * Inserts a char array value into the mapping of this Bundle, replacing 279 | * any existing value for the given key. Either key or value may be null. 280 | * 281 | * @param key a String, or null 282 | * @param value a char array object, or null 283 | */ 284 | public Bundler putCharArray(String key, char[] value) { 285 | bundle.putCharArray(key, value); 286 | return this; 287 | } 288 | 289 | /** 290 | * Inserts a float array value into the mapping of this Bundle, replacing 291 | * any existing value for the given key. Either key or value may be null. 292 | * 293 | * @param key a String, or null 294 | * @param value a float array object, or null 295 | */ 296 | public Bundler putFloatArray(String key, float[] value) { 297 | bundle.putFloatArray(key, value); 298 | return this; 299 | } 300 | 301 | /** 302 | * Inserts a CharSequence array value into the mapping of this Bundle, replacing 303 | * any existing value for the given key. Either key or value may be null. 304 | * 305 | * @param key a String, or null 306 | * @param value a CharSequence array object, or null 307 | */ 308 | @TargetApi(8) 309 | public Bundler putCharSequenceArray(String key, CharSequence[] value) { 310 | bundle.putCharSequenceArray(key, value); 311 | return this; 312 | } 313 | 314 | /** 315 | * Inserts a Bundle value into the mapping of this Bundle, replacing 316 | * any existing value for the given key. Either key or value may be null. 317 | * 318 | * @param key a String, or null 319 | * @param value a Bundle object, or null 320 | */ 321 | public Bundler putBundle(String key, Bundle value) { 322 | bundle.putBundle(key, value); 323 | return this; 324 | } 325 | 326 | /** 327 | * Inserts an {@link android.os.IBinder} value into the mapping of this Bundle, replacing 328 | * any existing value for the given key. Either key or value may be null. 329 | * 330 | *

You should be very careful when using this function. In many 331 | * places where Bundles are used (such as inside of Intent objects), the Bundle 332 | * can live longer inside of another process than the process that had originally 333 | * created it. In that case, the IBinder you supply here will become invalid 334 | * when your process goes away, and no longer usable, even if a new process is 335 | * created for you later on.

336 | * 337 | * @param key a String, or null 338 | * @param value an IBinder object, or null 339 | */ 340 | @TargetApi(18) 341 | public Bundler putBinder(String key, IBinder value) { 342 | bundle.putBinder(key, value); 343 | return this; 344 | } 345 | 346 | /** 347 | * Inserts a Boolean value into the mapping of this Bundle, replacing 348 | * any existing value for the given key. Either key or value may be null. 349 | * 350 | * @param key a String, or null 351 | * @param value a Boolean, or null 352 | */ 353 | public Bundler putBoolean(String key, boolean value) { 354 | bundle.putBoolean(key, value); 355 | return this; 356 | } 357 | 358 | /** 359 | * Inserts an int value into the mapping of this Bundle, replacing 360 | * any existing value for the given key. 361 | * 362 | * @param key a String, or null 363 | * @param value an int, or null 364 | */ 365 | public Bundler putInt(String key, int value) { 366 | bundle.putInt(key, value); 367 | return this; 368 | } 369 | 370 | /** 371 | * Inserts a long value into the mapping of this Bundle, replacing 372 | * any existing value for the given key. 373 | * 374 | * @param key a String, or null 375 | * @param value a long 376 | */ 377 | public Bundler putLong(String key, long value) { 378 | bundle.putLong(key, value); 379 | return this; 380 | } 381 | 382 | /** 383 | * Inserts a double value into the mapping of this Bundle, replacing 384 | * any existing value for the given key. 385 | * 386 | * @param key a String, or null 387 | * @param value a double 388 | */ 389 | public Bundler putDouble(String key, double value) { 390 | bundle.putDouble(key, value); 391 | return this; 392 | } 393 | 394 | /** 395 | * Inserts a String value into the mapping of this Bundle, replacing 396 | * any existing value for the given key. Either key or value may be null. 397 | * 398 | * @param key a String, or null 399 | * @param value a String, or null 400 | */ 401 | public Bundler putString(String key, String value) { 402 | bundle.putString(key, value); 403 | return this; 404 | } 405 | 406 | /** 407 | * Inserts a boolean array value into the mapping of this Bundle, replacing 408 | * any existing value for the given key. Either key or value may be null. 409 | * 410 | * @param key a String, or null 411 | * @param value a boolean array object, or null 412 | */ 413 | public Bundler putBooleanArray(String key, boolean[] value) { 414 | bundle.putBooleanArray(key, value); 415 | return this; 416 | } 417 | 418 | /** 419 | * Inserts an int array value into the mapping of this Bundle, replacing 420 | * any existing value for the given key. Either key or value may be null. 421 | * 422 | * @param key a String, or null 423 | * @param value an int array object, or null 424 | */ 425 | public Bundler putIntArray(String key, int[] value) { 426 | bundle.putIntArray(key, value); 427 | return this; 428 | } 429 | 430 | /** 431 | * Inserts a long array value into the mapping of this Bundle, replacing 432 | * any existing value for the given key. Either key or value may be null. 433 | * 434 | * @param key a String, or null 435 | * @param value a long array object, or null 436 | */ 437 | public Bundler putLongArray(String key, long[] value) { 438 | bundle.putLongArray(key, value); 439 | return this; 440 | } 441 | 442 | /** 443 | * Inserts a double array value into the mapping of this Bundle, replacing 444 | * any existing value for the given key. Either key or value may be null. 445 | * 446 | * @param key a String, or null 447 | * @param value a double array object, or null 448 | */ 449 | public Bundler putDoubleArray(String key, double[] value) { 450 | bundle.putDoubleArray(key, value); 451 | return this; 452 | } 453 | 454 | /** 455 | * Inserts a String array value into the mapping of this Bundle, replacing 456 | * any existing value for the given key. Either key or value may be null. 457 | * 458 | * @param key a String, or null 459 | * @param value a String array object, or null 460 | */ 461 | public Bundler putStringArray(String key, String[] value) { 462 | bundle.putStringArray(key, value); 463 | return this; 464 | } 465 | 466 | /** 467 | * Get the bundle. 468 | * 469 | * @return a bundle 470 | */ 471 | public Bundle get() { 472 | return bundle; 473 | } 474 | 475 | /** 476 | * Set the argument of Fragment. 477 | * 478 | * @param fragment a fragment 479 | * @return a fragment 480 | */ 481 | public T into(T fragment) { 482 | fragment.setArguments(get()); 483 | return fragment; 484 | } 485 | 486 | } 487 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/v13/FragmentPagerItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v13; 17 | 18 | import android.app.Fragment; 19 | import android.content.Context; 20 | import android.os.Bundle; 21 | 22 | import com.ogaclejapan.smarttablayout.utils.PagerItem; 23 | 24 | public class FragmentPagerItem extends PagerItem { 25 | 26 | private static final String TAG = "FragmentPagerItem"; 27 | private static final String KEY_POSITION = TAG + ":Position"; 28 | 29 | private final String className; 30 | private final Bundle args; 31 | 32 | protected FragmentPagerItem(CharSequence title, float width, String className, Bundle args) { 33 | super(title, width); 34 | this.className = className; 35 | this.args = args; 36 | } 37 | 38 | public static FragmentPagerItem of(CharSequence title, Class clazz) { 39 | return of(title, DEFAULT_WIDTH, clazz); 40 | } 41 | 42 | public static FragmentPagerItem of(CharSequence title, Class clazz, 43 | Bundle args) { 44 | return of(title, DEFAULT_WIDTH, clazz, args); 45 | } 46 | 47 | public static FragmentPagerItem of(CharSequence title, float width, 48 | Class clazz) { 49 | return of(title, width, clazz, new Bundle()); 50 | } 51 | 52 | public static FragmentPagerItem of(CharSequence title, float width, 53 | Class clazz, Bundle args) { 54 | return new FragmentPagerItem(title, width, clazz.getName(), args); 55 | } 56 | 57 | public static boolean hasPosition(Bundle args) { 58 | return args != null && args.containsKey(KEY_POSITION); 59 | } 60 | 61 | public static int getPosition(Bundle args) { 62 | return (hasPosition(args)) ? args.getInt(KEY_POSITION) : 0; 63 | } 64 | 65 | static void setPosition(Bundle args, int position) { 66 | args.putInt(KEY_POSITION, position); 67 | } 68 | 69 | public Fragment instantiate(Context context, int position) { 70 | setPosition(args, position); 71 | return Fragment.instantiate(context, className, args); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/v13/FragmentPagerItemAdapter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v13; 17 | 18 | import android.app.Fragment; 19 | import android.app.FragmentManager; 20 | import android.support.v13.app.FragmentPagerAdapter; 21 | import android.support.v4.util.SparseArrayCompat; 22 | import android.view.ViewGroup; 23 | 24 | import java.lang.ref.WeakReference; 25 | 26 | public class FragmentPagerItemAdapter extends FragmentPagerAdapter { 27 | 28 | private final FragmentPagerItems pages; 29 | private final SparseArrayCompat> holder; 30 | 31 | public FragmentPagerItemAdapter(FragmentManager fm, FragmentPagerItems pages) { 32 | super(fm); 33 | this.pages = pages; 34 | this.holder = new SparseArrayCompat<>(pages.size()); 35 | } 36 | 37 | @Override 38 | public int getCount() { 39 | return pages.size(); 40 | } 41 | 42 | @Override 43 | public Fragment getItem(int position) { 44 | return getPagerItem(position).instantiate(pages.getContext(), position); 45 | } 46 | 47 | @Override 48 | public Object instantiateItem(ViewGroup container, int position) { 49 | Object item = super.instantiateItem(container, position); 50 | if (item instanceof Fragment) { 51 | holder.put(position, new WeakReference((Fragment) item)); 52 | } 53 | return item; 54 | } 55 | 56 | @Override 57 | public void destroyItem(ViewGroup container, int position, Object object) { 58 | holder.remove(position); 59 | super.destroyItem(container, position, object); 60 | } 61 | 62 | @Override 63 | public CharSequence getPageTitle(int position) { 64 | return getPagerItem(position).getTitle(); 65 | } 66 | 67 | @Override 68 | public float getPageWidth(int position) { 69 | return getPagerItem(position).getWidth(); 70 | } 71 | 72 | public Fragment getPage(int position) { 73 | final WeakReference weakRefItem = holder.get(position); 74 | return (weakRefItem != null) ? weakRefItem.get() : null; 75 | } 76 | 77 | protected FragmentPagerItem getPagerItem(int position) { 78 | return pages.get(position); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/v13/FragmentPagerItems.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v13; 17 | 18 | import android.app.Fragment; 19 | import android.content.Context; 20 | import android.os.Bundle; 21 | import android.support.annotation.StringRes; 22 | 23 | import com.ogaclejapan.smarttablayout.utils.PagerItems; 24 | 25 | public class FragmentPagerItems extends PagerItems { 26 | 27 | public FragmentPagerItems(Context context) { 28 | super(context); 29 | } 30 | 31 | public static Creator with(Context context) { 32 | return new Creator(context); 33 | } 34 | 35 | public static class Creator { 36 | 37 | private final FragmentPagerItems items; 38 | 39 | public Creator(Context context) { 40 | items = new FragmentPagerItems(context); 41 | } 42 | 43 | public Creator add(@StringRes int title, Class clazz) { 44 | return add(FragmentPagerItem.of(items.getContext().getString(title), clazz)); 45 | } 46 | 47 | public Creator add(@StringRes int title, Class clazz, Bundle args) { 48 | return add(FragmentPagerItem.of(items.getContext().getString(title), clazz, args)); 49 | } 50 | 51 | public Creator add(@StringRes int title, float width, Class clazz) { 52 | return add(FragmentPagerItem.of(items.getContext().getString(title), width, clazz)); 53 | } 54 | 55 | public Creator add(@StringRes int title, float width, Class clazz, 56 | Bundle args) { 57 | return add(FragmentPagerItem.of(items.getContext().getString(title), width, clazz, args)); 58 | } 59 | 60 | public Creator add(CharSequence title, Class clazz) { 61 | return add(FragmentPagerItem.of(title, clazz)); 62 | } 63 | 64 | public Creator add(CharSequence title, Class clazz, Bundle args) { 65 | return add(FragmentPagerItem.of(title, clazz, args)); 66 | } 67 | 68 | public Creator add(FragmentPagerItem item) { 69 | items.add(item); 70 | return this; 71 | } 72 | 73 | public FragmentPagerItems create() { 74 | return items; 75 | } 76 | 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /utils-v13/src/main/java/com/ogaclejapan/smarttablayout/utils/v13/FragmentStatePagerItemAdapter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v13; 17 | 18 | import android.app.Fragment; 19 | import android.app.FragmentManager; 20 | import android.support.v13.app.FragmentStatePagerAdapter; 21 | import android.support.v4.util.SparseArrayCompat; 22 | import android.view.ViewGroup; 23 | 24 | import java.lang.ref.WeakReference; 25 | 26 | public class FragmentStatePagerItemAdapter extends FragmentStatePagerAdapter { 27 | 28 | private final FragmentPagerItems pages; 29 | private final SparseArrayCompat> holder; 30 | 31 | public FragmentStatePagerItemAdapter(FragmentManager fm, FragmentPagerItems pages) { 32 | super(fm); 33 | this.pages = pages; 34 | this.holder = new SparseArrayCompat<>(pages.size()); 35 | } 36 | 37 | @Override 38 | public int getCount() { 39 | return pages.size(); 40 | } 41 | 42 | @Override 43 | public Fragment getItem(int position) { 44 | return getPagerItem(position).instantiate(pages.getContext(), position); 45 | } 46 | 47 | @Override 48 | public Object instantiateItem(ViewGroup container, int position) { 49 | Object item = super.instantiateItem(container, position); 50 | if (item instanceof Fragment) { 51 | holder.put(position, new WeakReference((Fragment) item)); 52 | } 53 | return item; 54 | } 55 | 56 | @Override 57 | public void destroyItem(ViewGroup container, int position, Object object) { 58 | holder.remove(position); 59 | super.destroyItem(container, position, object); 60 | } 61 | 62 | @Override 63 | public CharSequence getPageTitle(int position) { 64 | return getPagerItem(position).getTitle(); 65 | } 66 | 67 | @Override 68 | public float getPageWidth(int position) { 69 | return getPagerItem(position).getWidth(); 70 | } 71 | 72 | public Fragment getPage(int position) { 73 | final WeakReference weakRefItem = holder.get(position); 74 | return (weakRefItem != null) ? weakRefItem.get() : null; 75 | } 76 | 77 | protected FragmentPagerItem getPagerItem(int position) { 78 | return pages.get(position); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /utils-v4/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /utils-v4/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) ${year} ${name} 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /utils-v4/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.jfrog.bintray' 3 | apply plugin: 'com.github.dcendents.android-maven' 4 | apply plugin: 'license' 5 | 6 | android { 7 | compileSdkVersion COMPILE_SDK_VERSION as int 8 | buildToolsVersion BUILD_TOOLS_VERSION 9 | 10 | defaultConfig { 11 | minSdkVersion 4 12 | targetSdkVersion COMPILE_SDK_VERSION as int 13 | versionCode VERSION_CODE as int 14 | versionName VERSION_NAME 15 | 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | lintOptions { 24 | abortOnError false 25 | } 26 | } 27 | 28 | dependencies { 29 | compile "com.android.support:support-v4:22.0.0" 30 | } 31 | 32 | license { 33 | 34 | sourceSets { 35 | main.java.srcDirs = android.sourceSets.main.java.srcDirs 36 | main.resources.srcDirs = android.sourceSets.main.resources.srcDirs 37 | } 38 | 39 | ext.year = Calendar.getInstance().get(Calendar.YEAR) 40 | ext.name = DEVELOPER_ID 41 | 42 | } 43 | 44 | install { 45 | repositories.mavenInstaller { 46 | // This generates POM.xml with proper parameters 47 | pom { 48 | project { 49 | packaging 'aar' 50 | 51 | name ARTIFACT_NAME 52 | description ARTIFACT_DESCRIPTION 53 | url SITE_URL 54 | 55 | licenses { 56 | license { 57 | name LICENCE_NAME 58 | url LICENCE_URL 59 | distribution LICENCE_DIST 60 | } 61 | } 62 | 63 | developers { 64 | developer { 65 | id DEVELOPER_ID 66 | name DEVELOPER_NAME 67 | email DEVELOPER_EMAIL 68 | } 69 | } 70 | issueManagement { 71 | system ISSUE_SYSTEM 72 | url ISSUE_URL 73 | } 74 | 75 | scm { 76 | connection SCM_CONNECTION 77 | developerConnection SCM_DEV_CONNECTION 78 | url SCM_URL 79 | 80 | } 81 | } 82 | } 83 | } 84 | } 85 | 86 | afterEvaluate { project -> 87 | 88 | task sourcesJar(type: Jar) { 89 | from android.sourceSets.main.java.srcDirs 90 | classifier = 'sources' 91 | } 92 | 93 | task javadoc(type: Javadoc) { 94 | failOnError false 95 | source = android.sourceSets.main.java.srcDirs 96 | options { 97 | links "http://docs.oracle.com/javase/7/docs/api/" 98 | linksOffline "http://d.android.com/reference", System.getenv("ANDROID_HOME") + "/docs/reference" 99 | } 100 | classpath += project.android.libraryVariants.toList().first().javaCompile.classpath 101 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 102 | 103 | } 104 | 105 | task javadocJar(type: Jar, dependsOn: javadoc) { 106 | classifier = 'javadoc' 107 | from javadoc.destinationDir 108 | } 109 | 110 | artifacts { 111 | archives javadocJar 112 | archives sourcesJar 113 | } 114 | 115 | } 116 | 117 | def getNexusUser() { 118 | return hasProperty('NEXUS_USER') ? NEXUS_USER : "" 119 | } 120 | 121 | def getNexusPassword() { 122 | return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : "" 123 | } 124 | 125 | def getBintrayUser() { 126 | return hasProperty('BINTRAY_USER') ? BINTRAY_USER : "" 127 | } 128 | 129 | def getBintrayApiKey() { 130 | return hasProperty('BINTRAY_APIKEY') ? BINTRAY_APIKEY : "" 131 | } 132 | 133 | def getGpgPassphrase() { 134 | return hasProperty('BINTRAY_GPG_PASSPHRASE') ? BINTRAY_GPG_PASSPHRASE : "" 135 | } 136 | 137 | bintray { 138 | 139 | user = bintrayUser 140 | key = bintrayApiKey 141 | 142 | configurations = ['archives'] 143 | 144 | dryRun = false 145 | publish = true 146 | 147 | pkg { 148 | repo = "maven" 149 | name = ARTIFACT_NAME + "-V4Utils" 150 | desc = ARTIFACT_DESCRIPTION 151 | websiteUrl = SITE_URL 152 | issueTrackerUrl = ISSUE_URL 153 | vcsUrl = SCM_URL 154 | licenses = ["Apache-2.0"] 155 | labels = ['android'] 156 | publicDownloadNumbers = true 157 | 158 | version { 159 | gpg { 160 | sign = true 161 | passphrase = gpgPassphrase 162 | } 163 | 164 | mavenCentralSync { 165 | sync = true 166 | user = nexusUser 167 | password = nexusPassword 168 | } 169 | 170 | } 171 | 172 | } 173 | 174 | } 175 | -------------------------------------------------------------------------------- /utils-v4/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 /Users/msk/Library/Android/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 | -------------------------------------------------------------------------------- /utils-v4/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/PagerItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | public abstract class PagerItem { 19 | 20 | protected static final float DEFAULT_WIDTH = 1.f; 21 | 22 | private final CharSequence title; 23 | private final float width; 24 | 25 | protected PagerItem(CharSequence title, float width) { 26 | this.title = title; 27 | this.width = width; 28 | } 29 | 30 | public CharSequence getTitle() { 31 | return title; 32 | } 33 | 34 | public float getWidth() { 35 | return width; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/PagerItems.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | import android.content.Context; 19 | 20 | import java.util.ArrayList; 21 | 22 | public abstract class PagerItems extends ArrayList { 23 | 24 | private final Context context; 25 | 26 | protected PagerItems(Context context) { 27 | this.context = context; 28 | } 29 | 30 | public Context getContext() { 31 | return context; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/ViewPagerItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | import android.support.annotation.LayoutRes; 19 | import android.view.LayoutInflater; 20 | import android.view.View; 21 | import android.view.ViewGroup; 22 | 23 | public class ViewPagerItem extends PagerItem { 24 | 25 | private final int resource; 26 | 27 | protected ViewPagerItem(CharSequence title, float width, @LayoutRes int resource) { 28 | super(title, width); 29 | this.resource = resource; 30 | } 31 | 32 | public static ViewPagerItem of(CharSequence title, @LayoutRes int resource) { 33 | return of(title, DEFAULT_WIDTH, resource); 34 | } 35 | 36 | public static ViewPagerItem of(CharSequence title, float width, @LayoutRes int resource) { 37 | return new ViewPagerItem(title, width, resource); 38 | } 39 | 40 | public View initiate(LayoutInflater inflater, ViewGroup container) { 41 | return inflater.inflate(resource, container, false); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/ViewPagerItemAdapter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | import android.support.v4.util.SparseArrayCompat; 19 | import android.support.v4.view.PagerAdapter; 20 | import android.view.LayoutInflater; 21 | import android.view.View; 22 | import android.view.ViewGroup; 23 | 24 | import java.lang.ref.WeakReference; 25 | 26 | public class ViewPagerItemAdapter extends PagerAdapter { 27 | 28 | private final ViewPagerItems pages; 29 | private final SparseArrayCompat> holder; 30 | private final LayoutInflater inflater; 31 | 32 | public ViewPagerItemAdapter(ViewPagerItems pages) { 33 | this.pages = pages; 34 | this.holder = new SparseArrayCompat<>(pages.size()); 35 | this.inflater = LayoutInflater.from(pages.getContext()); 36 | } 37 | 38 | @Override 39 | public int getCount() { 40 | return pages.size(); 41 | } 42 | 43 | @Override 44 | public Object instantiateItem(ViewGroup container, int position) { 45 | View view = getPagerItem(position).initiate(inflater, container); 46 | container.addView(view); 47 | holder.put(position, new WeakReference(view)); 48 | return view; 49 | } 50 | 51 | @Override 52 | public void destroyItem(ViewGroup container, int position, Object object) { 53 | holder.remove(position); 54 | container.removeView((View) object); 55 | } 56 | 57 | @Override 58 | public boolean isViewFromObject(View view, Object object) { 59 | return object == view; 60 | } 61 | 62 | @Override 63 | public CharSequence getPageTitle(int position) { 64 | return getPagerItem(position).getTitle(); 65 | } 66 | 67 | @Override 68 | public float getPageWidth(int position) { 69 | return getPagerItem(position).getWidth(); 70 | } 71 | 72 | public View getPage(int position) { 73 | final WeakReference weakRefItem = holder.get(position); 74 | return (weakRefItem != null) ? weakRefItem.get() : null; 75 | } 76 | 77 | protected ViewPagerItem getPagerItem(int position) { 78 | return pages.get(position); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/ViewPagerItems.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils; 17 | 18 | import android.content.Context; 19 | import android.support.annotation.LayoutRes; 20 | import android.support.annotation.StringRes; 21 | 22 | public class ViewPagerItems extends PagerItems { 23 | 24 | public ViewPagerItems(Context context) { 25 | super(context); 26 | } 27 | 28 | public static Creator with(Context context) { 29 | return new Creator(context); 30 | } 31 | 32 | public static class Creator { 33 | 34 | private final ViewPagerItems items; 35 | 36 | public Creator(Context context) { 37 | items = new ViewPagerItems(context); 38 | } 39 | 40 | public Creator add(@StringRes int title, @LayoutRes int resource) { 41 | return add(ViewPagerItem.of(items.getContext().getString(title), resource)); 42 | } 43 | 44 | public Creator add(@StringRes int title, float width, @LayoutRes int resource) { 45 | return add(ViewPagerItem.of(items.getContext().getString(title), width, resource)); 46 | } 47 | 48 | public Creator add(CharSequence title, @LayoutRes int resource) { 49 | return add(ViewPagerItem.of(title, resource)); 50 | } 51 | 52 | public Creator add(ViewPagerItem item) { 53 | items.add(item); 54 | return this; 55 | } 56 | 57 | public ViewPagerItems create() { 58 | return items; 59 | } 60 | 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/v4/Bundler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v4; 17 | 18 | import android.annotation.TargetApi; 19 | import android.os.Bundle; 20 | import android.os.IBinder; 21 | import android.os.Parcelable; 22 | import android.support.v4.app.Fragment; 23 | import android.util.Size; 24 | import android.util.SizeF; 25 | import android.util.SparseArray; 26 | 27 | import java.io.Serializable; 28 | import java.util.ArrayList; 29 | 30 | public class Bundler { 31 | 32 | private final Bundle bundle; 33 | 34 | /** 35 | * Constructs a new, empty Bundle. 36 | */ 37 | public Bundler() { 38 | this(null); 39 | } 40 | 41 | private Bundler(Bundle b) { 42 | bundle = (b == null) ? new Bundle() : new Bundle(b); 43 | } 44 | 45 | /** 46 | * Constructs a Bundle containing a copy of the mappings from the given 47 | * Bundle. 48 | * 49 | * @param b a Bundle to be copied. 50 | */ 51 | public static Bundler of(Bundle b) { 52 | return new Bundler(b); 53 | } 54 | 55 | /** 56 | * Inserts all mappings from the given Bundle into this Bundle. 57 | * 58 | * @param bundle a Bundle 59 | */ 60 | public Bundler putAll(Bundle bundle) { 61 | this.bundle.putAll(bundle); 62 | return this; 63 | } 64 | 65 | /** 66 | * Inserts a byte value into the mapping of this Bundle, replacing 67 | * any existing value for the given key. 68 | * 69 | * @param key a String, or null 70 | * @param value a byte 71 | */ 72 | public Bundler putByte(String key, byte value) { 73 | bundle.putByte(key, value); 74 | return this; 75 | } 76 | 77 | /** 78 | * Inserts a char value into the mapping of this Bundle, replacing 79 | * any existing value for the given key. 80 | * 81 | * @param key a String, or null 82 | * @param value a char, or null 83 | */ 84 | public Bundler putChar(String key, char value) { 85 | bundle.putChar(key, value); 86 | return this; 87 | } 88 | 89 | /** 90 | * Inserts a short value into the mapping of this Bundle, replacing 91 | * any existing value for the given key. 92 | * 93 | * @param key a String, or null 94 | * @param value a short 95 | */ 96 | public Bundler putShort(String key, short value) { 97 | bundle.putShort(key, value); 98 | return this; 99 | } 100 | 101 | /** 102 | * Inserts a float value into the mapping of this Bundle, replacing 103 | * any existing value for the given key. 104 | * 105 | * @param key a String, or null 106 | * @param value a float 107 | */ 108 | public Bundler putFloat(String key, float value) { 109 | bundle.putFloat(key, value); 110 | return this; 111 | } 112 | 113 | /** 114 | * Inserts a CharSequence value into the mapping of this Bundle, replacing 115 | * any existing value for the given key. Either key or value may be null. 116 | * 117 | * @param key a String, or null 118 | * @param value a CharSequence, or null 119 | */ 120 | public Bundler putCharSequence(String key, CharSequence value) { 121 | bundle.putCharSequence(key, value); 122 | return this; 123 | } 124 | 125 | /** 126 | * Inserts a Parcelable value into the mapping of this Bundle, replacing 127 | * any existing value for the given key. Either key or value may be null. 128 | * 129 | * @param key a String, or null 130 | * @param value a Parcelable object, or null 131 | */ 132 | public Bundler putParcelable(String key, Parcelable value) { 133 | bundle.putParcelable(key, value); 134 | return this; 135 | } 136 | 137 | /** 138 | * Inserts a Size value into the mapping of this Bundle, replacing 139 | * any existing value for the given key. Either key or value may be null. 140 | * 141 | * @param key a String, or null 142 | * @param value a Size object, or null 143 | */ 144 | @TargetApi(21) 145 | public Bundler putSize(String key, Size value) { 146 | bundle.putSize(key, value); 147 | return this; 148 | } 149 | 150 | /** 151 | * Inserts a SizeF value into the mapping of this Bundle, replacing 152 | * any existing value for the given key. Either key or value may be null. 153 | * 154 | * @param key a String, or null 155 | * @param value a SizeF object, or null 156 | */ 157 | @TargetApi(21) 158 | public Bundler putSizeF(String key, SizeF value) { 159 | bundle.putSizeF(key, value); 160 | return this; 161 | } 162 | 163 | /** 164 | * Inserts an array of Parcelable values into the mapping of this Bundle, 165 | * replacing any existing value for the given key. Either key or value may 166 | * be null. 167 | * 168 | * @param key a String, or null 169 | * @param value an array of Parcelable objects, or null 170 | */ 171 | public Bundler putParcelableArray(String key, Parcelable[] value) { 172 | bundle.putParcelableArray(key, value); 173 | return this; 174 | } 175 | 176 | /** 177 | * Inserts a List of Parcelable values into the mapping of this Bundle, 178 | * replacing any existing value for the given key. Either key or value may 179 | * be null. 180 | * 181 | * @param key a String, or null 182 | * @param value an ArrayList of Parcelable objects, or null 183 | */ 184 | public Bundler putParcelableArrayList(String key, 185 | ArrayList value) { 186 | bundle.putParcelableArrayList(key, value); 187 | return this; 188 | } 189 | 190 | /** 191 | * Inserts a SparceArray of Parcelable values into the mapping of this 192 | * Bundle, replacing any existing value for the given key. Either key 193 | * or value may be null. 194 | * 195 | * @param key a String, or null 196 | * @param value a SparseArray of Parcelable objects, or null 197 | */ 198 | public Bundler putSparseParcelableArray(String key, 199 | SparseArray value) { 200 | bundle.putSparseParcelableArray(key, value); 201 | return this; 202 | } 203 | 204 | /** 205 | * Inserts an ArrayList value into the mapping of this Bundle, replacing 206 | * any existing value for the given key. Either key or value may be null. 207 | * 208 | * @param key a String, or null 209 | * @param value an ArrayList object, or null 210 | */ 211 | public Bundler putIntegerArrayList(String key, ArrayList value) { 212 | bundle.putIntegerArrayList(key, value); 213 | return this; 214 | } 215 | 216 | /** 217 | * Inserts an ArrayList value into the mapping of this Bundle, replacing 218 | * any existing value for the given key. Either key or value may be null. 219 | * 220 | * @param key a String, or null 221 | * @param value an ArrayList object, or null 222 | */ 223 | public Bundler putStringArrayList(String key, ArrayList value) { 224 | bundle.putStringArrayList(key, value); 225 | return this; 226 | } 227 | 228 | /** 229 | * Inserts an ArrayList value into the mapping of this Bundle, replacing 230 | * any existing value for the given key. Either key or value may be null. 231 | * 232 | * @param key a String, or null 233 | * @param value an ArrayList object, or null 234 | */ 235 | @TargetApi(8) 236 | public Bundler putCharSequenceArrayList(String key, ArrayList value) { 237 | bundle.putCharSequenceArrayList(key, value); 238 | return this; 239 | } 240 | 241 | /** 242 | * Inserts a Serializable value into the mapping of this Bundle, replacing 243 | * any existing value for the given key. Either key or value may be null. 244 | * 245 | * @param key a String, or null 246 | * @param value a Serializable object, or null 247 | */ 248 | public Bundler putSerializable(String key, Serializable value) { 249 | bundle.putSerializable(key, value); 250 | return this; 251 | } 252 | 253 | /** 254 | * Inserts a byte array value into the mapping of this Bundle, replacing 255 | * any existing value for the given key. Either key or value may be null. 256 | * 257 | * @param key a String, or null 258 | * @param value a byte array object, or null 259 | */ 260 | public Bundler putByteArray(String key, byte[] value) { 261 | bundle.putByteArray(key, value); 262 | return this; 263 | } 264 | 265 | /** 266 | * Inserts a short array value into the mapping of this Bundle, replacing 267 | * any existing value for the given key. Either key or value may be null. 268 | * 269 | * @param key a String, or null 270 | * @param value a short array object, or null 271 | */ 272 | public Bundler putShortArray(String key, short[] value) { 273 | bundle.putShortArray(key, value); 274 | return this; 275 | } 276 | 277 | /** 278 | * Inserts a char array value into the mapping of this Bundle, replacing 279 | * any existing value for the given key. Either key or value may be null. 280 | * 281 | * @param key a String, or null 282 | * @param value a char array object, or null 283 | */ 284 | public Bundler putCharArray(String key, char[] value) { 285 | bundle.putCharArray(key, value); 286 | return this; 287 | } 288 | 289 | /** 290 | * Inserts a float array value into the mapping of this Bundle, replacing 291 | * any existing value for the given key. Either key or value may be null. 292 | * 293 | * @param key a String, or null 294 | * @param value a float array object, or null 295 | */ 296 | public Bundler putFloatArray(String key, float[] value) { 297 | bundle.putFloatArray(key, value); 298 | return this; 299 | } 300 | 301 | /** 302 | * Inserts a CharSequence array value into the mapping of this Bundle, replacing 303 | * any existing value for the given key. Either key or value may be null. 304 | * 305 | * @param key a String, or null 306 | * @param value a CharSequence array object, or null 307 | */ 308 | @TargetApi(8) 309 | public Bundler putCharSequenceArray(String key, CharSequence[] value) { 310 | bundle.putCharSequenceArray(key, value); 311 | return this; 312 | } 313 | 314 | /** 315 | * Inserts a Bundle value into the mapping of this Bundle, replacing 316 | * any existing value for the given key. Either key or value may be null. 317 | * 318 | * @param key a String, or null 319 | * @param value a Bundle object, or null 320 | */ 321 | public Bundler putBundle(String key, Bundle value) { 322 | bundle.putBundle(key, value); 323 | return this; 324 | } 325 | 326 | /** 327 | * Inserts an {@link android.os.IBinder} value into the mapping of this Bundle, replacing 328 | * any existing value for the given key. Either key or value may be null. 329 | * 330 | *

You should be very careful when using this function. In many 331 | * places where Bundles are used (such as inside of Intent objects), the Bundle 332 | * can live longer inside of another process than the process that had originally 333 | * created it. In that case, the IBinder you supply here will become invalid 334 | * when your process goes away, and no longer usable, even if a new process is 335 | * created for you later on.

336 | * 337 | * @param key a String, or null 338 | * @param value an IBinder object, or null 339 | */ 340 | @TargetApi(18) 341 | public Bundler putBinder(String key, IBinder value) { 342 | bundle.putBinder(key, value); 343 | return this; 344 | } 345 | 346 | /** 347 | * Inserts a Boolean value into the mapping of this Bundle, replacing 348 | * any existing value for the given key. Either key or value may be null. 349 | * 350 | * @param key a String, or null 351 | * @param value a Boolean, or null 352 | */ 353 | public Bundler putBoolean(String key, boolean value) { 354 | bundle.putBoolean(key, value); 355 | return this; 356 | } 357 | 358 | /** 359 | * Inserts an int value into the mapping of this Bundle, replacing 360 | * any existing value for the given key. 361 | * 362 | * @param key a String, or null 363 | * @param value an int, or null 364 | */ 365 | public Bundler putInt(String key, int value) { 366 | bundle.putInt(key, value); 367 | return this; 368 | } 369 | 370 | /** 371 | * Inserts a long value into the mapping of this Bundle, replacing 372 | * any existing value for the given key. 373 | * 374 | * @param key a String, or null 375 | * @param value a long 376 | */ 377 | public Bundler putLong(String key, long value) { 378 | bundle.putLong(key, value); 379 | return this; 380 | } 381 | 382 | /** 383 | * Inserts a double value into the mapping of this Bundle, replacing 384 | * any existing value for the given key. 385 | * 386 | * @param key a String, or null 387 | * @param value a double 388 | */ 389 | public Bundler putDouble(String key, double value) { 390 | bundle.putDouble(key, value); 391 | return this; 392 | } 393 | 394 | /** 395 | * Inserts a String value into the mapping of this Bundle, replacing 396 | * any existing value for the given key. Either key or value may be null. 397 | * 398 | * @param key a String, or null 399 | * @param value a String, or null 400 | */ 401 | public Bundler putString(String key, String value) { 402 | bundle.putString(key, value); 403 | return this; 404 | } 405 | 406 | /** 407 | * Inserts a boolean array value into the mapping of this Bundle, replacing 408 | * any existing value for the given key. Either key or value may be null. 409 | * 410 | * @param key a String, or null 411 | * @param value a boolean array object, or null 412 | */ 413 | public Bundler putBooleanArray(String key, boolean[] value) { 414 | bundle.putBooleanArray(key, value); 415 | return this; 416 | } 417 | 418 | /** 419 | * Inserts an int array value into the mapping of this Bundle, replacing 420 | * any existing value for the given key. Either key or value may be null. 421 | * 422 | * @param key a String, or null 423 | * @param value an int array object, or null 424 | */ 425 | public Bundler putIntArray(String key, int[] value) { 426 | bundle.putIntArray(key, value); 427 | return this; 428 | } 429 | 430 | /** 431 | * Inserts a long array value into the mapping of this Bundle, replacing 432 | * any existing value for the given key. Either key or value may be null. 433 | * 434 | * @param key a String, or null 435 | * @param value a long array object, or null 436 | */ 437 | public Bundler putLongArray(String key, long[] value) { 438 | bundle.putLongArray(key, value); 439 | return this; 440 | } 441 | 442 | /** 443 | * Inserts a double array value into the mapping of this Bundle, replacing 444 | * any existing value for the given key. Either key or value may be null. 445 | * 446 | * @param key a String, or null 447 | * @param value a double array object, or null 448 | */ 449 | public Bundler putDoubleArray(String key, double[] value) { 450 | bundle.putDoubleArray(key, value); 451 | return this; 452 | } 453 | 454 | /** 455 | * Inserts a String array value into the mapping of this Bundle, replacing 456 | * any existing value for the given key. Either key or value may be null. 457 | * 458 | * @param key a String, or null 459 | * @param value a String array object, or null 460 | */ 461 | public Bundler putStringArray(String key, String[] value) { 462 | bundle.putStringArray(key, value); 463 | return this; 464 | } 465 | 466 | /** 467 | * Get the bundle. 468 | * 469 | * @return a bundle 470 | */ 471 | public Bundle get() { 472 | return bundle; 473 | } 474 | 475 | /** 476 | * Set the argument of Fragment. 477 | * 478 | * @param fragment a fragment 479 | * @return a fragment 480 | */ 481 | public T into(T fragment) { 482 | fragment.setArguments(get()); 483 | return fragment; 484 | } 485 | 486 | } 487 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/v4/FragmentPagerItem.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v4; 17 | 18 | import android.content.Context; 19 | import android.os.Bundle; 20 | import android.support.v4.app.Fragment; 21 | 22 | import com.ogaclejapan.smarttablayout.utils.PagerItem; 23 | 24 | public class FragmentPagerItem extends PagerItem { 25 | 26 | private static final String TAG = "FragmentPagerItem"; 27 | private static final String KEY_POSITION = TAG + ":Position"; 28 | 29 | private final String className; 30 | private final Bundle args; 31 | 32 | protected FragmentPagerItem(CharSequence title, float width, String className, Bundle args) { 33 | super(title, width); 34 | this.className = className; 35 | this.args = args; 36 | } 37 | 38 | public static FragmentPagerItem of(CharSequence title, Class clazz) { 39 | return of(title, DEFAULT_WIDTH, clazz); 40 | } 41 | 42 | public static FragmentPagerItem of(CharSequence title, Class clazz, 43 | Bundle args) { 44 | return of(title, DEFAULT_WIDTH, clazz, args); 45 | } 46 | 47 | public static FragmentPagerItem of(CharSequence title, float width, 48 | Class clazz) { 49 | return of(title, width, clazz, new Bundle()); 50 | } 51 | 52 | public static FragmentPagerItem of(CharSequence title, float width, 53 | Class clazz, Bundle args) { 54 | return new FragmentPagerItem(title, width, clazz.getName(), args); 55 | } 56 | 57 | public static boolean hasPosition(Bundle args) { 58 | return args != null && args.containsKey(KEY_POSITION); 59 | } 60 | 61 | public static int getPosition(Bundle args) { 62 | return (hasPosition(args)) ? args.getInt(KEY_POSITION) : 0; 63 | } 64 | 65 | static void setPosition(Bundle args, int position) { 66 | args.putInt(KEY_POSITION, position); 67 | } 68 | 69 | public Fragment instantiate(Context context, int position) { 70 | setPosition(args, position); 71 | return Fragment.instantiate(context, className, args); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/v4/FragmentPagerItemAdapter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v4; 17 | 18 | import android.support.v4.app.Fragment; 19 | import android.support.v4.app.FragmentManager; 20 | import android.support.v4.app.FragmentPagerAdapter; 21 | import android.support.v4.util.SparseArrayCompat; 22 | import android.view.ViewGroup; 23 | 24 | import java.lang.ref.WeakReference; 25 | 26 | public class FragmentPagerItemAdapter extends FragmentPagerAdapter { 27 | 28 | private final FragmentPagerItems pages; 29 | private final SparseArrayCompat> holder; 30 | 31 | public FragmentPagerItemAdapter(FragmentManager fm, FragmentPagerItems pages) { 32 | super(fm); 33 | this.pages = pages; 34 | this.holder = new SparseArrayCompat<>(pages.size()); 35 | } 36 | 37 | @Override 38 | public int getCount() { 39 | return pages.size(); 40 | } 41 | 42 | @Override 43 | public Fragment getItem(int position) { 44 | return getPagerItem(position).instantiate(pages.getContext(), position); 45 | } 46 | 47 | @Override 48 | public Object instantiateItem(ViewGroup container, int position) { 49 | Object item = super.instantiateItem(container, position); 50 | if (item instanceof Fragment) { 51 | holder.put(position, new WeakReference((Fragment) item)); 52 | } 53 | return item; 54 | } 55 | 56 | @Override 57 | public void destroyItem(ViewGroup container, int position, Object object) { 58 | holder.remove(position); 59 | super.destroyItem(container, position, object); 60 | } 61 | 62 | @Override 63 | public CharSequence getPageTitle(int position) { 64 | return getPagerItem(position).getTitle(); 65 | } 66 | 67 | @Override 68 | public float getPageWidth(int position) { 69 | return super.getPageWidth(position); 70 | } 71 | 72 | public Fragment getPage(int position) { 73 | final WeakReference weakRefItem = holder.get(position); 74 | return (weakRefItem != null) ? weakRefItem.get() : null; 75 | } 76 | 77 | protected FragmentPagerItem getPagerItem(int position) { 78 | return pages.get(position); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/v4/FragmentPagerItems.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v4; 17 | 18 | import android.content.Context; 19 | import android.os.Bundle; 20 | import android.support.annotation.StringRes; 21 | import android.support.v4.app.Fragment; 22 | 23 | import com.ogaclejapan.smarttablayout.utils.PagerItems; 24 | 25 | public class FragmentPagerItems extends PagerItems { 26 | 27 | public FragmentPagerItems(Context context) { 28 | super(context); 29 | } 30 | 31 | public static Creator with(Context context) { 32 | return new Creator(context); 33 | } 34 | 35 | public static class Creator { 36 | 37 | private final FragmentPagerItems items; 38 | 39 | public Creator(Context context) { 40 | items = new FragmentPagerItems(context); 41 | } 42 | 43 | public Creator add(@StringRes int title, Class clazz) { 44 | return add(FragmentPagerItem.of(items.getContext().getString(title), clazz)); 45 | } 46 | 47 | public Creator add(@StringRes int title, Class clazz, Bundle args) { 48 | return add(FragmentPagerItem.of(items.getContext().getString(title), clazz, args)); 49 | } 50 | 51 | public Creator add(@StringRes int title, float width, Class clazz) { 52 | return add(FragmentPagerItem.of(items.getContext().getString(title), width, clazz)); 53 | } 54 | 55 | public Creator add(@StringRes int title, float width, Class clazz, 56 | Bundle args) { 57 | return add(FragmentPagerItem.of(items.getContext().getString(title), width, clazz, args)); 58 | } 59 | 60 | public Creator add(CharSequence title, Class clazz) { 61 | return add(FragmentPagerItem.of(title, clazz)); 62 | } 63 | 64 | public Creator add(CharSequence title, Class clazz, Bundle args) { 65 | return add(FragmentPagerItem.of(title, clazz, args)); 66 | } 67 | 68 | public Creator add(FragmentPagerItem item) { 69 | items.add(item); 70 | return this; 71 | } 72 | 73 | public FragmentPagerItems create() { 74 | return items; 75 | } 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /utils-v4/src/main/java/com/ogaclejapan/smarttablayout/utils/v4/FragmentStatePagerItemAdapter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (C) 2015 ogaclejapan 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 | package com.ogaclejapan.smarttablayout.utils.v4; 17 | 18 | import android.support.v4.app.Fragment; 19 | import android.support.v4.app.FragmentManager; 20 | import android.support.v4.app.FragmentStatePagerAdapter; 21 | import android.support.v4.util.SparseArrayCompat; 22 | import android.view.ViewGroup; 23 | 24 | import java.lang.ref.WeakReference; 25 | 26 | public class FragmentStatePagerItemAdapter extends FragmentStatePagerAdapter { 27 | 28 | private final FragmentPagerItems pages; 29 | private final SparseArrayCompat> holder; 30 | 31 | public FragmentStatePagerItemAdapter(FragmentManager fm, FragmentPagerItems pages) { 32 | super(fm); 33 | this.pages = pages; 34 | this.holder = new SparseArrayCompat<>(pages.size()); 35 | } 36 | 37 | @Override 38 | public int getCount() { 39 | return pages.size(); 40 | } 41 | 42 | @Override 43 | public Fragment getItem(int position) { 44 | return getPagerItem(position).instantiate(pages.getContext(), position); 45 | } 46 | 47 | @Override 48 | public Object instantiateItem(ViewGroup container, int position) { 49 | Object item = super.instantiateItem(container, position); 50 | if (item instanceof Fragment) { 51 | holder.put(position, new WeakReference((Fragment) item)); 52 | } 53 | return item; 54 | } 55 | 56 | @Override 57 | public void destroyItem(ViewGroup container, int position, Object object) { 58 | holder.remove(position); 59 | super.destroyItem(container, position, object); 60 | } 61 | 62 | @Override 63 | public CharSequence getPageTitle(int position) { 64 | return getPagerItem(position).getTitle(); 65 | } 66 | 67 | @Override 68 | public float getPageWidth(int position) { 69 | return getPagerItem(position).getWidth(); 70 | } 71 | 72 | public Fragment getPage(int position) { 73 | final WeakReference weakRefItem = holder.get(position); 74 | return (weakRefItem != null) ? weakRefItem.get() : null; 75 | } 76 | 77 | protected FragmentPagerItem getPagerItem(int position) { 78 | return pages.get(position); 79 | } 80 | 81 | } 82 | --------------------------------------------------------------------------------