diff --git a/README.md b/README.md
index 5557888..3ce756b 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,14 @@
-### Jetpack Compose Colorful Customizable Sliders
+# Jetpack Compose Colorful Customizable Sliders
Colorful sliders that can have Solid or Gradient colors for thumb or track which can have thumb and
track with varying sizes, borders with solid or gradient colors. And Sliders with emojis, or custom
Composables like **Icon**.
-|Properties | Dimensions | Slider with Icon | Slider with Label | Gradient |
+| Slider with Icon | Gradient | Properties | Slider with Label | Dimensions |
| ----------|-----------| -----------| -----------| -----------|
-| | | | | |
+| | | | | |
-### ColorfulSlider
+## ColorfulSlider
Sliders that can use Color or gradient for track, thumb, or tick colors with custom thumb and track
heights.
@@ -122,7 +122,7 @@ data class SliderBrushColor(
}
```
-### SliderWithLabel
+## SliderWithLabel
Sliders that can move a label above the Slider and display progress
@@ -173,7 +173,7 @@ SliderWithLabel(
)
```
-### ColorfulIconSlider
+## ColorfulIconSlider
Sliders that can use any Composable for thumb and use Color or gradient for track, thumb, or tick
colors with custom thumb and track heights.
diff --git a/app/build.gradle b/app/build.gradle
index 85e4dd8..2745ea9 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -50,15 +50,19 @@ dependencies {
implementation project(':slider')
implementation 'androidx.core:core-ktx:1.7.0'
+ implementation 'androidx.appcompat:appcompat:1.4.1'
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
+
implementation "androidx.compose.ui:ui:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
- implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
implementation 'androidx.activity:activity-compose:1.4.0'
- implementation 'com.google.accompanist:accompanist-systemuicontroller:0.24.3-alpha'
- implementation "com.google.accompanist:accompanist-pager:0.24.3-alpha"
- implementation "com.google.accompanist:accompanist-pager-indicators:0.24.3-alpha"
+ def accompanist_version = "0.24.6-alpha"
+ // Accompanist
+ implementation "com.google.accompanist:accompanist-systemuicontroller:$accompanist_version"
+ implementation "com.google.accompanist:accompanist-pager:$accompanist_version"
+ implementation "com.google.accompanist:accompanist-drawablepainter:$accompanist_version"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
diff --git a/app/src/main/java/com/smarttoolfactory/composematerialslider/MainActivity.kt b/app/src/main/java/com/smarttoolfactory/composematerialslider/MainActivity.kt
index 4da131e..8b15302 100644
--- a/app/src/main/java/com/smarttoolfactory/composematerialslider/MainActivity.kt
+++ b/app/src/main/java/com/smarttoolfactory/composematerialslider/MainActivity.kt
@@ -4,7 +4,6 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.ExperimentalAnimationApi
-import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.Composable
@@ -12,10 +11,8 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
import com.google.accompanist.pager.*
import com.smarttoolfactory.composematerialslider.demo.*
-import com.smarttoolfactory.composematerialslider.ui.theme.BlueSmart
import com.smarttoolfactory.composematerialslider.ui.theme.BlueSmartDark
import com.smarttoolfactory.composematerialslider.ui.theme.ComposeMaterialSliderTheme
import kotlinx.coroutines.launch
@@ -54,11 +51,7 @@ private fun HomeContent() {
// Our selected tab is our current page
selectedTabIndex = pagerState.currentPage,
// Override the indicator, using the provided pagerTabIndicatorOffset modifier
- indicator = { tabPositions ->
- TabRowDefaults.Indicator(
- Modifier.pagerTabIndicatorOffset(pagerState, tabPositions)
- )
- }
+ indicator = {}
) {
// Add tabs for all of our pages
tabList.forEachIndexed { index, title ->
diff --git a/build.gradle b/build.gradle
index bfbdce8..8d3938d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,11 +1,11 @@
buildscript {
ext {
- compose_version = '1.2.0-alpha06'
+ compose_version = '1.2.0-alpha07'
}
}// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
- id 'com.android.application' version '7.1.2' apply false
- id 'com.android.library' version '7.1.2' apply false
+ id 'com.android.application' version '7.1.3' apply false
+ id 'com.android.library' version '7.1.3' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
}
diff --git a/settings.gradle b/settings.gradle
index 8705b9c..20059d5 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -10,6 +10,7 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
+ maven { url 'https://jitpack.io'}
}
}
rootProject.name = "Compose Material Slider"
diff --git a/slider/build.gradle b/slider/build.gradle
index 877bb7b..8c47357 100644
--- a/slider/build.gradle
+++ b/slider/build.gradle
@@ -44,19 +44,15 @@ android {
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
- implementation 'androidx.appcompat:appcompat:1.4.1'
- implementation 'com.google.android.material:material:1.5.0'
+
+ implementation 'com.github.SmartToolFactory:Compose-Extended-Gestures:1.0.0'
// Jetpack Compose
implementation "androidx.compose.ui:ui:$compose_version"
- implementation "androidx.compose.ui:ui-tooling:$compose_version"
implementation "androidx.compose.material:material:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version"
implementation "androidx.compose.runtime:runtime:$compose_version"
- implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
- implementation 'androidx.activity:activity-compose:1.4.0'
-
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
diff --git a/slider/src/main/java/com/smarttoolfactory/slider/ColorfulIconSlider.kt b/slider/src/main/java/com/smarttoolfactory/slider/ColorfulIconSlider.kt
index 8e5566c..250d279 100644
--- a/slider/src/main/java/com/smarttoolfactory/slider/ColorfulIconSlider.kt
+++ b/slider/src/main/java/com/smarttoolfactory/slider/ColorfulIconSlider.kt
@@ -24,7 +24,7 @@ import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.*
-import com.smarttoolfactory.slider.gesture.pointerMotionEvents
+import com.smarttoolfactory.gesture.pointerMotionEvents
/**
* Material Slider allows to choose height for track and thumb radius and selection between
diff --git a/slider/src/main/java/com/smarttoolfactory/slider/ColorfulSlider.kt b/slider/src/main/java/com/smarttoolfactory/slider/ColorfulSlider.kt
index cc49dc1..f8f2edf 100644
--- a/slider/src/main/java/com/smarttoolfactory/slider/ColorfulSlider.kt
+++ b/slider/src/main/java/com/smarttoolfactory/slider/ColorfulSlider.kt
@@ -23,7 +23,7 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
-import com.smarttoolfactory.slider.gesture.pointerMotionEvents
+import com.smarttoolfactory.gesture.pointerMotionEvents
import kotlin.math.abs
/**
diff --git a/slider/src/main/java/com/smarttoolfactory/slider/gesture/AwaitPointerMotionEvent.kt b/slider/src/main/java/com/smarttoolfactory/slider/gesture/AwaitPointerMotionEvent.kt
deleted file mode 100644
index 63059f7..0000000
--- a/slider/src/main/java/com/smarttoolfactory/slider/gesture/AwaitPointerMotionEvent.kt
+++ /dev/null
@@ -1,165 +0,0 @@
-package com.smarttoolfactory.slider.gesture
-
-import androidx.compose.foundation.gestures.*
-import androidx.compose.ui.input.pointer.*
-import kotlinx.coroutines.coroutineScope
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.launch
-
-/**
- * Reads [awaitFirstDown], and [awaitPointerEvent] to
- * get [PointerInputChange] and motion event states
- * [onDown], [onMove], and [onUp].
- *
- * To prevent other pointer functions that call [awaitFirstDown] or [awaitPointerEvent]
- * (scroll, swipe, detect functions)
- * receiving changes call [PointerInputChange.consumeDownChange] in [onDown],
- * and call [PointerInputChange.consumePositionChange]
- * in [onMove] block.
- *
- * @param onDown is invoked when first pointer is down initially.
- * @param onMove one or multiple pointers are being moved on screen.
- * @param onUp last pointer is up
- * @param delayAfterDownInMillis is optional delay after [onDown] This delay might be
- * required Composables like **Canvas** to process [onDown] before [onMove]
- *
-
- */
-suspend fun PointerInputScope.detectMotionEvents(
- onDown: (PointerInputChange) -> Unit = {},
- onMove: (PointerInputChange) -> Unit = {},
- onUp: (PointerInputChange) -> Unit = {},
- delayAfterDownInMillis: Long = 0L
-) {
- coroutineScope {
- forEachGesture {
- awaitPointerEventScope {
- // Wait for at least one pointer to press down, and set first contact position
- val down: PointerInputChange = awaitFirstDown()
- onDown(down)
-
- var pointer = down
- // Main pointer is the one that is down initially
- var pointerId = down.id
-
- // If a move event is followed fast enough down is skipped, especially by Canvas
- // to prevent it we add delay after first touch
- var waitedAfterDown = false
-
- launch {
- delay(delayAfterDownInMillis)
- waitedAfterDown = true
- }
-
- while (true) {
-
- val event: PointerEvent = awaitPointerEvent()
-
- val anyPressed = event.changes.any { it.pressed }
-
- // There are at least one pointer pressed
- if (anyPressed) {
- // Get pointer that is down, if first pointer is up
- // get another and use it if other pointers are also down
- // event.changes.first() doesn't return same order
- val pointerInputChange =
- event.changes.firstOrNull { it.id == pointerId }
- ?: event.changes.first()
-
- // Next time will check same pointer with this id
- pointerId = pointerInputChange.id
- pointer = pointerInputChange
-
- if (waitedAfterDown) {
- onMove(pointer)
- }
- } else {
- // All of the pointers are up
- onUp(pointer)
- break
- }
- }
- }
- }
- }
-}
-
-/**
- * Reads [awaitFirstDown], and [awaitPointerEvent] to
- * get [PointerInputChange] and motion event states
- * [onDown], [onMove], and [onUp]. Unlike overload of this function [onMove] returns
- * list of [PointerInputChange] to get data about all pointers that are on the screen.
- *
- * To prevent other pointer functions that call [awaitFirstDown] or [awaitPointerEvent]
- * (scroll, swipe, detect functions)
- * receiving changes call [PointerInputChange.consumeDownChange] in [onDown],
- * and call [PointerInputChange.consumePositionChange]
- * in [onMove] block.
- *
- * @param onDown is invoked when first pointer is down initially.
- * @param onMove one or multiple pointers are being moved on screen.
- * @param onUp last pointer is up
- * @param delayAfterDownInMillis is optional delay after [onDown] This delay might be
- * required Composables like **Canvas** to process [onDown] before [onMove]
- *
- */
-suspend fun PointerInputScope.detectMotionEventsAsList(
- onDown: (PointerInputChange) -> Unit = {},
- onMove: (List) -> Unit = {},
- onUp: (PointerInputChange) -> Unit = {},
- delayAfterDownInMillis: Long = 0L
-) {
-
- coroutineScope {
- forEachGesture {
- awaitPointerEventScope {
- // Wait for at least one pointer to press down, and set first contact position
- val down: PointerInputChange = awaitFirstDown()
- onDown(down)
-
- var pointer = down
- // Main pointer is the one that is down initially
- var pointerId = down.id
-
- // If a move event is followed fast enough down is skipped, especially by Canvas
- // to prevent it we add delay after first touch
- var waitedAfterDown = false
-
- launch {
- delay(delayAfterDownInMillis)
- waitedAfterDown = true
- }
-
- while (true) {
-
- val event: PointerEvent = awaitPointerEvent()
-
- val anyPressed = event.changes.any { it.pressed }
-
- // There are at least one pointer pressed
- if (anyPressed) {
- // Get pointer that is down, if first pointer is up
- // get another and use it if other pointers are also down
- // event.changes.first() doesn't return same order
- val pointerInputChange =
- event.changes.firstOrNull { it.id == pointerId }
- ?: event.changes.first()
-
- // Next time will check same pointer with this id
- pointerId = pointerInputChange.id
- pointer = pointerInputChange
-
- if (waitedAfterDown) {
- onMove(event.changes)
- }
-
- } else {
- // All of the pointers are up
- onUp(pointer)
- break
- }
- }
- }
- }
- }
-}
diff --git a/slider/src/main/java/com/smarttoolfactory/slider/gesture/MotionEvent.kt b/slider/src/main/java/com/smarttoolfactory/slider/gesture/MotionEvent.kt
deleted file mode 100644
index 31902bd..0000000
--- a/slider/src/main/java/com/smarttoolfactory/slider/gesture/MotionEvent.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.smarttoolfactory.slider.gesture
-
-enum class MotionEvent {
- Idle, Down, Move, Up
-}
diff --git a/slider/src/main/java/com/smarttoolfactory/slider/gesture/PointerMotionModifier.kt b/slider/src/main/java/com/smarttoolfactory/slider/gesture/PointerMotionModifier.kt
deleted file mode 100644
index 721922d..0000000
--- a/slider/src/main/java/com/smarttoolfactory/slider/gesture/PointerMotionModifier.kt
+++ /dev/null
@@ -1,216 +0,0 @@
-package com.smarttoolfactory.slider.gesture
-
-import androidx.compose.foundation.gestures.awaitFirstDown
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.input.pointer.*
-
-/**
- * Create a modifier for processing pointer motion input within the region of the modified element.
- *
- * After [AwaitPointerEventScope.awaitFirstDown] returned a [PointerInputChange] then
- * [onDown] is called at first pointer contact.
- * Moving any pointer causes [AwaitPointerEventScope.awaitPointerEvent] then [onMove] is called.
- * When last pointer is up [onUp] is called.
- *
- * To prevent other pointer functions that call [awaitFirstDown] or [awaitPointerEvent]
- * (scroll, swipe, detect functions)
- * receiving changes call [PointerInputChange.consumeDownChange] in [onDown],
- * and call [PointerInputChange.consumePositionChange]
- * in [onMove] block.
- *
- * @param onDown is invoked when first pointer is down initially.
- * @param onMove is invoked when one or multiple pointers are being moved on screen.
- * @param onUp is invoked when last pointer is up
- * @param delayAfterDownInMillis is optional delay after [onDown] This delay might be
- * required Composables like **Canvas** to process [onDown] before [onMove]
- *
- * The pointer input handling block will be cancelled and re-started when pointerInput
- * is recomposed with a different [key1].
- */
-fun Modifier.pointerMotionEvents(
- key1: Any? = Unit,
- onDown: (PointerInputChange) -> Unit = {},
- onMove: (PointerInputChange) -> Unit = {},
- onUp: (PointerInputChange) -> Unit = {},
- delayAfterDownInMillis: Long = 0L
-) = this.then(
- Modifier.pointerInput(key1) {
- detectMotionEvents(onDown, onMove, onUp, delayAfterDownInMillis)
- }
-)
-/**
- * Create a modifier for processing pointer motion input within the region of the modified element.
- *
- * After [AwaitPointerEventScope.awaitFirstDown] returned a [PointerInputChange] then
- * [onDown] is called at first pointer contact.
- * Moving any pointer causes [AwaitPointerEventScope.awaitPointerEvent] then [onMove] is called.
- * When last pointer is up [onUp] is called.
- *
- * To prevent other pointer functions that call [awaitFirstDown] or [awaitPointerEvent]
- * (scroll, swipe, detect functions)
- * receiving changes call [PointerInputChange.consumeDownChange] in [onDown],
- * and call [PointerInputChange.consumePositionChange]
- * in [onMove] block.
- *
- * @param onDown is invoked when first pointer is down initially.
- * @param onMove is invoked when one or multiple pointers are being moved on screen.
- * @param onUp is invoked when last pointer is up
- * @param delayAfterDownInMillis is optional delay after [onDown] This delay might be
- * required Composables like **Canvas** to process [onDown] before [onMove]
- *
- * The pointer input handling block will be cancelled and re-started when pointerInput
- * is recomposed with a different [key1] or [key2].
- */
-fun Modifier.pointerMotionEvents(
- key1: Any?,
- key2: Any?,
- onDown: (PointerInputChange) -> Unit = {},
- onMove: (PointerInputChange) -> Unit = {},
- onUp: (PointerInputChange) -> Unit = {},
- delayAfterDownInMillis: Long = 0L
-) = this.then(
- Modifier.pointerInput(key1, key2) {
- pointerMotionEvents(onDown, onMove, onUp, delayAfterDownInMillis)
- }
-)
-
-/**
- * Create a modifier for processing pointer motion input within the region of the modified element.
- *
- * After [AwaitPointerEventScope.awaitFirstDown] returned a [PointerInputChange] then
- * [onDown] is called at first pointer contact.
- * Moving any pointer causes [AwaitPointerEventScope.awaitPointerEvent] then [onMove] is called.
- * When last pointer is up [onUp] is called.
- *
- * To prevent other pointer functions that call [awaitFirstDown] or [awaitPointerEvent]
- * (scroll, swipe, detect functions)
- * receiving changes call [PointerInputChange.consumeDownChange] in [onDown],
- * and call [PointerInputChange.consumePositionChange]
- * in [onMove] block.
- *
- * @param onDown is invoked when first pointer is down initially.
- * @param onMove is invoked when one or multiple pointers are being moved on screen.
- * @param onUp is invoked when last pointer is up
- * @param delayAfterDownInMillis is optional delay after [onDown] This delay might be
- * required Composables like **Canvas** to process [onDown] before [onMove]
- *
- * The pointer input handling block will be cancelled and re-started when pointerInput
- * is recomposed with any different [keys].
- */
-fun Modifier.pointerMotionEvents(
- vararg keys: Any?,
- onDown: (PointerInputChange) -> Unit = {},
- onMove: (PointerInputChange) -> Unit = {},
- onUp: (PointerInputChange) -> Unit = {},
- delayAfterDownInMillis: Long = 0L
-) = this.then(
- Modifier.pointerInput(keys) {
- detectMotionEvents(onDown, onMove, onUp, delayAfterDownInMillis)
- }
-)
-
-/**
- * Create a modifier for processing pointer motion input within the region of the modified element.
- *
- * After [AwaitPointerEventScope.awaitFirstDown] returned a [PointerInputChange] then
- * [onDown] is called at first pointer contact.
- * Moving any pointer causes [AwaitPointerEventScope.awaitPointerEvent] then [onMove] is called.
- * When last pointer is up [onUp] is called.
- *
- * To prevent other pointer functions that call [awaitFirstDown] or [awaitPointerEvent]
- * (scroll, swipe, detect functions)
- * receiving changes call [PointerInputChange.consumeDownChange] in [onDown],
- * and call [PointerInputChange.consumePositionChange]
- * in [onMove] block.
- *
- * @param onDown is invoked when first pointer is down initially.
- * @param onMove is invoked when one or multiple pointers are being moved on screen.
- * @param onUp is invoked when last pointer is up
- * @param delayAfterDownInMillis is optional delay after [onDown] This delay might be
- * required Composables like **Canvas** to process [onDown] before [onMove]
- *
- * The pointer input handling block will be cancelled and re-started when pointerInput
- * is recomposed with a different [key1].
- */
-fun Modifier.pointerMotionEventList(
- key1: Any? = Unit,
- onDown: (PointerInputChange) -> Unit = {},
- onMove: (List) -> Unit = {},
- onUp: (PointerInputChange) -> Unit = {},
- delayAfterDownInMillis: Long = 0L
-) = this.then(
- Modifier.pointerInput(key1) {
- detectMotionEventsAsList(onDown, onMove, onUp, delayAfterDownInMillis)
- }
-)
-
-/**
- * Create a modifier for processing pointer motion input within the region of the modified element.
- *
- * After [AwaitPointerEventScope.awaitFirstDown] returned a [PointerInputChange] then
- * [onDown] is called at first pointer contact.
- * Moving any pointer causes [AwaitPointerEventScope.awaitPointerEvent] then [onMove] is called.
- * When last pointer is up [onUp] is called.
- *
- * To prevent other pointer functions that call [awaitFirstDown] or [awaitPointerEvent]
- * (scroll, swipe, detect functions)
- * receiving changes call [PointerInputChange.consumeDownChange] in [onDown],
- * and call [PointerInputChange.consumePositionChange]
- * in [onMove] block.
- *
- * @param onDown is invoked when first pointer is down initially.
- * @param onMove is invoked when one or multiple pointers are being moved on screen.
- * @param onUp is invoked when last pointer is up
- * @param delayAfterDownInMillis is optional delay after [onDown] This delay might be
- * required Composables like **Canvas** to process [onDown] before [onMove]
- *
- * The pointer input handling block will be cancelled and re-started when pointerInput
- * is recomposed with a different [key1] or [key2].
- */
-fun Modifier.pointerMotionEventList(
- key1: Any? = Unit,
- key2: Any? = Unit,
- onDown: (PointerInputChange) -> Unit = {},
- onMove: (List) -> Unit = {},
- onUp: (PointerInputChange) -> Unit = {},
- delayAfterDownInMillis: Long = 0L
-) = this.then(
- Modifier.pointerInput(key1, key2) {
- detectMotionEventsAsList(onDown, onMove, onUp, delayAfterDownInMillis)
- }
-)
-
-/**
- * Create a modifier for processing pointer motion input within the region of the modified element.
- *
- * After [AwaitPointerEventScope.awaitFirstDown] returned a [PointerInputChange] then
- * [onDown] is called at first pointer contact.
- * Moving any pointer causes [AwaitPointerEventScope.awaitPointerEvent] then [onMove] is called.
- * When last pointer is up [onUp] is called.
- *
- * To prevent other pointer functions that call [awaitFirstDown] or [awaitPointerEvent]
- * (scroll, swipe, detect functions)
- * receiving changes call [PointerInputChange.consumeDownChange] in [onDown],
- * and call [PointerInputChange.consumePositionChange]
- * in [onMove] block.
- *
- * @param onDown is invoked when first pointer is down initially.
- * @param onMove is invoked when one or multiple pointers are being moved on screen.
- * @param onUp is invoked when last pointer is up
- * @param delayAfterDownInMillis is optional delay after [onDown] This delay might be
- * required Composables like **Canvas** to process [onDown] before [onMove]
- *
- * The pointer input handling block will be cancelled and re-started when pointerInput
- * is recomposed with any different [keys].
- */
-fun Modifier.pointerMotionEventList(
- vararg keys: Any?,
- onDown: (PointerInputChange) -> Unit = {},
- onMove: (List) -> Unit = {},
- onUp: (PointerInputChange) -> Unit = {},
- delayAfterDownInMillis: Long = 0L
-) = this.then(
- Modifier.pointerInput(keys) {
- detectMotionEventsAsList(onDown, onMove, onUp, delayAfterDownInMillis)
- }
-)