├── settings.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── wildscrolllibrary
├── src
│ └── main
│ │ ├── res
│ │ ├── values
│ │ │ ├── strings.xml
│ │ │ ├── ids.xml
│ │ │ ├── colors.xml
│ │ │ ├── dimens.xml
│ │ │ └── attrs_wildscroll.xml
│ │ ├── drawable
│ │ │ ├── fastscroll_background_popup.xml
│ │ │ └── fastscroll_popup_circle.xml
│ │ └── layout
│ │ │ └── popup_section.xml
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ └── appspell
│ │ └── wildscroll
│ │ ├── adapter
│ │ ├── SectionFastScroll.kt
│ │ └── SectionFastScrollAdapter.kt
│ │ ├── sections
│ │ ├── popup
│ │ │ ├── SectionPopup.kt
│ │ │ ├── SectionCirclePopup.kt
│ │ │ └── SectionLetterPopup.kt
│ │ ├── Sections.kt
│ │ ├── fastscroll
│ │ │ └── FastScroll.kt
│ │ └── SectionBarView.kt
│ │ ├── coroutines
│ │ └── Android.kt
│ │ └── view
│ │ └── WildScrollRecyclerView.kt
├── proguard-rules.pro
├── .gitignore
└── build.gradle
├── app
├── src
│ └── main
│ │ ├── res
│ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ └── ic_launcher_round.png
│ │ ├── values
│ │ │ ├── dimens.xml
│ │ │ ├── strings.xml
│ │ │ ├── styles.xml
│ │ │ └── colors.xml
│ │ ├── drawable-mdpi
│ │ │ ├── background_circle.xml
│ │ │ └── background_popup.xml
│ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ ├── drawable
│ │ │ ├── ic_circle.xml
│ │ │ ├── ic_android.xml
│ │ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ │ ├── fragment_simple.xml
│ │ │ ├── fragment_custom_programmatically.xml
│ │ │ ├── fragment_sections.xml
│ │ │ ├── activity_main.xml
│ │ │ ├── fragment_custom.xml
│ │ │ ├── item_sections_section.xml
│ │ │ ├── item_sample_list.xml
│ │ │ ├── item_sections_item.xml
│ │ │ └── item_second_sample_list.xml
│ │ └── drawable-v24
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── java
│ │ └── com
│ │ │ └── appspell
│ │ │ └── wildscroll
│ │ │ ├── data
│ │ │ ├── Company.kt
│ │ │ └── DataSource.kt
│ │ │ ├── fragments
│ │ │ ├── SimpleFragment.kt
│ │ │ ├── CustomLayoutFragment.kt
│ │ │ ├── SectionsFragment.kt
│ │ │ └── CustomProgrammaticallyFragment.kt
│ │ │ ├── adapter
│ │ │ ├── SimpleAdapter.kt
│ │ │ ├── SimpleSecondAdapter.kt
│ │ │ └── SectionsAdapter.kt
│ │ │ └── MainActivity.kt
│ │ └── AndroidManifest.xml
├── proguard-rules.pro
├── .gitignore
└── build.gradle
├── .idea
├── vcs.xml
├── modules.xml
├── runConfigurations.xml
└── misc.xml
├── gradle.properties
├── .gitignore
├── LICENSE
├── gradlew.bat
├── gradlew
└── README.md
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':wildscrolllibrary'
2 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | WildScrollLibrary
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/appspell/Wild-Scroll/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/java/com/appspell/wildscroll/adapter/SectionFastScroll.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.adapter
2 |
3 | interface SectionFastScroll {
4 | fun getSectionName(position: Int): String
5 | }
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/data/Company.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.data
2 |
3 | data class Company(val company: String,
4 | val phrase: String,
5 | val street: String,
6 | val avatar: String)
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 8dp
4 | 12sp
5 | 16sp
6 | 42sp
7 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/res/drawable/fastscroll_background_popup.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/background_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Jan 02 15:11:03 MSK 2018
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-4.1-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/res/drawable/fastscroll_popup_circle.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Wild Scroll
3 | Simple
4 | Layout
5 | Programmatically
6 | Sections
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-mdpi/background_popup.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_circle.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #00000000
4 | #85000000
5 | #d9000000
6 | #07000000
7 | #1c757575
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 24sp
4 | 16dp
5 |
6 | 3dp
7 |
8 | 10sp
9 | 13sp
10 | 8dp
11 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #2196F3
4 | #2196F3
5 | #0D47A1
6 | #E3F2FD
7 | #00BCD4
8 | #006064
9 | #E0F7FA
10 | #d8000000
11 | #82000000
12 | #10000000
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_simple.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_custom_programmatically.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/res/layout/popup_section.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
18 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/java/com/appspell/wildscroll/adapter/SectionFastScrollAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.adapter
2 |
3 | import android.support.v7.widget.RecyclerView
4 | import android.support.v7.widget.RecyclerView.ViewHolder
5 | import com.appspell.wildscroll.sections.SectionInfo
6 |
7 | abstract class SectionFastScrollAdapter : RecyclerView.Adapter(), SectionFastScroll {
8 |
9 | var sections: Map = emptyMap()
10 | set(value) {
11 | field = value
12 | value.values.forEach { section ->
13 | notifyItemChanged(section.position)
14 | }
15 | }
16 |
17 | open fun isSection(position: Int): Boolean = sections.containsKey(position)
18 |
19 | fun getSectionInfo(position: Int) = sections[position]
20 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/wildscrolllibrary/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_android.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # Intellij
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/dictionaries
41 | .idea/libraries
42 |
43 | # Keystore files
44 | *.jks
45 |
46 | # External native build folder generated in Android Studio 2.2 and later
47 | .externalNativeBuild
48 |
49 | # Google Services (e.g. APIs or Firebase)
50 | google-services.json
51 |
52 | # Freeline
53 | freeline.py
54 | freeline/
55 | freeline_project_description.json
56 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # Intellij
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/dictionaries
41 | .idea/libraries
42 |
43 | # Keystore files
44 | *.jks
45 |
46 | # External native build folder generated in Android Studio 2.2 and later
47 | .externalNativeBuild
48 |
49 | # Google Services (e.g. APIs or Firebase)
50 | google-services.json
51 |
52 | # Freeline
53 | freeline.py
54 | freeline/
55 | freeline_project_description.json
--------------------------------------------------------------------------------
/wildscrolllibrary/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # Intellij
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/dictionaries
41 | .idea/libraries
42 |
43 | # Keystore files
44 | *.jks
45 |
46 | # External native build folder generated in Android Studio 2.2 and later
47 | .externalNativeBuild
48 |
49 | # Google Services (e.g. APIs or Firebase)
50 | google-services.json
51 |
52 | # Freeline
53 | freeline.py
54 | freeline/
55 | freeline_project_description.json
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/java/com/appspell/wildscroll/sections/popup/SectionPopup.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.sections.popup
2 |
3 | import android.graphics.Canvas
4 | import android.graphics.Rect
5 | import com.appspell.wildscroll.sections.Sections
6 |
7 | interface SectionPopup {
8 | fun show(section: String, x: Int, y: Int, parentWidth: Int, parentHeight: Int, sections: Sections)
9 | fun dismiss()
10 | fun draw(canvas: Canvas)
11 | fun getRect(): Rect
12 |
13 | var onDismissListener: (() -> Unit)?
14 | var width: Int
15 | var height: Int
16 | }
17 |
18 | class StubSectionPopup : SectionPopup {
19 | override fun show(section: String, x: Int, y: Int, parentWidth: Int, parentHeight: Int, sections: Sections) {}
20 | override fun dismiss() {}
21 | override fun draw(canvas: Canvas) {}
22 | override fun getRect(): Rect = Rect(0, 0, 0, 0)
23 |
24 | override var onDismissListener: (() -> Unit)? = null
25 | override var width: Int = 0
26 | override var height: Int = 0
27 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Alexey
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/data/DataSource.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.data
2 |
3 | import android.content.res.Resources
4 | import com.appspell.wildscroll.R
5 | import com.google.gson.GsonBuilder
6 | import com.google.gson.reflect.TypeToken
7 |
8 |
9 | class DataSource(private val resources: Resources) {
10 | val companies: List
11 | get() {
12 | val json = resources.openRawResource(R.raw.mockdata).bufferedReader().use { it.readText() }
13 |
14 | val listType = object : TypeToken>() {}.type
15 | val list = GsonBuilder().create().fromJson>(json, listType)
16 | //
17 | // val alp = "QWERTYUIOOPLKJHGFDSAZXVBNM1234567890"
18 | // for(i in 0..100000) {
19 | // var name = ""
20 | // for (n in 0..20) {
21 | // name += alp[Random().nextInt(alp.length)]
22 | // }
23 | //
24 | // list.add(Company(name, name[0].toUpperCase().toString()))
25 | // }
26 | return list.sortedBy { it.company } //TODO do it in background
27 | }
28 |
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/fragments/SimpleFragment.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.fragments
2 |
3 | import android.os.Bundle
4 | import android.support.v4.app.Fragment
5 | import android.support.v7.widget.LinearLayoutManager
6 | import android.support.v7.widget.RecyclerView
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import com.appspell.wildscroll.R
11 | import com.appspell.wildscroll.R.layout
12 | import com.appspell.wildscroll.adapter.SampleAdapter
13 | import com.appspell.wildscroll.data.DataSource
14 |
15 | class SimpleFragment : Fragment() {
16 |
17 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
18 | inflater.inflate(layout.fragment_simple, container, false)
19 |
20 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
21 | val recyclerView = view.findViewById(R.id.list)
22 | with(recyclerView) {
23 | layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
24 | adapter = SampleAdapter()
25 | (adapter as SampleAdapter).items = DataSource(resources).companies
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/fragments/CustomLayoutFragment.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.fragments
2 |
3 | import android.os.Bundle
4 | import android.support.v4.app.Fragment
5 | import android.support.v7.widget.LinearLayoutManager
6 | import android.support.v7.widget.RecyclerView
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import com.appspell.wildscroll.R
11 | import com.appspell.wildscroll.R.layout
12 | import com.appspell.wildscroll.adapter.SampleAdapter
13 | import com.appspell.wildscroll.data.DataSource
14 |
15 | class CustomLayoutFragment : Fragment() {
16 |
17 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
18 | inflater.inflate(layout.fragment_custom, container, false)
19 |
20 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
21 | val recyclerView = view.findViewById(R.id.list)
22 | with(recyclerView) {
23 | layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
24 | adapter = SampleAdapter()
25 | (adapter as SampleAdapter).items = DataSource(resources).companies
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/fragments/SectionsFragment.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.fragments
2 |
3 | import android.os.Bundle
4 | import android.support.v4.app.Fragment
5 | import android.support.v7.widget.LinearLayoutManager
6 | import android.support.v7.widget.RecyclerView
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import com.appspell.wildscroll.R
11 | import com.appspell.wildscroll.R.layout
12 | import com.appspell.wildscroll.adapter.SectionsAdapter
13 | import com.appspell.wildscroll.data.DataSource
14 |
15 | class SectionsFragment : Fragment() {
16 |
17 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
18 | inflater.inflate(layout.fragment_sections, container, false)
19 |
20 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
21 | val recyclerView = view.findViewById(R.id.list)
22 | with(recyclerView) {
23 | layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
24 | adapter = SectionsAdapter()
25 | (adapter as SectionsAdapter).items = DataSource(resources).companies //TODO need to duplicate section items
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/java/com/appspell/wildscroll/coroutines/Android.kt:
--------------------------------------------------------------------------------
1 | package com.eatigo.common.coroutines
2 |
3 | import android.os.Handler
4 | import android.os.Looper
5 | import kotlin.coroutines.experimental.AbstractCoroutineContextElement
6 | import kotlin.coroutines.experimental.Continuation
7 | import kotlin.coroutines.experimental.ContinuationInterceptor
8 |
9 | object Android : AbstractCoroutineContextElement(ContinuationInterceptor), ContinuationInterceptor {
10 | override fun interceptContinuation(continuation: Continuation): Continuation = AndroidContinuation(continuation)
11 | }
12 |
13 | private class AndroidContinuation(val cont: Continuation) : Continuation by cont {
14 | override fun resume(value: T) {
15 | when (Looper.myLooper() == Looper.getMainLooper()) {
16 | true -> cont.resume(value)
17 | false -> Handler(Looper.getMainLooper()).post { cont.resume(value) }
18 | }
19 | }
20 |
21 | override fun resumeWithException(exception: Throwable) {
22 | when (Looper.myLooper() == Looper.getMainLooper()) {
23 | true -> cont.resumeWithException(exception)
24 | false -> Handler(Looper.getMainLooper()).post { cont.resumeWithException(exception) }
25 | }
26 | }
27 | }
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_sections.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
19 |
20 |
21 |
30 |
31 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/res/values/attrs_wildscroll.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/java/com/appspell/wildscroll/sections/popup/SectionCirclePopup.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.sections.popup
2 |
3 | import android.annotation.SuppressLint
4 | import android.content.Context
5 | import android.graphics.PorterDuff
6 | import android.support.annotation.ColorRes
7 | import android.support.annotation.DimenRes
8 | import android.support.v4.content.res.ResourcesCompat
9 | import appspell.com.wildscroll.R
10 |
11 |
12 | @SuppressLint("ResourceType")
13 | class SectionCirclePopup(
14 | context: Context,
15 | @ColorRes
16 | sectionTextColorRes: Int = R.color.fastscroll_highlight_text,
17 | @DimenRes
18 | sectionTextSizeDimen: Int = R.dimen.fastscroll_popup_section_text_size,
19 | @ColorRes
20 | backgroundColorRes: Int = R.color.fastscroll_popup_background,
21 | @DimenRes
22 | paddingRes: Int = R.dimen.fastscroll_popup_padding)
23 | : SectionLetterPopup(context = context,
24 | textColorRes = sectionTextColorRes,
25 | textSizeDimen = sectionTextSizeDimen,
26 | backgroundResource = R.drawable.fastscroll_popup_circle,
27 | paddingRes = paddingRes) {
28 |
29 | override var backgroundColorRes: Int = backgroundColorRes
30 | set(value) {
31 | field = value
32 | val color = ResourcesCompat.getColor(context.resources, value, context.theme)
33 | background?.mutate()?.setColorFilter(color, PorterDuff.Mode.SRC_IN)
34 | }
35 |
36 | init {
37 | this.backgroundColorRes = backgroundColorRes
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | apply plugin: 'kotlin-android'
4 |
5 | apply plugin: 'kotlin-android-extensions'
6 |
7 | android {
8 | compileSdkVersion 27
9 | buildToolsVersion "27.0.2"
10 | defaultConfig {
11 | applicationId "com.appspell.wildscroll"
12 | minSdkVersion 15
13 | targetSdkVersion 27
14 | versionCode 1
15 | versionName "1.0"
16 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
17 | vectorDrawables.useSupportLibrary = true
18 | }
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | }
26 |
27 | dependencies {
28 | implementation fileTree(include: ['*.jar'], dir: 'libs')
29 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
30 | implementation 'com.android.support:appcompat-v7:27.0.2'
31 | implementation 'com.android.support.constraint:constraint-layout:1.0.2'
32 | implementation 'com.android.support:recyclerview-v7:27.0.2'
33 | implementation 'com.android.support:cardview-v7:27.0.2'
34 | implementation 'com.google.code.gson:gson:2.8.2'
35 | testImplementation 'junit:junit:4.12'
36 | androidTestImplementation 'com.android.support.test:runner:1.0.1'
37 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
38 | implementation project(':wildscrolllibrary')
39 | implementation 'com.android.support:design:27.0.2'
40 | }
41 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_custom.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/adapter/SimpleAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.adapter
2 |
3 | import android.support.v7.widget.RecyclerView
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.TextView
8 | import com.appspell.wildscroll.R
9 | import com.appspell.wildscroll.data.Company
10 |
11 | class SampleAdapter : RecyclerView.Adapter(), SectionFastScroll {
12 | var items = emptyList()
13 | set(value) {
14 | field = value
15 | notifyDataSetChanged()
16 | }
17 |
18 | override fun getItemCount() = items.size
19 |
20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder? {
21 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_sample_list, parent, false)
22 | return ListViewHolder(view)
23 | }
24 |
25 | override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
26 | holder.bind(items[position])
27 | }
28 |
29 | override fun getSectionName(position: Int): String = items[position].company
30 | }
31 |
32 | class ListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
33 | private val company: TextView = itemView.findViewById(R.id.company)
34 | private val phrase: TextView = itemView.findViewById(R.id.phrase)
35 | private val street: TextView = itemView.findViewById(R.id.street)
36 |
37 | fun bind(item: Company) {
38 | company.text = item.company
39 | phrase.text = item.phrase
40 | street.text = item.street
41 | }
42 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/adapter/SimpleSecondAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.adapter
2 |
3 | import android.support.v7.widget.RecyclerView
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.TextView
8 | import com.appspell.wildscroll.R
9 | import com.appspell.wildscroll.data.Company
10 |
11 | class SampleSecondAdapter : RecyclerView.Adapter(), SectionFastScroll {
12 | var items = emptyList()
13 | set(value) {
14 | field = value
15 | notifyDataSetChanged()
16 | }
17 |
18 | override fun getItemCount() = items.size
19 |
20 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SecondListViewHolder? {
21 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_second_sample_list, parent, false)
22 | return SecondListViewHolder(view)
23 | }
24 |
25 | override fun onBindViewHolder(holder: SecondListViewHolder, position: Int) {
26 | holder.bind(items[position])
27 | }
28 |
29 | override fun getSectionName(position: Int): String = items[position].company
30 | }
31 |
32 | class SecondListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
33 | private val company: TextView = itemView.findViewById(R.id.company)
34 | private val phrase: TextView = itemView.findViewById(R.id.phrase)
35 | private val street: TextView = itemView.findViewById(R.id.street)
36 |
37 | fun bind(item: Company) {
38 | company.text = item.company
39 | phrase.text = item.phrase
40 | street.text = item.street
41 | }
42 | }
--------------------------------------------------------------------------------
/wildscrolllibrary/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'kotlin-android'
3 | apply plugin: 'kotlin-android-extensions'
4 | apply plugin: 'bintray-release'
5 |
6 | buildscript {
7 | repositories {
8 | jcenter()
9 | }
10 | dependencies {
11 | classpath 'com.novoda:bintray-release:0.8.0'
12 | }
13 | }
14 |
15 | android {
16 | compileSdkVersion 27
17 | buildToolsVersion "27.0.2"
18 | defaultConfig {
19 | minSdkVersion 15
20 | targetSdkVersion 27
21 | versionCode 1
22 | versionName "0.90"
23 | }
24 |
25 | buildTypes {
26 | release {
27 | minifyEnabled false
28 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
29 | }
30 | }
31 | }
32 |
33 | kotlin {
34 | experimental {
35 | coroutines "enable"
36 | }
37 | }
38 |
39 | dependencies {
40 | implementation 'com.android.support:appcompat-v7:27.0.2'
41 | implementation "com.android.support:recyclerview-v7:27.0.2"
42 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
43 |
44 | //coroutines
45 | implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:0.19.2"
46 | }
47 | repositories {
48 | mavenCentral()
49 | jcenter()
50 | }
51 |
52 | publish {
53 | userOrg = 'appspell'
54 | groupId = 'com.appspell.wild-scroll'
55 | artifactId = 'wild-scroll'
56 | publishVersion = android.defaultConfig.versionName
57 | desc = 'Android RecyclerView Fast Scroller'
58 | website = 'https://github.com/appspell/Wild-Scroll'
59 | }
60 |
61 | tasks.withType(Javadoc).all {
62 | enabled = false
63 | }
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_sections_section.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
27 |
28 |
42 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll
2 |
3 | import android.content.Context
4 | import android.os.Bundle
5 | import android.support.design.widget.TabLayout
6 | import android.support.v4.app.Fragment
7 | import android.support.v4.app.FragmentManager
8 | import android.support.v4.app.FragmentStatePagerAdapter
9 | import android.support.v4.view.ViewPager
10 | import android.support.v7.app.AppCompatActivity
11 | import com.appspell.wildscroll.fragments.CustomLayoutFragment
12 | import com.appspell.wildscroll.fragments.CustomProgrammaticallyFragment
13 | import com.appspell.wildscroll.fragments.SimpleFragment
14 |
15 | class SampleActivity : AppCompatActivity() {
16 |
17 | override fun onCreate(savedInstanceState: Bundle?) {
18 | super.onCreate(savedInstanceState)
19 | setContentView(R.layout.activity_main)
20 |
21 | val viewPager = findViewById(R.id.pager)
22 | viewPager.adapter = PagerAdapter(supportFragmentManager, this)
23 |
24 | val tabLayout = findViewById(R.id.tabLayout)
25 | tabLayout.setupWithViewPager(viewPager)
26 | }
27 | }
28 |
29 | internal class PagerAdapter(fm: FragmentManager, private val context: Context) : FragmentStatePagerAdapter(fm) {
30 |
31 | override fun getItem(position: Int): Fragment? =
32 | when (position) {
33 | 0 -> SimpleFragment()
34 | 1 -> CustomLayoutFragment()
35 | 2 -> CustomProgrammaticallyFragment()
36 | // 3 -> SectionsFragment()
37 | else -> null
38 | }
39 |
40 | override fun getPageTitle(position: Int): CharSequence? =
41 | when (position) {
42 | 0 -> context.getString(R.string.tab_simple)
43 | 1 -> context.getString(R.string.tab_custom_layout)
44 | 2 -> context.getString(R.string.tab_custom_programmatically)
45 | // 3 -> context.getString(R.string.tab_sections)
46 | else -> null
47 | }
48 |
49 | override fun getCount(): Int {
50 | return 3
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/fragments/CustomProgrammaticallyFragment.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.fragments
2 |
3 | import android.graphics.Typeface
4 | import android.os.Bundle
5 | import android.support.v4.app.Fragment
6 | import android.support.v7.widget.LinearLayoutManager
7 | import android.view.LayoutInflater
8 | import android.view.View
9 | import android.view.ViewGroup
10 | import com.appspell.wildscroll.R
11 | import com.appspell.wildscroll.R.layout
12 | import com.appspell.wildscroll.adapter.SampleSecondAdapter
13 | import com.appspell.wildscroll.data.DataSource
14 | import com.appspell.wildscroll.sections.Gravity.LEFT
15 | import com.appspell.wildscroll.sections.popup.SectionLetterPopup
16 | import com.appspell.wildscroll.view.WildScrollRecyclerView
17 |
18 | class CustomProgrammaticallyFragment : Fragment() {
19 |
20 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? =
21 | inflater.inflate(layout.fragment_custom_programmatically, container, false)
22 |
23 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
24 | val recyclerView = view.findViewById(R.id.list)
25 | with(recyclerView) {
26 | layoutManager = LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
27 | adapter = SampleSecondAdapter()
28 | (adapter as SampleSecondAdapter).items = DataSource(resources).companies
29 |
30 | textColor = R.color.colorSecondaryDark
31 | textSize = R.dimen.textRegular
32 | textTypeFace = Typeface.SANS_SERIF
33 |
34 | highlightColor = R.color.colorSecondary
35 | highlightTextSize = R.dimen.fastscroll_section_highlight_text_size
36 | highlightTextFace = Typeface.DEFAULT_BOLD
37 |
38 | sectionBarPaddingLeft = R.dimen.padding
39 | sectionBarPaddingRight = R.dimen.padding
40 | sectionBarCollapseDigital = false
41 | sectionBarGravity = LEFT
42 |
43 | sectionPopup = SectionLetterPopup(context,
44 | textColorRes = R.color.colorSecondaryLight,
45 | textSizeDimen = R.dimen.textPopup,
46 | textTypeFace = Typeface.DEFAULT_BOLD,
47 | backgroundResource = R.drawable.background_popup,
48 | paddingRes = R.dimen.padding)
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_sample_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
28 |
29 |
45 |
46 |
58 |
59 |
72 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_sections_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
34 |
35 |
51 |
52 |
64 |
65 |
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/appspell/wildscroll/adapter/SectionsAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.adapter
2 |
3 | import android.support.v7.widget.RecyclerView
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import android.widget.TextView
8 | import com.appspell.wildscroll.R
9 | import com.appspell.wildscroll.data.Company
10 | import com.appspell.wildscroll.sections.SectionInfo
11 |
12 | class SectionsAdapter : SectionFastScrollAdapter(), SectionFastScroll {
13 | companion object {
14 |
15 | const val SECTION = 10
16 | const val ITEM = 20
17 | }
18 |
19 | var items = emptyList()
20 | set(value) {
21 | field = value
22 | notifyDataSetChanged()
23 | }
24 |
25 | override fun getItemCount(): Int = items.count()
26 |
27 | override fun getItemViewType(position: Int): Int =
28 | if (isSection(position)) {
29 | SECTION
30 | } else {
31 | ITEM
32 | }
33 |
34 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder? =
35 | when (viewType) {
36 | SECTION -> {
37 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_sections_section, parent, false)
38 | SectionsSectionViewHolder(view)
39 | }
40 | ITEM -> {
41 | val view = LayoutInflater.from(parent.context).inflate(R.layout.item_sections_item, parent, false)
42 | SectionsItemViewHolder(view)
43 | }
44 | else -> null
45 | }
46 |
47 | override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
48 | when (getItemViewType(position)) {
49 | SECTION -> {
50 | holder as SectionsSectionViewHolder
51 | holder.bind(getSectionInfo(position)!!)
52 | }
53 | ITEM -> {
54 | holder as SectionsItemViewHolder
55 | holder.bind(items[position])
56 | }
57 | else -> throw Exception("Cannot find binding for ${getItemViewType(position)}")
58 | }
59 |
60 | }
61 |
62 | override fun getSectionName(position: Int): String = items[position].company
63 | }
64 |
65 |
66 | class SectionsSectionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
67 | private val section = itemView.findViewById(R.id.section)
68 |
69 | fun bind(sectionInfo: SectionInfo) {
70 | section.text = sectionInfo.shortName.toString()
71 | }
72 | }
73 |
74 | class SectionsItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
75 | private val section = itemView.findViewById(R.id.section)
76 |
77 | private val company = itemView.findViewById(R.id.company)
78 | private val phrase = itemView.findViewById(R.id.phrase)
79 | private val street = itemView.findViewById(R.id.street)
80 |
81 | fun bind(item: Company) {
82 | section.text = item.company
83 | company.text = item.company
84 | phrase.text = item.phrase
85 | street.text = item.street
86 | }
87 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_second_sample_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
17 |
18 |
25 |
26 |
30 |
31 |
42 |
43 |
61 |
62 |
75 |
76 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/wildscrolllibrary/src/main/java/com/appspell/wildscroll/sections/Sections.kt:
--------------------------------------------------------------------------------
1 | package com.appspell.wildscroll.sections
2 |
3 | import android.support.v4.util.ArrayMap
4 | import android.support.v7.widget.RecyclerView
5 | import android.text.TextUtils
6 | import com.appspell.wildscroll.adapter.SectionFastScroll
7 | import com.appspell.wildscroll.adapter.SectionFastScrollAdapter
8 | import com.eatigo.common.coroutines.Android
9 | import kotlinx.coroutines.experimental.CommonPool
10 | import kotlinx.coroutines.experimental.Deferred
11 | import kotlinx.coroutines.experimental.Job
12 | import kotlinx.coroutines.experimental.async
13 | import kotlinx.coroutines.experimental.launch
14 | import java.util.TreeMap
15 |
16 | interface OnSectionChangedListener {
17 | fun onSectionChanged()
18 | }
19 |
20 | enum class Gravity {
21 | LEFT, RIGHT //TODO top and bottom
22 | }
23 |
24 | data class SectionInfo(val name: String,
25 | val shortName: Char,
26 | val position: Int,
27 | val count: Int)
28 |
29 | class Sections {
30 | companion object {
31 | const val UNSELECTED = -1
32 |
33 | private const val SECTION_SHORT_NAME_EMPTY = '-'
34 | private const val SECTION_SHORT_NAME_DIGITAL = '#'
35 | }
36 |
37 | var left = 0f
38 | var top = 0f
39 | var width = 0f
40 | var height = 0f
41 |
42 | var gravity = Gravity.RIGHT
43 | var collapseDigital = true
44 |
45 | var paddingLeft = 0f
46 | var paddingRight = 0f
47 |
48 | var sections: ArrayMap = ArrayMap()
49 |
50 | var selected = UNSELECTED //TODO redraw section bar after set new value
51 |
52 | private var job: Job? = null
53 |
54 | fun getCount() = sections.size
55 |
56 | fun changeSize(w: Int, h: Int, highlightTextSize: Float) {
57 | val sectionCount = sections.size
58 |
59 | when (gravity) {
60 | Gravity.LEFT -> {
61 | width = highlightTextSize + paddingLeft + paddingRight
62 | height = h / sectionCount.toFloat()
63 | left = 0f
64 | }
65 | Gravity.RIGHT -> {
66 | width = highlightTextSize + paddingLeft + paddingRight
67 | height = h / sectionCount.toFloat()
68 | left = w - width
69 | }
70 | //TODO top / bottom
71 | }
72 | }
73 |
74 | fun contains(x: Float, y: Float): Boolean {
75 | return x >= left &&
76 | x <= left + width &&
77 | y >= top &&
78 | y <= height * sections.size
79 | }
80 |
81 | fun getSectionInfoByIndex(index: Int): SectionInfo? {
82 | val key = getSectionByIndex(index)
83 | return sections[key]
84 | }
85 |
86 | fun createShortName(name: String): Char =
87 | when {
88 | name.isEmpty() -> SECTION_SHORT_NAME_EMPTY
89 | collapseDigital && TextUtils.isDigitsOnly(name[0].toString()) -> SECTION_SHORT_NAME_DIGITAL
90 | else -> name[0].toUpperCase()
91 | }
92 |
93 | fun refresh(adapter: RecyclerView.Adapter<*>?, listener: OnSectionChangedListener) { //TODO move it to separate class
94 | job?.cancel()
95 | job = launch(Android) {
96 | sections = fetchSections(adapter).await()
97 | // prepareSectionsAdapter(adapter)
98 | listener.onSectionChanged()
99 | }
100 | }
101 |
102 | private suspend fun prepareSectionsAdapter(adapter: RecyclerView.Adapter<*>?) {
103 | if (adapter !is SectionFastScrollAdapter<*>) return
104 | adapter.sections = prepareSectionInformationForAdapter().await()
105 | }
106 |
107 | private fun prepareSectionInformationForAdapter(): Deferred