├── .github ├── FUNDING.yml └── workflows │ └── maven-publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── _config.yml ├── alphabetsindexfastscrollrecycler ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── in │ │ └── myinnos │ │ └── alphabetsindexfastscrollrecycler │ │ ├── IndexFastScrollRecyclerSection.kt │ │ ├── IndexFastScrollRecyclerView.kt │ │ └── utilities_fs │ │ └── StringMatcher.java │ ├── res │ └── values │ │ ├── attrs.xml │ │ └── strings.xml │ └── resources │ └── META-INF │ └── com │ └── github │ └── myinnos │ └── AlphabetIndex-Fast-Scroll-RecyclerView │ └── verification.properties ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── in │ │ └── myinnos │ │ └── indexfastscrollrecycler │ │ ├── Helpers.kt │ │ ├── MainActivity.kt │ │ ├── adapter │ │ └── RecyclerViewAdapter.kt │ │ ├── helper │ │ └── DataHelper.kt │ │ └── utility │ │ └── AlphabetItem.kt │ └── res │ ├── drawable-hdpi │ └── ic_delete.png │ ├── drawable-mdpi │ └── ic_delete.png │ ├── drawable-xhdpi │ └── ic_delete.png │ ├── drawable-xxhdpi │ └── ic_delete.png │ ├── layout │ ├── activity_main.xml │ └── item_recycler_view_layout.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images-gif ├── AlphabetIndex-Fast-Scroll-RecyclerView_1.gif ├── AlphabetIndex-Fast-Scroll-RecyclerView_2.gif └── AlphabetIndex-Fast-Scroll-RecyclerView_3.gif └── settings.gradle /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [myinnos] 2 | custom: ['https://www.paypal.me/fansfolio'] 3 | custom: ['https://www.buymeacoffee.com/myinnos'] 4 | 5 | -------------------------------------------------------------------------------- /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a package using Maven and then publish it to GitHub packages when a release is created 2 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#apache-maven-with-a-settings-path 3 | 4 | name: Maven Package 5 | 6 | on: 7 | release: 8 | types: [created] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | packages: write 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Set up JDK 11 21 | uses: actions/setup-java@v4 22 | with: 23 | java-version: '11' 24 | distribution: 'temurin' 25 | server-id: github # Value of the distributionManagement/repository/id field of the pom.xml 26 | settings-path: ${{ github.workspace }} # location for the settings.xml file 27 | 28 | - name: Build with Maven 29 | run: mvn -B package --file pom.xml 30 | 31 | - name: Publish to GitHub Packages Apache Maven 32 | run: mvn deploy -s $GITHUB_WORKSPACE/settings.xml 33 | env: 34 | GITHUB_TOKEN: ${{ github.token }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | .idea/ 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | 10 | instapk.log* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AlphabetIndex Fast Scroll RecyclerView 2 | A Powerful AlphabetIndex FastScroller for Android's RecyclerView! 3 | 4 | [![](https://jitpack.io/v/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView.svg)](https://jitpack.io/#myinnos/AlphabetIndex-Fast-Scroll-RecyclerView) [![MyInnos website](https://img.shields.io/badge/visit-website-red.svg?logo=firefox)](https://www.myinnos.in/) [![](https://jitpack.io/v/jitpack/maven-simple/month.svg)](https://jitpack.io/#myinnos/AlphabetIndex-Fast-Scroll-RecyclerView) Android Language Badge 5 | 6 | 7 | ![AlphabetIndex-Fast-Scroll-RecyclerView - Example1](https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/0d6c4f2f0b9f3b573a4f2abf2c87b62237081286/images-gif/AlphabetIndex-Fast-Scroll-RecyclerView_1.gif) 8 | ![AlphabetIndex-Fast-Scroll-RecyclerView - Example2](https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/0d6c4f2f0b9f3b573a4f2abf2c87b62237081286/images-gif/AlphabetIndex-Fast-Scroll-RecyclerView_2.gif) 9 | ![AlphabetIndex-Fast-Scroll-RecyclerView - Example3](https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/master/images-gif/AlphabetIndex-Fast-Scroll-RecyclerView_3.gif) 10 | 11 | #### Kindly use the following links to use this library: 12 | 13 | In build.gradle (Project) 14 | ```java 15 | allprojects { 16 | repositories { 17 | ... 18 | maven { url "https://jitpack.io" } 19 | } 20 | } 21 | ``` 22 | And then in the other gradle file(may be your app gradle or your own module library gradle, but never add in both of them to avoid conflict.) 23 | ```java 24 | dependencies { 25 | implementation 'com.github.myinnos:AlphabetIndex-Fast-Scroll-RecyclerView:2.0' 26 | 27 | // AppCompat version 28 | // implementation 'com.github.myinnos:AlphabetIndex-Fast-Scroll-RecyclerView:1.0.92' 29 | // or 30 | // AndroidX version 31 | // implementation 'com.github.myinnos:AlphabetIndex-Fast-Scroll-RecyclerView:1.0.95' 32 | 33 | } 34 | ``` 35 | How to use 36 | ----- 37 | **Step 1:** add this to your xml: 38 | ```xml 39 | 43 | ``` 44 | **Step 2:** implement SectionIndexer to RecyclerViewAdapter. 45 | ```java 46 | public class RecyclerViewAdapter extends RecyclerView.Adapter implements SectionIndexer { 47 | 48 | private List mDataArray; 49 | private ArrayList mSectionPositions; 50 | 51 | ..... 52 | 53 | @Override 54 | public int getSectionForPosition(int position) { 55 | return 0; 56 | } 57 | 58 | @Override 59 | public Object[] getSections() { 60 | List sections = new ArrayList<>(26); 61 | mSectionPositions = new ArrayList<>(26); 62 | for (int i = 0, size = mDataArray.size(); i < size; i++) { 63 | String section = String.valueOf(mDataArray.get(i).charAt(0)).toUpperCase(); 64 | if (!sections.contains(section)) { 65 | sections.add(section); 66 | mSectionPositions.add(i); 67 | } 68 | } 69 | return sections.toArray(new String[0]); 70 | } 71 | 72 | @Override 73 | public int getPositionForSection(int sectionIndex) { 74 | return mSectionPositions.get(sectionIndex); 75 | } 76 | 77 | } 78 | ``` 79 | #### Note: mDataArray: this is your recycler data array model. 80 | 81 | Features 82 | ----- 83 | - Change IndexTextSize: 84 | ```java 85 | mRecyclerView.setIndexTextSize(12); 86 | ``` 87 | - Change IndexBarTextColor: 88 | ```java 89 | mRecyclerView.setIndexBarTextColor("#FFFFFF"); 90 | 91 | mRecyclerView.setIndexBarTextColor(R.color.index_bar_text_color); 92 | ``` 93 | - Change IndexBarColor: 94 | ```java 95 | mRecyclerView.setIndexBarColor("#33334c"); 96 | 97 | mRecyclerView.setIndexBarColor(R.color.index_bar_color); 98 | ``` 99 | - Change IndexBarCornerRadius: 100 | ```java 101 | mRecyclerView.setIndexBarCornerRadius(3); 102 | ``` 103 | - Change IndexBarTransparentValue: 104 | ```java 105 | mRecyclerView.setIndexBarTransparentValue((float) 0.4); 106 | ``` 107 | - Change IndexBarMargin: 108 | ```java 109 | mRecyclerView.setIndexBarMargin(4); 110 | ``` 111 | - Change IndexBarWidth: 112 | ```java 113 | mRecyclerView.setIndexBarWidth(40); 114 | ``` 115 | - Change PreviewPadding: 116 | ```java 117 | mRecyclerView.setPreviewPadding(2); 118 | ``` 119 | - Change PreviewVisibility: 120 | ```java 121 | mRecyclerView.setPreviewVisibility(false); 122 | ``` 123 | - Change Typeface: 124 | ```java 125 | Typeface typeface = Typeface.createFromAsset(context.getAssets(), "Custom-Font.ttf"); 126 | mRecyclerView.setTypeface(typeface); 127 | ``` 128 | - To hide/show Fast Scroll IndexBar: 129 | ```java 130 | mRecyclerView.setIndexBarVisibility(true); 131 | ``` 132 | - Change IndexBarHighLateTextColor: 133 | ```java 134 | mRecyclerView.setIndexBarHighLightTextColor("#33334c); 135 | 136 | mRecyclerView.setIndexBarHighLightTextColor(R.color.index_bar_highlight_text_color); 137 | ``` 138 | - To hide/show IndexBarHighLightText: 139 | ```java 140 | mRecyclerView.setIndexBarHighLightTextVisibility(true); 141 | ``` 142 | - To hide/show IndexBarStroke: 143 | ```java 144 | mRecyclerView.setIndexBarStrokeVisibility(true); 145 | ``` 146 | - Change IndexBarStrokeWidth: 147 | ```java 148 | mRecyclerView.setIndexBarStrokeWidth(1); 149 | ``` 150 | - Change IndexBarStrokeColor: 151 | ```java 152 | mRecyclerView.setIndexBarStrokeColor("#000000"); 153 | ``` 154 | 155 | Compatibility 156 | ----- 157 | This library works with any layout manager but is optimized for the use with a LinearLayoutManager. 158 | 159 | ##### Any Queries? or Feedback, please let me know by opening a [new issue](https://github.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/issues/new)! 160 | 161 | ## Contact 162 | #### Prabhakar Thota 163 | * :globe_with_meridians: Website: [myinnos.in](http://www.myinnos.in "Prabhakar Thota") 164 | * :email: e-mail: contact@myinnos.in 165 | * :mag_right: LinkedIn: [PrabhakarThota](https://www.linkedin.com/in/prabhakarthota "Prabhakar Thota on LinkedIn") 166 | * :thumbsup: Twitter: [@myinnos](https://twitter.com/myinnos "Prabhakar Thota on twitter") 167 | * :camera: Instagram: [@prabhakar_t_](https://www.instagram.com/prabhakar_t_/ "Prabhakar Thota on Instagram") 168 | 169 | >⚡ If you appreciate my work, consider buying me a cup of :coffee: to keep me recharged :metal: by [GitHub](https://github.com/sponsors/myinnos) or [PayPal](https://www.paypal.me/fansfolio) 170 | 171 | ### Contributing 172 | 173 | Thanks to all the people who contributed to AlphabetIndex Fast Scroll RecyclerView 174 | 175 | 176 | 177 | 178 | 187 | 188 | License 189 | ------- 190 | 191 | Copyright 2017 - 2022 MyInnos 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 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'kotlin-android' 3 | final ANDROIDX = '1.0.0' 4 | //apply plugin: 'com.github.dcendents.android-maven' // ADD THIS 5 | 6 | group='com.github.jitpack' 7 | 8 | android { 9 | compileSdkVersion 33 10 | 11 | defaultConfig { 12 | minSdkVersion 15 13 | targetSdkVersion 33 14 | versionCode 1 15 | versionName "1.0" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | allprojects { 26 | repositories { 27 | mavenCentral() 28 | maven { 29 | url "https://maven.google.com" 30 | } 31 | } 32 | } 33 | 34 | dependencies { 35 | implementation 'androidx.appcompat:appcompat:1.6.1' 36 | implementation "com.google.android.material:material:1.8.0" 37 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 38 | implementation 'androidx.core:core-ktx:1.10.0' 39 | } 40 | 41 | // build a jar with source files 42 | task sourcesJar(type: Jar) { 43 | from android.sourceSets.main.java.srcDirs 44 | classifier = 'sources' 45 | } 46 | 47 | task javadoc(type: Javadoc) { 48 | failOnError false 49 | source = android.sourceSets.main.java.sourceFiles 50 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 51 | classpath += configurations.implementation 52 | } 53 | 54 | // build a jar with javadoc 55 | task javadocJar(type: Jar, dependsOn: javadoc) { 56 | classifier = 'javadoc' 57 | from javadoc.destinationDir 58 | } 59 | 60 | artifacts { 61 | archives sourcesJar 62 | archives javadocJar 63 | } 64 | 65 | // uncomment to build a jar file in addition to the default aar file 66 | //android.libraryVariants.all { variant -> 67 | // def name = variant.buildType.name 68 | // def task = project.tasks.create "jar${name.capitalize()}", Jar 69 | // task.dependsOn variant.javaCompile 70 | // task.from variant.javaCompile.destinationDir 71 | // artifacts.add('archives', task); 72 | //} -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\10\AppData\Local\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 | -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/src/main/java/in/myinnos/alphabetsindexfastscrollrecycler/IndexFastScrollRecyclerSection.kt: -------------------------------------------------------------------------------- 1 | package `in`.myinnos.alphabetsindexfastscrollrecycler 2 | 3 | import android.content.Context 4 | import android.graphics.* 5 | import android.util.Log 6 | import android.widget.SectionIndexer 7 | import android.view.MotionEvent 8 | import androidx.annotation.ColorInt 9 | import androidx.recyclerview.widget.LinearLayoutManager 10 | import androidx.recyclerview.widget.RecyclerView 11 | import java.lang.Exception 12 | 13 | /* 14 | * Created by MyInnos on 31-01-2017. 15 | * Updated by AbandonedCart 07-2022. 16 | */ class IndexFastScrollRecyclerSection( 17 | context: Context, 18 | recyclerView: IndexFastScrollRecyclerView 19 | ) : RecyclerView.AdapterDataObserver() { 20 | private var mIndexBarWidth: Float 21 | private var mIndexBarMarginLeft: Float 22 | private var mIndexBarMarginRight: Float 23 | private var mIndexBarMarginTop: Float 24 | private var mIndexBarMarginBottom: Float 25 | private val mPreviewPadding: Float 26 | private val mDensity: Float 27 | private val mScaledDensity: Float 28 | private var mListViewWidth = 0 29 | private var mListViewHeight = 0 30 | private var mCurrentSection = -1 31 | private var mIsIndexing = false 32 | private val mRecyclerView: RecyclerView? 33 | private var mIndexer: SectionIndexer? = null 34 | private var mSections: Array? = null 35 | private var mIndexbarRect: RectF? = null 36 | private var setIndexTextSize: Int 37 | private var setPreviewPadding: Int 38 | private var previewVisibility = true 39 | private var setIndexBarCornerRadius: Int 40 | private var setTypeface: Typeface? = null 41 | private var setIndexBarVisibility = true 42 | private var setSetIndexBarHighLightTextVisibility = false 43 | private var setIndexBarStrokeVisibility = true 44 | var mIndexBarStrokeWidth: Int 45 | 46 | @ColorInt 47 | private var mIndexBarStrokeColor: Int 48 | 49 | @ColorInt 50 | private var indexbarBackgroudColor: Int 51 | 52 | @ColorInt 53 | private var indexbarTextColor: Int 54 | 55 | @ColorInt 56 | private var indexbarHighLightTextColor: Int 57 | private var setPreviewTextSize: Int 58 | 59 | @ColorInt 60 | private var previewBackgroundColor: Int 61 | 62 | @ColorInt 63 | private var previewTextColor: Int 64 | private var previewBackgroudAlpha: Int 65 | private var indexbarBackgroudAlpha: Int 66 | fun draw(canvas: Canvas) { 67 | if (setIndexBarVisibility) { 68 | val indexbarPaint = Paint() 69 | indexbarPaint.color = indexbarBackgroudColor 70 | indexbarPaint.alpha = indexbarBackgroudAlpha 71 | indexbarPaint.isAntiAlias = true 72 | canvas.drawRoundRect( 73 | mIndexbarRect!!, setIndexBarCornerRadius * mDensity, 74 | setIndexBarCornerRadius * mDensity, indexbarPaint 75 | ) 76 | if (setIndexBarStrokeVisibility) { 77 | indexbarPaint.style = Paint.Style.STROKE 78 | indexbarPaint.color = mIndexBarStrokeColor 79 | indexbarPaint.strokeWidth = mIndexBarStrokeWidth.toFloat() // set stroke width 80 | canvas.drawRoundRect( 81 | mIndexbarRect!!, setIndexBarCornerRadius * mDensity, 82 | setIndexBarCornerRadius * mDensity, indexbarPaint 83 | ) 84 | } 85 | if (mSections != null && mSections!!.size > 0) { 86 | // Preview is shown when mCurrentSection is set 87 | if (previewVisibility && mCurrentSection >= 0 && mSections!![mCurrentSection] != "") { 88 | val previewPaint = Paint() 89 | previewPaint.color = previewBackgroundColor 90 | previewPaint.alpha = previewBackgroudAlpha 91 | previewPaint.isAntiAlias = true 92 | previewPaint.setShadowLayer( 93 | 3f, 0f, 0f, 94 | Color.argb(64, 0, 0, 0) 95 | ) 96 | val previewTextPaint = Paint() 97 | previewTextPaint.color = previewTextColor 98 | previewTextPaint.isAntiAlias = true 99 | previewTextPaint.textSize = setPreviewTextSize * mScaledDensity 100 | previewTextPaint.typeface = setTypeface 101 | val previewTextWidth = 102 | previewTextPaint.measureText(mSections!![mCurrentSection]) 103 | var previewSize = 104 | 2 * mPreviewPadding + previewTextPaint.descent() - previewTextPaint.ascent() 105 | previewSize = Math.max(previewSize, previewTextWidth + 2 * mPreviewPadding) 106 | val previewRect = RectF( 107 | (mListViewWidth - previewSize) / 2, 108 | (mListViewHeight - previewSize) / 2, 109 | (mListViewWidth - previewSize) / 2 + previewSize, 110 | (mListViewHeight - previewSize) / 2 + previewSize 111 | ) 112 | canvas.drawRoundRect(previewRect, 5 * mDensity, 5 * mDensity, previewPaint) 113 | canvas.drawText( 114 | mSections!![mCurrentSection], 115 | previewRect.left + (previewSize - previewTextWidth) / 2 - 1, 116 | previewRect.top + (previewSize - (previewTextPaint.descent() - previewTextPaint.ascent())) / 2 - previewTextPaint.ascent(), 117 | previewTextPaint 118 | ) 119 | setPreviewFadeTimeout(300) 120 | } 121 | val indexPaint = Paint() 122 | indexPaint.color = indexbarTextColor 123 | indexPaint.isAntiAlias = true 124 | indexPaint.textSize = setIndexTextSize * mScaledDensity 125 | indexPaint.typeface = setTypeface 126 | val sectionHeight = 127 | (mIndexbarRect!!.height() - mIndexBarMarginTop - mIndexBarMarginBottom) / mSections!!.size 128 | val paddingTop = (sectionHeight - (indexPaint.descent() - indexPaint.ascent())) / 2 129 | for (i in mSections!!.indices) { 130 | if (setSetIndexBarHighLightTextVisibility) { 131 | if (mCurrentSection > -1 && i == mCurrentSection) { 132 | indexPaint.typeface = Typeface.create(setTypeface, Typeface.BOLD) 133 | indexPaint.textSize = (setIndexTextSize + 3) * mScaledDensity 134 | indexPaint.color = indexbarHighLightTextColor 135 | } else { 136 | indexPaint.typeface = setTypeface 137 | indexPaint.textSize = setIndexTextSize * mScaledDensity 138 | indexPaint.color = indexbarTextColor 139 | } 140 | val paddingLeft = (mIndexBarWidth - indexPaint.measureText( 141 | mSections!![i] 142 | )) / 2 143 | canvas.drawText( 144 | mSections!![i], 145 | mIndexbarRect!!.left + paddingLeft, 146 | mIndexbarRect!!.top + mIndexBarMarginTop + sectionHeight * i + paddingTop - indexPaint.ascent(), 147 | indexPaint 148 | ) 149 | } else { 150 | val paddingLeft = (mIndexBarWidth - indexPaint.measureText( 151 | mSections!![i] 152 | )) / 2 153 | canvas.drawText( 154 | mSections!![i], 155 | mIndexbarRect!!.left + paddingLeft, 156 | mIndexbarRect!!.top + mIndexBarMarginTop + sectionHeight * i + paddingTop - indexPaint.ascent(), 157 | indexPaint 158 | ) 159 | } 160 | } 161 | } 162 | } 163 | } 164 | 165 | fun onTouchEvent(ev: MotionEvent): Boolean { 166 | when (ev.action) { 167 | MotionEvent.ACTION_DOWN -> // If down event occurs inside index bar region, start indexing 168 | if (contains(ev.x, ev.y)) { 169 | 170 | // It demonstrates that the motion event started from index bar 171 | mIsIndexing = true 172 | // Determine which section the point is in, and move the list to that section 173 | mCurrentSection = getSectionByPoint(ev.y) 174 | scrollToPosition() 175 | return true 176 | } 177 | MotionEvent.ACTION_MOVE -> if (mIsIndexing) { 178 | // If this event moves inside index bar 179 | if (contains(ev.x, ev.y)) { 180 | // Determine which section the point is in, and move the list to that section 181 | mCurrentSection = getSectionByPoint(ev.y) 182 | scrollToPosition() 183 | } 184 | return true 185 | } 186 | MotionEvent.ACTION_UP -> if (mIsIndexing) { 187 | mIsIndexing = false 188 | mCurrentSection = -1 189 | } 190 | } 191 | return false 192 | } 193 | 194 | private fun scrollToPosition() { 195 | try { 196 | val position = mIndexer?.getPositionForSection(mCurrentSection) 197 | val layoutManager = mRecyclerView!!.layoutManager 198 | if (layoutManager is LinearLayoutManager) { 199 | position?.let { layoutManager.scrollToPositionWithOffset(it, 0) } 200 | } else position?.let { layoutManager?.scrollToPosition(it) } 201 | } catch (e: Exception) { 202 | Log.d("INDEX_BAR", "Data size returns null") 203 | } 204 | } 205 | 206 | fun onSizeChanged(w: Int, h: Int) { 207 | mListViewWidth = w 208 | mListViewHeight = h 209 | mIndexbarRect = RectF( 210 | w - mIndexBarMarginLeft - mIndexBarWidth, 211 | mIndexBarMarginTop, 212 | w - mIndexBarMarginRight, 213 | h - mIndexBarMarginBottom - if (mRecyclerView!!.clipToPadding) 0 else mRecyclerView.paddingBottom 214 | ) 215 | } 216 | 217 | fun setAdapter(adapter: RecyclerView.Adapter?) { 218 | if (adapter is SectionIndexer) { 219 | adapter.registerAdapterDataObserver(this) 220 | mIndexer = adapter 221 | mSections = mIndexer?.sections as Array 222 | } 223 | } 224 | 225 | override fun onChanged() { 226 | super.onChanged() 227 | updateSections() 228 | } 229 | 230 | fun updateSections() { 231 | mSections = mIndexer?.sections as Array 232 | } 233 | 234 | fun contains(x: Float, y: Float): Boolean { 235 | // Determine if the point is in index bar region, which includes the right margin of the bar 236 | return x >= mIndexbarRect!!.left && y >= mIndexbarRect!!.top && y <= mIndexbarRect!!.top + mIndexbarRect!!.height() 237 | } 238 | 239 | private fun getSectionByPoint(y: Float): Int { 240 | if (mSections == null || mSections?.isEmpty() == true) return 0 241 | if (y < mIndexbarRect!!.top + mIndexBarMarginTop) return 0 242 | return if (y >= mIndexbarRect!!.top + mIndexbarRect!!.height() - mIndexBarMarginTop) mSections!!.size - 1 else ((y - mIndexbarRect!!.top - mIndexBarMarginTop) / ((mIndexbarRect!!.height() - mIndexBarMarginBottom - mIndexBarMarginTop) / mSections!!.size)).toInt() 243 | } 244 | 245 | private var mLastFadeRunnable: Runnable? = null 246 | private fun setPreviewFadeTimeout(delay: Long) { 247 | if (mRecyclerView != null) { 248 | if (mLastFadeRunnable != null) { 249 | mRecyclerView.removeCallbacks(mLastFadeRunnable) 250 | } 251 | mLastFadeRunnable = Runnable { mRecyclerView.invalidate() } 252 | mRecyclerView.postDelayed(mLastFadeRunnable, delay) 253 | } 254 | } 255 | 256 | private fun convertTransparentValueToBackgroundAlpha(value: Float): Int { 257 | return (255 * value).toInt() 258 | } 259 | 260 | /** 261 | * @param value int to set the text size of the index bar 262 | */ 263 | fun setIndexTextSize(value: Int) { 264 | setIndexTextSize = value 265 | } 266 | 267 | /** 268 | * @param value float to set the width of the index bar 269 | */ 270 | fun setIndexBarWidth(value: Float) { 271 | mIndexBarWidth = value 272 | } 273 | 274 | /** 275 | * @param value float to set the margin of the index bar 276 | */ 277 | fun setIndexBarMargin(value: Float) { 278 | mIndexBarMarginLeft = value 279 | mIndexBarMarginRight = value 280 | mIndexBarMarginTop = value 281 | mIndexBarMarginBottom = value 282 | } 283 | 284 | /** 285 | * @param value float to set the top margin of the index bar 286 | */ 287 | fun setIndexBarTopMargin(value: Float) { 288 | mIndexBarMarginTop = value 289 | } 290 | 291 | /** 292 | * @param value float to set the bottom margin of the index bar 293 | */ 294 | fun setIndexBarBottomMargin(value: Float) { 295 | mIndexBarMarginBottom = value 296 | } 297 | 298 | /** 299 | * @param value float to set the left margin of the index bar 300 | */ 301 | fun setIndexBarHorizontalMargin(value: Float) { 302 | mIndexBarMarginLeft = value 303 | mIndexBarMarginRight = value 304 | } 305 | 306 | /** 307 | * @param value float to set the right margin of the index bar 308 | */ 309 | fun setIndexBarVerticalMargin(value: Float) { 310 | mIndexBarMarginTop = value 311 | mIndexBarMarginBottom = value 312 | } 313 | 314 | /** 315 | * @param value int to set preview padding 316 | */ 317 | fun setPreviewPadding(value: Int) { 318 | setPreviewPadding = value 319 | } 320 | 321 | /** 322 | * @param value int to set the radius of the index bar 323 | */ 324 | fun setIndexBarCornerRadius(value: Int) { 325 | setIndexBarCornerRadius = value 326 | } 327 | 328 | /** 329 | * @param value float to set the transparency of the color for index bar 330 | */ 331 | fun setIndexBarTransparentValue(value: Float) { 332 | indexbarBackgroudAlpha = convertTransparentValueToBackgroundAlpha(value) 333 | } 334 | 335 | /** 336 | * @param typeface Typeface to set the typeface of the preview & the index bar 337 | */ 338 | fun setTypeface(typeface: Typeface?) { 339 | setTypeface = typeface 340 | } 341 | 342 | /** 343 | * @param shown boolean to show or hide the index bar 344 | */ 345 | fun setIndexBarVisibility(shown: Boolean) { 346 | setIndexBarVisibility = shown 347 | } 348 | 349 | /** 350 | * @param shown boolean to show or hide the index bar 351 | */ 352 | fun setIndexBarStrokeVisibility(shown: Boolean) { 353 | setIndexBarStrokeVisibility = shown 354 | } 355 | 356 | /** 357 | * @param shown boolean to show or hide the preview box 358 | */ 359 | fun setPreviewVisibility(shown: Boolean) { 360 | previewVisibility = shown 361 | } 362 | 363 | /** 364 | * @param value int to set the text size of the preview box 365 | */ 366 | fun setIndexBarStrokeWidth(value: Int) { 367 | mIndexBarStrokeWidth = value 368 | } 369 | 370 | /** 371 | * @param value int to set the text size of the preview box 372 | */ 373 | fun setPreviewTextSize(value: Int) { 374 | setPreviewTextSize = value 375 | } 376 | 377 | /** 378 | * @param color The color for the preview box 379 | */ 380 | fun setPreviewColor(@ColorInt color: Int) { 381 | previewBackgroundColor = color 382 | } 383 | 384 | /** 385 | * @param color The text color for the preview box 386 | */ 387 | fun setPreviewTextColor(@ColorInt color: Int) { 388 | previewTextColor = color 389 | } 390 | 391 | /** 392 | * @param value float to set the transparency value of the preview box 393 | */ 394 | fun setPreviewTransparentValue(value: Float) { 395 | previewBackgroudAlpha = convertTransparentValueToBackgroundAlpha(value) 396 | } 397 | 398 | /** 399 | * @param color The color for the scroll track 400 | */ 401 | fun setIndexBarColor(@ColorInt color: Int) { 402 | indexbarBackgroudColor = color 403 | } 404 | 405 | /** 406 | * @param color The text color for the index bar 407 | */ 408 | fun setIndexBarTextColor(@ColorInt color: Int) { 409 | indexbarTextColor = color 410 | } 411 | 412 | /** 413 | * @param color The text color for the index bar 414 | */ 415 | fun setIndexBarStrokeColor(@ColorInt color: Int) { 416 | mIndexBarStrokeColor = color 417 | } 418 | 419 | /** 420 | * @param color The text color for the index bar 421 | */ 422 | fun setIndexBarHighLightTextColor(@ColorInt color: Int) { 423 | indexbarHighLightTextColor = color 424 | } 425 | 426 | /** 427 | * @param shown boolean to show or hide the index bar 428 | */ 429 | fun setIndexBarHighLightTextVisibility(shown: Boolean) { 430 | setSetIndexBarHighLightTextVisibility = shown 431 | } 432 | 433 | init { 434 | setIndexTextSize = recyclerView.setIndexTextSize 435 | val setIndexbarWidth = recyclerView.mIndexBarWidth 436 | val setIndexbarMarginLeft = recyclerView.mIndexBarMarginLeft 437 | val setIndexbarMarginRight = recyclerView.mIndexBarMarginRight 438 | val setIndexbarMarginTop = recyclerView.mIndexBarMarginTop 439 | val setIndexbarMarginBottom = recyclerView.mIndexBarMarginBottom 440 | setPreviewPadding = recyclerView.mPreviewPadding 441 | setPreviewTextSize = recyclerView.mPreviewTextSize 442 | previewBackgroundColor = recyclerView.mPreviewBackgroundColor 443 | previewTextColor = recyclerView.mPreviewTextColor 444 | previewBackgroudAlpha = 445 | convertTransparentValueToBackgroundAlpha(recyclerView.mPreviewTransparentValue) 446 | mIndexBarStrokeColor = recyclerView.mSetIndexBarStrokeColor 447 | mIndexBarStrokeWidth = recyclerView.mIndexBarStrokeWidth 448 | setIndexBarCornerRadius = recyclerView.mIndexBarCornerRadius 449 | indexbarBackgroudColor = recyclerView.mIndexBarBackgroundColor 450 | indexbarTextColor = recyclerView.mIndexBarTextColor 451 | indexbarHighLightTextColor = recyclerView.mIndexBarHighLightTextColor 452 | indexbarBackgroudAlpha = 453 | convertTransparentValueToBackgroundAlpha(recyclerView.mIndexBarTransparentValue) 454 | mDensity = context.resources.displayMetrics.density 455 | mScaledDensity = context.resources.displayMetrics.scaledDensity 456 | mRecyclerView = recyclerView 457 | mRecyclerView.setLayoutManager(LinearLayoutManager(context)) 458 | setAdapter(mRecyclerView.getAdapter()) 459 | mIndexBarWidth = setIndexbarWidth * mDensity 460 | mIndexBarMarginLeft = setIndexbarMarginLeft * mDensity 461 | mIndexBarMarginRight = setIndexbarMarginRight * mDensity 462 | mIndexBarMarginTop = setIndexbarMarginTop * mDensity 463 | mIndexBarMarginBottom = setIndexbarMarginBottom * mDensity 464 | mPreviewPadding = setPreviewPadding * mDensity 465 | } 466 | } -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/src/main/java/in/myinnos/alphabetsindexfastscrollrecycler/IndexFastScrollRecyclerView.kt: -------------------------------------------------------------------------------- 1 | package `in`.myinnos.alphabetsindexfastscrollrecycler 2 | 3 | 4 | import android.annotation.SuppressLint 5 | import android.content.Context 6 | import android.graphics.Canvas 7 | import android.graphics.Color 8 | import android.graphics.Typeface 9 | import android.util.AttributeSet 10 | import android.util.TypedValue 11 | import android.view.GestureDetector 12 | import android.view.GestureDetector.SimpleOnGestureListener 13 | import android.view.MotionEvent 14 | import androidx.annotation.ColorInt 15 | import androidx.annotation.ColorRes 16 | import androidx.core.content.ContextCompat 17 | import androidx.recyclerview.widget.RecyclerView 18 | 19 | /* 20 | * Created by MyInnos on 31-01-2017. 21 | * Updated by AbandonedCart 07-2022. 22 | */ class IndexFastScrollRecyclerView : RecyclerView { 23 | private var mScroller: IndexFastScrollRecyclerSection? = null 24 | private var mGestureDetector: GestureDetector? = null 25 | private var mEnabled = true 26 | private var mTransient = false 27 | var setIndexTextSize = 12 28 | var mIndexBarWidth = 20f 29 | var mIndexBarMarginLeft = 2f 30 | var mIndexBarMarginRight = 2f 31 | var mIndexBarMarginTop = 2f 32 | var mIndexBarMarginBottom = 2f 33 | var mPreviewPadding = 5 34 | var mIndexBarCornerRadius = 5 35 | var mIndexBarTransparentValue = 0.6.toFloat() 36 | var mIndexBarStrokeWidth = 2 37 | 38 | @ColorInt 39 | var mSetIndexBarStrokeColor = Color.BLACK 40 | 41 | @ColorInt 42 | var mIndexBarBackgroundColor = Color.BLACK 43 | 44 | @ColorInt 45 | var mIndexBarTextColor = Color.WHITE 46 | 47 | @ColorInt 48 | var mIndexBarHighLightTextColor = Color.BLACK 49 | 50 | var mPreviewTextSize = 50 51 | 52 | @ColorInt 53 | var mPreviewBackgroundColor = Color.BLACK 54 | 55 | @ColorInt 56 | var mPreviewTextColor = Color.WHITE 57 | var mPreviewTransparentValue = 0.4.toFloat() 58 | 59 | constructor(context: Context?) : super(context!!) {} 60 | constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { 61 | init(context, attrs) 62 | } 63 | 64 | constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super( 65 | context, 66 | attrs, 67 | defStyle 68 | ) { 69 | init(context, attrs) 70 | } 71 | 72 | private fun init(context: Context, attrs: AttributeSet?) { 73 | if (attrs != null) { 74 | val typedArray = 75 | context.obtainStyledAttributes(attrs, R.styleable.IndexFastScrollRecyclerView) 76 | try { 77 | setIndexTextSize = typedArray.getInt( 78 | R.styleable.IndexFastScrollRecyclerView_setIndexTextSize, 79 | setIndexTextSize 80 | ) 81 | mIndexBarWidth = typedArray.getFloat( 82 | R.styleable.IndexFastScrollRecyclerView_setIndexbarWidth, 83 | mIndexBarWidth 84 | ) 85 | mIndexBarMarginLeft = typedArray.getFloat( 86 | R.styleable.IndexFastScrollRecyclerView_setIndexbarMargin, 87 | mIndexBarMarginLeft 88 | ) 89 | mIndexBarMarginRight = typedArray.getFloat( 90 | R.styleable.IndexFastScrollRecyclerView_setIndexbarMargin, 91 | mIndexBarMarginRight 92 | ) 93 | mIndexBarMarginTop = typedArray.getFloat( 94 | R.styleable.IndexFastScrollRecyclerView_setIndexbarMargin, 95 | mIndexBarMarginTop 96 | ) 97 | mIndexBarMarginBottom = typedArray.getFloat( 98 | R.styleable.IndexFastScrollRecyclerView_setIndexbarMargin, 99 | mIndexBarMarginBottom 100 | ) 101 | mPreviewPadding = typedArray.getInt( 102 | R.styleable.IndexFastScrollRecyclerView_setPreviewPadding, 103 | mPreviewPadding 104 | ) 105 | mIndexBarCornerRadius = typedArray.getInt( 106 | R.styleable.IndexFastScrollRecyclerView_setIndexBarCornerRadius, 107 | mIndexBarCornerRadius 108 | ) 109 | mIndexBarTransparentValue = typedArray.getFloat( 110 | R.styleable.IndexFastScrollRecyclerView_setIndexBarTransparentValue, 111 | mIndexBarTransparentValue 112 | ) 113 | mEnabled = true 114 | if (typedArray.hasValue(R.styleable.IndexFastScrollRecyclerView_setIndexBarShown)) { 115 | mEnabled = typedArray.getBoolean( 116 | R.styleable.IndexFastScrollRecyclerView_setIndexBarShown, 117 | mEnabled 118 | ) 119 | } 120 | mTransient = false 121 | if (typedArray.hasValue(R.styleable.IndexFastScrollRecyclerView_setTransientIndexBar)) { 122 | mTransient = typedArray.getBoolean( 123 | R.styleable.IndexFastScrollRecyclerView_setTransientIndexBar, 124 | mTransient 125 | ) 126 | } 127 | setTransientIndexBar(mTransient) 128 | if (typedArray.hasValue(R.styleable.IndexFastScrollRecyclerView_setIndexBarColor)) { 129 | val tv = TypedValue() 130 | typedArray.getValue( 131 | R.styleable.IndexFastScrollRecyclerView_setIndexBarColor, 132 | tv 133 | ) 134 | mIndexBarBackgroundColor = if (tv.type == TypedValue.TYPE_STRING) { 135 | Color.parseColor(typedArray.getString(R.styleable.IndexFastScrollRecyclerView_setIndexBarColor)) 136 | } else { 137 | typedArray.getColor( 138 | R.styleable.IndexFastScrollRecyclerView_setIndexBarColor, 139 | mIndexBarBackgroundColor 140 | ) 141 | } 142 | } 143 | if (typedArray.hasValue(R.styleable.IndexFastScrollRecyclerView_setIndexBarTextColor)) { 144 | val tv = TypedValue() 145 | typedArray.getValue( 146 | R.styleable.IndexFastScrollRecyclerView_setIndexBarColor, 147 | tv 148 | ) 149 | mIndexBarTextColor = if (tv.type == TypedValue.TYPE_STRING) { 150 | Color.parseColor(typedArray.getString(R.styleable.IndexFastScrollRecyclerView_setIndexBarTextColor)) 151 | } else { 152 | typedArray.getColor( 153 | R.styleable.IndexFastScrollRecyclerView_setIndexBarTextColor, 154 | mIndexBarTextColor 155 | ) 156 | } 157 | } 158 | if (typedArray.hasValue(R.styleable.IndexFastScrollRecyclerView_setIndexBarHighlightTextColor)) { 159 | val tv = TypedValue() 160 | typedArray.getValue( 161 | R.styleable.IndexFastScrollRecyclerView_setIndexBarColor, 162 | tv 163 | ) 164 | mIndexBarHighLightTextColor = if (tv.type == TypedValue.TYPE_STRING) { 165 | Color.parseColor(typedArray.getString(R.styleable.IndexFastScrollRecyclerView_setIndexBarHighlightTextColor)) 166 | } else { 167 | typedArray.getColor( 168 | R.styleable.IndexFastScrollRecyclerView_setIndexBarHighlightTextColor, 169 | mIndexBarHighLightTextColor 170 | ) 171 | } 172 | } 173 | mPreviewTextSize = typedArray.getInt( 174 | R.styleable.IndexFastScrollRecyclerView_setPreviewTextSize, 175 | mPreviewTextSize 176 | ) 177 | mPreviewTransparentValue = typedArray.getFloat( 178 | R.styleable.IndexFastScrollRecyclerView_setPreviewTransparentValue, 179 | mPreviewTransparentValue 180 | ) 181 | if (typedArray.hasValue(R.styleable.IndexFastScrollRecyclerView_setPreviewColor)) { 182 | val tv = TypedValue() 183 | typedArray.getValue( 184 | R.styleable.IndexFastScrollRecyclerView_setIndexBarColor, 185 | tv 186 | ) 187 | mPreviewBackgroundColor = if (tv.type == TypedValue.TYPE_STRING) { 188 | Color.parseColor(typedArray.getString(R.styleable.IndexFastScrollRecyclerView_setPreviewColor)) 189 | } else { 190 | typedArray.getColor( 191 | R.styleable.IndexFastScrollRecyclerView_setPreviewColor, 192 | mPreviewBackgroundColor 193 | ) 194 | } 195 | } 196 | if (typedArray.hasValue(R.styleable.IndexFastScrollRecyclerView_setPreviewTextColor)) { 197 | val tv = TypedValue() 198 | typedArray.getValue( 199 | R.styleable.IndexFastScrollRecyclerView_setIndexBarColor, 200 | tv 201 | ) 202 | mPreviewTextColor = if (tv.type == TypedValue.TYPE_STRING) { 203 | Color.parseColor(typedArray.getString(R.styleable.IndexFastScrollRecyclerView_setPreviewTextColor)) 204 | } else { 205 | typedArray.getColor( 206 | R.styleable.IndexFastScrollRecyclerView_setPreviewTextColor, 207 | mPreviewTextColor 208 | ) 209 | } 210 | } 211 | if (typedArray.hasValue(R.styleable.IndexFastScrollRecyclerView_setIndexBarStrokeWidth)) { 212 | mIndexBarStrokeWidth = typedArray.getInt( 213 | R.styleable.IndexFastScrollRecyclerView_setIndexBarStrokeWidth, 214 | mIndexBarStrokeWidth 215 | ) 216 | } 217 | if (typedArray.hasValue(R.styleable.IndexFastScrollRecyclerView_setIndexBarStrokeColor)) { 218 | val tv = TypedValue() 219 | typedArray.getValue( 220 | R.styleable.IndexFastScrollRecyclerView_setIndexBarColor, 221 | tv 222 | ) 223 | mSetIndexBarStrokeColor = if (tv.type == TypedValue.TYPE_STRING) { 224 | Color.parseColor(typedArray.getString(R.styleable.IndexFastScrollRecyclerView_setIndexBarStrokeColor)) 225 | } else { 226 | typedArray.getColor( 227 | R.styleable.IndexFastScrollRecyclerView_setIndexBarStrokeColor, 228 | mSetIndexBarStrokeColor 229 | ) 230 | } 231 | } 232 | } finally { 233 | typedArray.recycle() 234 | } 235 | 236 | // This line here is necessary else the attributes won't be updated if a value is passed from XML 237 | mScroller = IndexFastScrollRecyclerSection(context, this) 238 | mScroller?.setIndexBarVisibility(mEnabled) 239 | } 240 | } 241 | 242 | override fun draw(canvas: Canvas) { 243 | super.draw(canvas) 244 | // Overlay index bar 245 | if (mScroller != null) mScroller?.draw(canvas) 246 | } 247 | 248 | @SuppressLint("ClickableViewAccessibility") 249 | override fun onTouchEvent(ev: MotionEvent): Boolean { 250 | if (mEnabled) { 251 | // Intercept ListView's touch event 252 | if (mScroller != null && mScroller!!.onTouchEvent(ev)) return true 253 | if (mGestureDetector == null) { 254 | mGestureDetector = GestureDetector(context, object : SimpleOnGestureListener() { 255 | override fun onFling( 256 | e1: MotionEvent, e2: MotionEvent, 257 | velocityX: Float, velocityY: Float 258 | ): Boolean { 259 | return super.onFling(e1, e2, velocityX, velocityY) 260 | } 261 | }) 262 | } 263 | mGestureDetector?.onTouchEvent(ev) 264 | } 265 | return super.onTouchEvent(ev) 266 | } 267 | 268 | override fun onInterceptTouchEvent(ev: MotionEvent): Boolean { 269 | return if (mEnabled && mScroller != null && mScroller!!.contains(ev.x, ev.y)) true 270 | else super.onInterceptTouchEvent(ev) 271 | } 272 | 273 | override fun setAdapter(adapter: Adapter<*>?) { 274 | super.setAdapter(adapter) 275 | if (mScroller != null) mScroller?.setAdapter(adapter as Adapter?) 276 | } 277 | 278 | override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { 279 | super.onSizeChanged(w, h, oldw, oldh) 280 | if (mScroller != null) mScroller?.onSizeChanged(w, h) 281 | } 282 | 283 | /** 284 | * @param value int to set the text size of the index bar 285 | */ 286 | fun setIndexTextSize(value: Int) { 287 | mScroller?.setIndexTextSize(value) 288 | } 289 | 290 | /** 291 | * @param value float to set the width of the index bar 292 | */ 293 | fun setIndexBarWidth(value: Float) { 294 | mScroller?.setIndexBarWidth(value) 295 | } 296 | 297 | /** 298 | * @param value float to set the margin of the index bar 299 | */ 300 | fun setIndexBarMargin(value: Float) { 301 | mScroller?.setIndexBarMargin(value) 302 | } 303 | 304 | /** 305 | * @param value float to set the top margin of the index bar 306 | */ 307 | fun setIndexBarTopMargin(value: Float) { 308 | mScroller?.setIndexBarTopMargin(value) 309 | } 310 | 311 | /** 312 | * @param value float to set the bottom margin of the index bar 313 | */ 314 | fun setIndexBarBottomMargin(value: Float) { 315 | mScroller?.setIndexBarBottomMargin(value) 316 | } 317 | 318 | /** 319 | * @param value float to set the Horizontal margin of the index bar 320 | */ 321 | fun setIndexBarHorizontalMargin(value: Float) { 322 | mScroller?.setIndexBarHorizontalMargin(value) 323 | } 324 | 325 | /** 326 | * @param value float to set the Vertical margin of the index bar 327 | */ 328 | fun setIndexBarVerticalMargin(value: Float) { 329 | mScroller?.setIndexBarVerticalMargin(value) 330 | } 331 | 332 | /** 333 | * @param value int to set the preview padding 334 | */ 335 | fun setPreviewPadding(value: Int) { 336 | mScroller?.setPreviewPadding(value) 337 | } 338 | 339 | /** 340 | * @param value int to set the corner radius of the index bar 341 | */ 342 | fun setIndexBarCornerRadius(value: Int) { 343 | mScroller?.setIndexBarCornerRadius(value) 344 | } 345 | 346 | /** 347 | * @param value float to set the transparency value of the index bar 348 | */ 349 | fun setIndexBarTransparentValue(value: Float) { 350 | mScroller?.setIndexBarTransparentValue(value) 351 | } 352 | 353 | /** 354 | * @param typeface Typeface to set the typeface of the preview & the index bar 355 | */ 356 | fun setTypeface(typeface: Typeface?) { 357 | mScroller?.setTypeface(typeface) 358 | } 359 | 360 | /** 361 | * @param shown boolean to show or hide the index bar 362 | */ 363 | fun setIndexBarVisibility(shown: Boolean) { 364 | mScroller?.setIndexBarVisibility(shown) 365 | mEnabled = shown 366 | } 367 | 368 | private val scrollRunnable = Runnable { 369 | mScroller?.setIndexBarVisibility(false) 370 | invalidate() 371 | } 372 | private val scrollListener: OnScrollListener = object : OnScrollListener() { 373 | override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { 374 | super.onScrollStateChanged(recyclerView, newState) 375 | if (newState == SCROLL_STATE_DRAGGING) { 376 | recyclerView.removeCallbacks(scrollRunnable) 377 | mScroller?.setIndexBarVisibility(true) 378 | } else if (newState == SCROLL_STATE_IDLE) { 379 | recyclerView.postDelayed(scrollRunnable, 1000) 380 | } 381 | } 382 | } 383 | 384 | fun setTransientIndexBar(enabled: Boolean) { 385 | if (enabled) { 386 | setOnScrollListener(scrollListener) 387 | } else { 388 | removeCallbacks(scrollRunnable) 389 | removeOnScrollListener(scrollListener) 390 | } 391 | mTransient = enabled 392 | } 393 | 394 | /** 395 | * @param shown boolean to show or hide the index bar 396 | */ 397 | fun setIndexBarStrokeVisibility(shown: Boolean) { 398 | mScroller?.setIndexBarStrokeVisibility(shown) 399 | } 400 | 401 | /** 402 | * @param color The color for the index bar 403 | */ 404 | fun setIndexBarStrokeColor(color: String?) { 405 | mScroller?.setIndexBarStrokeColor(Color.parseColor(color)) 406 | } 407 | 408 | /** 409 | * @param color The color for the preview box 410 | */ 411 | fun setIndexBarStrokeColor(@ColorRes color: Int) { 412 | mScroller?.setIndexBarStrokeColor(ContextCompat.getColor(context, color)) 413 | } 414 | 415 | /** 416 | * @param value int to set the text size of the preview box 417 | */ 418 | fun setIndexBarStrokeWidth(value: Int) { 419 | mScroller?.setIndexBarStrokeWidth(value) 420 | } 421 | 422 | /** 423 | * @param shown boolean to show or hide the preview 424 | */ 425 | fun setPreviewVisibility(shown: Boolean) { 426 | mScroller?.setPreviewVisibility(shown) 427 | } 428 | 429 | /** 430 | * @param value int to set the text size of the preview box 431 | */ 432 | fun setPreviewTextSize(value: Int) { 433 | mScroller?.setPreviewTextSize(value) 434 | } 435 | 436 | /** 437 | * @param color The color for the preview box 438 | */ 439 | fun setPreviewColor(@ColorRes color: Int) { 440 | mScroller?.setPreviewColor(ContextCompat.getColor(context, color)) 441 | } 442 | 443 | /** 444 | * @param color The color for the preview box 445 | */ 446 | fun setPreviewColor(color: String?) { 447 | mScroller?.setPreviewColor(Color.parseColor(color)) 448 | } 449 | 450 | /** 451 | * @param color The text color for the preview box 452 | */ 453 | fun setPreviewTextColor(@ColorRes color: Int) { 454 | mScroller?.setPreviewTextColor(ContextCompat.getColor(context, color)) 455 | } 456 | 457 | /** 458 | * @param value float to set the transparency value of the preview box 459 | */ 460 | fun setPreviewTransparentValue(value: Float) { 461 | mScroller?.setPreviewTransparentValue(value) 462 | } 463 | 464 | /** 465 | * @param color The text color for the preview box 466 | */ 467 | fun setPreviewTextColor(color: String?) { 468 | mScroller?.setPreviewTextColor(Color.parseColor(color)) 469 | } 470 | 471 | /** 472 | * @param color The color for the index bar 473 | */ 474 | fun setIndexBarColor(color: String?) { 475 | mScroller?.setIndexBarColor(Color.parseColor(color)) 476 | } 477 | 478 | /** 479 | * @param color The color for the index bar 480 | */ 481 | fun setIndexBarColor(@ColorRes color: Int) { 482 | mScroller?.setIndexBarColor(ContextCompat.getColor(context, color)) 483 | } 484 | 485 | /** 486 | * @param color The text color for the index bar 487 | */ 488 | fun setIndexBarTextColor(color: String?) { 489 | mScroller?.setIndexBarTextColor(Color.parseColor(color)) 490 | } 491 | 492 | /** 493 | * @param color The text color for the index bar 494 | */ 495 | fun setIndexBarTextColor(@ColorRes color: Int) { 496 | mScroller?.setIndexBarTextColor(ContextCompat.getColor(context, color)) 497 | } 498 | 499 | /** 500 | * @param color The text color for the index bar 501 | */ 502 | fun setIndexBarHighLightTextColor(color: String?) { 503 | mScroller?.setIndexBarHighLightTextColor(Color.parseColor(color)) 504 | } 505 | 506 | /** 507 | * @param color The text color for the index bar 508 | */ 509 | fun setIndexBarHighLightTextColor(@ColorRes color: Int) { 510 | mScroller?.setIndexBarHighLightTextColor(ContextCompat.getColor(context, color)) 511 | } 512 | 513 | /** 514 | * @param shown boolean to show or hide the index bar 515 | */ 516 | fun setIndexBarHighLightTextVisibility(shown: Boolean) { 517 | mScroller?.setIndexBarHighLightTextVisibility(shown) 518 | } 519 | 520 | fun updateSections() { 521 | mScroller?.updateSections() 522 | } 523 | } -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/src/main/java/in/myinnos/alphabetsindexfastscrollrecycler/utilities_fs/StringMatcher.java: -------------------------------------------------------------------------------- 1 | package in.myinnos.alphabetsindexfastscrollrecycler.utilities_fs; 2 | 3 | /** 4 | * Created by MyInnos on 31-01-2017. 5 | */ 6 | 7 | public class StringMatcher { 8 | public static boolean match(String value, String keyword) { 9 | if (value == null || keyword == null) 10 | return false; 11 | if (keyword.length() > value.length()) 12 | return false; 13 | 14 | int i = 0, j = 0; 15 | do { 16 | if (keyword.charAt(j) == value.charAt(i)) { 17 | i++; 18 | j++; 19 | } else if (j > 0) 20 | break; 21 | else 22 | i++; 23 | } while (i < value.length() && j < keyword.length()); 24 | 25 | return (j == keyword.length())? true : false; 26 | } 27 | } -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/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 | -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AlphabetsIndexFastScrollRecycler 3 | 4 | -------------------------------------------------------------------------------- /alphabetsindexfastscrollrecycler/src/main/resources/META-INF/com/github/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/verification.properties: -------------------------------------------------------------------------------- 1 | #This is the verification token for the com.github.myinnos:AlphabetIndex-Fast-Scroll-RecyclerView SDK. 2 | #Thu Sep 05 05:48:29 PDT 2024 3 | token=6BDJND3E25BTNCOHKZTZL35WUI 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-kapt' 4 | 5 | 6 | final ANDROIDX = '1.0.0' 7 | final BUTTERKNIFE = '10.1.0' 8 | 9 | android { 10 | compileSdkVersion 33 11 | 12 | defaultConfig { 13 | applicationId "in.myinnos.indexfastscrollrecycler" 14 | minSdkVersion 15 15 | targetSdkVersion 33 16 | versionCode 1 17 | versionName "1.0" 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | compileOptions { 27 | sourceCompatibility JavaVersion.VERSION_1_8 28 | targetCompatibility JavaVersion.VERSION_1_8 29 | } 30 | 31 | buildFeatures { 32 | dataBinding true 33 | } 34 | } 35 | 36 | dependencies { 37 | implementation "androidx.appcompat:appcompat:${ANDROIDX}" 38 | implementation "com.google.android.material:material:${ANDROIDX}" 39 | implementation "com.jakewharton:butterknife:${BUTTERKNIFE}" 40 | annotationProcessor "com.jakewharton:butterknife-compiler:${BUTTERKNIFE}" 41 | implementation project(':alphabetsindexfastscrollrecyclerLibrary') 42 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 43 | implementation 'androidx.core:core-ktx:1.10.0' 44 | 45 | // reflection-based flavor 46 | implementation 'com.github.kirich1409:viewbindingpropertydelegate-full:1.5.8' 47 | // reflection-free flavor 48 | implementation 'com.github.kirich1409:viewbindingpropertydelegate-noreflection:1.5.8' 49 | } 50 | repositories { 51 | mavenCentral() 52 | } 53 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in C:\Users\10\AppData\Local\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 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/in/myinnos/indexfastscrollrecycler/Helpers.kt: -------------------------------------------------------------------------------- 1 | package `in`.myinnos.indexfastscrollrecycler 2 | 3 | import java.util.ArrayList 4 | import java.util.HashMap 5 | 6 | class Helpers { 7 | companion object { 8 | fun sectionsHelper(sections: MutableList, test: ArrayList): HashMap { 9 | val mapOfSections = hashMapOf() 10 | var lastFound = 0 11 | test.forEachIndexed { index, s -> 12 | if (sections.any { it == s }) { 13 | val value = sections.indexOfFirst { it == s } 14 | mapOfSections[index] = value 15 | lastFound = value 16 | } else { 17 | mapOfSections[index] = lastFound 18 | } 19 | } 20 | return mapOfSections 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /app/src/main/java/in/myinnos/indexfastscrollrecycler/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package `in`.myinnos.indexfastscrollrecycler 2 | 3 | 4 | import `in`.myinnos.alphabetsindexfastscrollrecycler.IndexFastScrollRecyclerView 5 | import `in`.myinnos.indexfastscrollrecycler.adapter.RecyclerViewAdapter 6 | import `in`.myinnos.indexfastscrollrecycler.helper.DataHelper 7 | import `in`.myinnos.indexfastscrollrecycler.utility.AlphabetItem 8 | import android.os.Bundle 9 | import androidx.appcompat.app.AppCompatActivity 10 | import androidx.recyclerview.widget.LinearLayoutManager 11 | import androidx.recyclerview.widget.RecyclerView 12 | import java.util.* 13 | 14 | class MainActivity : AppCompatActivity() { 15 | 16 | var mRecyclerView: IndexFastScrollRecyclerView? = null 17 | 18 | private val mAlphabetItems by lazy { ArrayList() } 19 | 20 | // getAlphabetFullData() - full data, getAlphabetNotFullData() - not full data 21 | private val mDataArray by lazy { DataHelper.getAlphabetFullData() } 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | setContentView(R.layout.activity_main) 26 | mRecyclerView = findViewById(R.id.fast_scroller_recycler) 27 | initialiseData() 28 | initialiseUI() 29 | } 30 | 31 | private fun initialiseData() { 32 | //Alphabet fast scroller data 33 | val strAlphabets: MutableList = ArrayList() 34 | for (i in mDataArray.indices) { 35 | val name = mDataArray[i] 36 | if (name.trim { it <= ' ' }.isEmpty()) continue 37 | val word = name.substring(0, 1) 38 | if (!strAlphabets.contains(word)) { 39 | strAlphabets.add(word) 40 | mAlphabetItems.add(AlphabetItem(i, word, false)) 41 | } 42 | } 43 | } 44 | 45 | private fun initialiseUI() { 46 | mRecyclerView?.apply { 47 | layoutManager = LinearLayoutManager(this@MainActivity) 48 | adapter = RecyclerViewAdapter(mDataArray) 49 | setIndexTextSize(12) 50 | setIndexBarColor(R.color.color_setIndexBarColor) 51 | setIndexBarCornerRadius(0) 52 | setIndexBarTransparentValue(0.4.toFloat()) 53 | setIndexBarTopMargin(60f) 54 | setIndexBarBottomMargin(100f) 55 | setIndexBarHorizontalMargin(20f) 56 | setPreviewPadding(0) 57 | setIndexBarTextColor(R.color.color_setIndexBarTextColor) 58 | setPreviewTextSize(60) 59 | setPreviewColor(R.color.color_setPreviewColor) 60 | setPreviewTextColor(R.color.color_setPreviewTextColor) 61 | setPreviewTransparentValue(0.6f) 62 | setIndexBarVisibility(true) 63 | setIndexBarStrokeVisibility(true) 64 | setIndexBarStrokeWidth(1) 65 | setIndexBarStrokeColor(R.color.color_setIndexBarStrokeColor) 66 | setIndexBarHighLightTextColor(R.color.color_setIndexBarHighLightTextColor) 67 | setIndexBarHighLightTextVisibility(true) 68 | } 69 | Objects.requireNonNull(mRecyclerView?.layoutManager) 70 | .scrollToPosition(0) 71 | } 72 | } -------------------------------------------------------------------------------- /app/src/main/java/in/myinnos/indexfastscrollrecycler/adapter/RecyclerViewAdapter.kt: -------------------------------------------------------------------------------- 1 | package `in`.myinnos.indexfastscrollrecycler.adapter 2 | 3 | import `in`.myinnos.indexfastscrollrecycler.Helpers.Companion.sectionsHelper 4 | import `in`.myinnos.indexfastscrollrecycler.R 5 | import android.widget.SectionIndexer 6 | import android.view.ViewGroup 7 | import android.view.LayoutInflater 8 | import android.view.View 9 | import android.widget.TextView 10 | import android.widget.ImageButton 11 | import androidx.recyclerview.widget.RecyclerView 12 | import java.util.* 13 | import kotlin.collections.ArrayList 14 | 15 | /** 16 | * Created by MyInnos on 01-02-2017. 17 | */ 18 | class RecyclerViewAdapter(private val mDataArray: ArrayList?) : 19 | RecyclerView.Adapter(), SectionIndexer { 20 | 21 | private val mSections = "ABCDEFGHIJKLMNOPQRSTUVWXYZ#" 22 | private var sectionsTranslator = HashMap() 23 | private var mSectionPositions: ArrayList? = null 24 | 25 | override fun getItemCount(): Int { 26 | return mDataArray?.size ?: 0 27 | } 28 | 29 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { 30 | val v: View = LayoutInflater.from(parent.context) 31 | .inflate(R.layout.item_recycler_view_layout, parent, false) 32 | return ViewHolder(v) 33 | } 34 | 35 | override fun onBindViewHolder(holder: ViewHolder, position: Int) { 36 | holder.mTextView.text = mDataArray!![position] 37 | holder.mImageButton.setOnClickListener { 38 | mDataArray.removeAt(holder.adapterPosition) 39 | notifyDataSetChanged() 40 | } 41 | } 42 | 43 | override fun getSectionForPosition(position: Int): Int { 44 | return 0 45 | } 46 | 47 | override fun getSections(): Array { 48 | /* List sections = new ArrayList<>(26); 49 | mSectionPositions = new ArrayList<>(26); 50 | for (int i = 0, size = mDataArray.size(); i < size; i++) { 51 | String section = String.valueOf(mDataArray.get(i).charAt(0)).toUpperCase(); 52 | if (!sections.contains(section)) { 53 | sections.add(section); 54 | mSectionPositions.add(i); 55 | } 56 | } */ 57 | val sections: MutableList = ArrayList(27) 58 | val alphabetFull = ArrayList() 59 | mSectionPositions = ArrayList() 60 | run { 61 | var i = 0 62 | val size = mDataArray!!.size 63 | while (i < size) { 64 | val section = mDataArray[i][0].toString().uppercase(Locale.getDefault()) 65 | if (!sections.contains(section)) { 66 | sections.add(section) 67 | mSectionPositions?.add(i) 68 | } 69 | i++ 70 | } 71 | } 72 | for (element in mSections) { 73 | alphabetFull.add(element.toString()) 74 | } 75 | sectionsTranslator = sectionsHelper(sections, alphabetFull) 76 | return alphabetFull.toTypedArray() 77 | } 78 | 79 | override fun getPositionForSection(sectionIndex: Int): Int { 80 | return mSectionPositions!![sectionsTranslator[sectionIndex]!!] 81 | } 82 | 83 | class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { 84 | var mTextView: TextView 85 | var mImageButton: ImageButton 86 | 87 | init { 88 | mTextView = itemView.findViewById(R.id.tv_alphabet) 89 | mImageButton = itemView.findViewById(R.id.ib_alphabet) 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /app/src/main/java/in/myinnos/indexfastscrollrecycler/helper/DataHelper.kt: -------------------------------------------------------------------------------- 1 | package `in`.myinnos.indexfastscrollrecycler.helper 2 | 3 | import java.util.ArrayList 4 | 5 | /** 6 | * Created by MyInnos on 01-02-2017. 7 | */ 8 | object DataHelper { 9 | fun getAlphabetFullData(): ArrayList { 10 | return ArrayList().apply { 11 | add("A item 1") 12 | add("A item 2") 13 | add("A item 3") 14 | add("A item 4") 15 | add("A item 5") 16 | add("B item 1") 17 | add("B item 2") 18 | add("B item 3") 19 | add("B item 4") 20 | add("B item 5") 21 | add("C item 1") 22 | add("C item 2") 23 | add("C item 3") 24 | add("C item 4") 25 | add("C item 5") 26 | add("D item 1") 27 | add("D item 2") 28 | add("D item 3") 29 | add("D item 4") 30 | add("D item 5") 31 | add("E item 1") 32 | add("E item 2") 33 | add("E item 3") 34 | add("E item 4") 35 | add("E item 5") 36 | add("F item 1") 37 | add("F item 2") 38 | add("F item 3") 39 | add("F item 4") 40 | add("F item 5") 41 | add("G item 1") 42 | add("G item 2") 43 | add("G item 3") 44 | add("G item 4") 45 | add("G item 5") 46 | add("H item 1") 47 | add("H item 2") 48 | add("H item 3") 49 | add("H item 4") 50 | add("H item 5") 51 | add("I item 1") 52 | add("I item 2") 53 | add("I item 3") 54 | add("I item 4") 55 | add("I item 5") 56 | add("J item 1") 57 | add("J item 2") 58 | add("J item 3") 59 | add("J item 4") 60 | add("J item 5") 61 | add("K item 1") 62 | add("K item 2") 63 | add("K item 3") 64 | add("K item 4") 65 | add("K item 5") 66 | add("L item 1") 67 | add("L item 2") 68 | add("L item 3") 69 | add("L item 4") 70 | add("L item 5") 71 | add("M item 1") 72 | add("M item 2") 73 | add("M item 3") 74 | add("M item 4") 75 | add("M item 5") 76 | add("N item 1") 77 | add("N item 2") 78 | add("N item 3") 79 | add("N item 4") 80 | add("N item 5") 81 | add("O item 1") 82 | add("O item 2") 83 | add("O item 3") 84 | add("O item 4") 85 | add("O item 5") 86 | add("P item 1") 87 | add("P item 2") 88 | add("P item 3") 89 | add("P item 4") 90 | add("P item 5") 91 | add("Q item 1") 92 | add("Q item 2") 93 | add("Q item 3") 94 | add("Q item 4") 95 | add("Q item 5") 96 | add("R item 1") 97 | add("R item 2") 98 | add("R item 3") 99 | add("R item 4") 100 | add("R item 5") 101 | add("S item 1") 102 | add("S item 2") 103 | add("S item 3") 104 | add("S item 4") 105 | add("S item 5") 106 | add("T item 1") 107 | add("T item 2") 108 | add("T item 3") 109 | add("T item 4") 110 | add("T item 5") 111 | add("U item 1") 112 | add("U item 2") 113 | add("U item 3") 114 | add("U item 4") 115 | add("U item 5") 116 | add("V item 1") 117 | add("V item 2") 118 | add("V item 3") 119 | add("V item 4") 120 | add("V item 5") 121 | add("W item 1") 122 | add("W item 2") 123 | add("W item 3") 124 | add("W item 4") 125 | add("W item 5") 126 | add("X item 1") 127 | add("X item 2") 128 | add("X item 3") 129 | add("X item 4") 130 | add("X item 5") 131 | add("Y item 1") 132 | add("Y item 2") 133 | add("Y item 3") 134 | add("Y item 4") 135 | add("Y item 5") 136 | add("Z item 1") 137 | add("Z item 2") 138 | add("Z item 3") 139 | add("Z item 4") 140 | add("Z item 5") 141 | } 142 | } 143 | 144 | fun getAlphabetNotFullData(): ArrayList { 145 | return ArrayList().apply { 146 | add("A item 1") 147 | add("A item 2") 148 | add("A item 3") 149 | add("A item 4") 150 | add("A item 5") 151 | add("B item 1") 152 | add("B item 2") 153 | add("B item 3") 154 | add("B item 4") 155 | add("B item 5") 156 | add("C item 1") 157 | add("C item 2") 158 | add("C item 3") 159 | add("C item 4") 160 | add("C item 5") 161 | add("D item 1") 162 | add("D item 2") 163 | add("D item 3") 164 | add("D item 4") 165 | add("D item 5") 166 | add("E item 1") 167 | add("E item 2") 168 | add("E item 3") 169 | add("E item 4") 170 | add("E item 5") 171 | add("F item 1") 172 | add("F item 2") 173 | add("F item 3") 174 | add("F item 4") 175 | add("F item 5") 176 | add("G item 1") 177 | add("G item 2") 178 | add("G item 3") 179 | add("G item 4") 180 | add("G item 5") 181 | add("H item 1") 182 | add("H item 2") 183 | add("H item 3") 184 | add("H item 4") 185 | add("H item 5") 186 | add("I item 1") 187 | add("I item 2") 188 | add("I item 3") 189 | add("I item 4") 190 | add("I item 5") 191 | add("J item 1") 192 | add("J item 2") 193 | add("J item 3") 194 | add("J item 4") 195 | add("J item 5") 196 | add("K item 1") 197 | add("K item 2") 198 | add("K item 3") 199 | add("K item 4") 200 | add("K item 5") 201 | add("L item 1") 202 | add("L item 2") 203 | add("L item 3") 204 | add("L item 4") 205 | add("L item 5") 206 | add("M item 1") 207 | add("M item 2") 208 | add("M item 3") 209 | add("M item 4") 210 | add("M item 5") 211 | add("N item 1") 212 | add("N item 2") 213 | add("N item 3") 214 | add("N item 4") 215 | add("N item 5") 216 | add("Z item 1") 217 | add("Z item 2") 218 | add("Z item 3") 219 | add("Z item 4") 220 | add("Z item 5") 221 | } 222 | } 223 | } -------------------------------------------------------------------------------- /app/src/main/java/in/myinnos/indexfastscrollrecycler/utility/AlphabetItem.kt: -------------------------------------------------------------------------------- 1 | package `in`.myinnos.indexfastscrollrecycler.utility 2 | 3 | /** 4 | * Created by MyInnos on 01-02-2017. 5 | */ 6 | class AlphabetItem(var position: Int, var word: String, var isActive: Boolean) -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/app/src/main/res/drawable-hdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/app/src/main/res/drawable-mdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/app/src/main/res/drawable-xhdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/app/src/main/res/drawable-xxhdpi/ic_delete.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_recycler_view_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 14 | 15 | 23 | 24 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | #33334c 8 | #FFFFFF 9 | #33334c 10 | #FFFFFF 11 | #000000 12 | #33334c 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Index Fast Scroll Recycler 3 | Delete item 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = "1.8.10" 5 | repositories { 6 | google() 7 | mavenCentral() 8 | maven { 9 | url "https://maven.google.com" 10 | } 11 | google() 12 | } 13 | dependencies { 14 | classpath 'com.android.tools.build:gradle:7.2.2' 15 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1' 16 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | google() 25 | mavenCentral() 26 | maven { 27 | url "https://maven.google.com" 28 | } 29 | } 30 | } 31 | 32 | task clean(type: Delete) { 33 | delete rootProject.buildDir 34 | } 35 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | android.enableJetifier=true 19 | android.useAndroidX=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Mon Aug 12 10:24:43 IST 2019 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-7.3.3-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 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /images-gif/AlphabetIndex-Fast-Scroll-RecyclerView_1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/images-gif/AlphabetIndex-Fast-Scroll-RecyclerView_1.gif -------------------------------------------------------------------------------- /images-gif/AlphabetIndex-Fast-Scroll-RecyclerView_2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/images-gif/AlphabetIndex-Fast-Scroll-RecyclerView_2.gif -------------------------------------------------------------------------------- /images-gif/AlphabetIndex-Fast-Scroll-RecyclerView_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myinnos/AlphabetIndex-Fast-Scroll-RecyclerView/e68cfc1ccaa70cad87d87db393f7d215f99b0674/images-gif/AlphabetIndex-Fast-Scroll-RecyclerView_3.gif -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':alphabetsindexfastscrollrecyclerLibrary' 2 | project(':alphabetsindexfastscrollrecyclerLibrary').projectDir = new File('alphabetsindexfastscrollrecycler') 3 | 4 | include ':app' --------------------------------------------------------------------------------