Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
test-cross
提交
4b7a7868
T
test-cross
项目概览
DCloud
/
test-cross
通知
41
Star
1
Fork
1
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
test-cross
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
4b7a7868
编写于
12月 21, 2023
作者:
H
hdx
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
add test_compose_ui_slider_100
上级
3a36e41d
变更
44
显示空白变更内容
内联
并排
Showing
44 changed file
with
2289 addition
and
0 deletion
+2289
-0
test_compose_ui_slider_100/.gitignore
test_compose_ui_slider_100/.gitignore
+10
-0
test_compose_ui_slider_100/app/.gitignore
test_compose_ui_slider_100/app/.gitignore
+2
-0
test_compose_ui_slider_100/app/build.gradle
test_compose_ui_slider_100/app/build.gradle
+66
-0
test_compose_ui_slider_100/app/proguard-rules.pro
test_compose_ui_slider_100/app/proguard-rules.pro
+21
-0
test_compose_ui_slider_100/app/src/androidTest/java/com/example/jetpackcompose/ExampleInstrumentedTest.kt
...ava/com/example/jetpackcompose/ExampleInstrumentedTest.kt
+24
-0
test_compose_ui_slider_100/app/src/main/AndroidManifest.xml
test_compose_ui_slider_100/app/src/main/AndroidManifest.xml
+32
-0
test_compose_ui_slider_100/app/src/main/java/androidx/compose/material1/DragGestureDetectorCopy.kt
...ava/androidx/compose/material1/DragGestureDetectorCopy.kt
+114
-0
test_compose_ui_slider_100/app/src/main/java/androidx/compose/material1/Slider.kt
...00/app/src/main/java/androidx/compose/material1/Slider.kt
+1195
-0
test_compose_ui_slider_100/app/src/main/java/androidx/compose/material1/Strings.android.kt
...c/main/java/androidx/compose/material1/Strings.android.kt
+38
-0
test_compose_ui_slider_100/app/src/main/java/androidx/compose/material1/Strings.kt
...0/app/src/main/java/androidx/compose/material1/Strings.kt
+33
-0
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/MainActivity.kt
.../src/main/java/com/example/jetpackcompose/MainActivity.kt
+51
-0
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/ui/theme/Color.kt
...rc/main/java/com/example/jetpackcompose/ui/theme/Color.kt
+8
-0
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/ui/theme/Shape.kt
...rc/main/java/com/example/jetpackcompose/ui/theme/Shape.kt
+11
-0
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/ui/theme/Theme.kt
...rc/main/java/com/example/jetpackcompose/ui/theme/Theme.kt
+47
-0
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/ui/theme/Type.kt
...src/main/java/com/example/jetpackcompose/ui/theme/Type.kt
+28
-0
test_compose_ui_slider_100/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
.../app/src/main/res/drawable-v24/ic_launcher_foreground.xml
+30
-0
test_compose_ui_slider_100/app/src/main/res/drawable/ic_launcher_background.xml
..._100/app/src/main/res/drawable/ic_launcher_background.xml
+170
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
...er_100/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+5
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
.../app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+5
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-hdpi/ic_launcher.webp
..._slider_100/app/src/main/res/mipmap-hdpi/ic_launcher.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
...r_100/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-mdpi/ic_launcher.webp
..._slider_100/app/src/main/res/mipmap-mdpi/ic_launcher.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
...r_100/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
...slider_100/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
..._100/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
...lider_100/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
...100/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
...ider_100/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
...00/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
+0
-0
test_compose_ui_slider_100/app/src/main/res/values/colors.xml
..._compose_ui_slider_100/app/src/main/res/values/colors.xml
+10
-0
test_compose_ui_slider_100/app/src/main/res/values/strings.xml
...compose_ui_slider_100/app/src/main/res/values/strings.xml
+3
-0
test_compose_ui_slider_100/app/src/main/res/values/themes.xml
..._compose_ui_slider_100/app/src/main/res/values/themes.xml
+7
-0
test_compose_ui_slider_100/app/src/main/res/xml/backup_rules.xml
...mpose_ui_slider_100/app/src/main/res/xml/backup_rules.xml
+13
-0
test_compose_ui_slider_100/app/src/main/res/xml/data_extraction_rules.xml
...slider_100/app/src/main/res/xml/data_extraction_rules.xml
+19
-0
test_compose_ui_slider_100/app/src/test/java/com/example/jetpackcompose/ExampleUnitTest.kt
...c/test/java/com/example/jetpackcompose/ExampleUnitTest.kt
+17
-0
test_compose_ui_slider_100/build.gradle
test_compose_ui_slider_100/build.gradle
+11
-0
test_compose_ui_slider_100/gradle.properties
test_compose_ui_slider_100/gradle.properties
+23
-0
test_compose_ui_slider_100/gradle/wrapper/gradle-wrapper.jar
test_compose_ui_slider_100/gradle/wrapper/gradle-wrapper.jar
+0
-0
test_compose_ui_slider_100/gradle/wrapper/gradle-wrapper.properties
...se_ui_slider_100/gradle/wrapper/gradle-wrapper.properties
+6
-0
test_compose_ui_slider_100/gradlew
test_compose_ui_slider_100/gradlew
+185
-0
test_compose_ui_slider_100/gradlew.bat
test_compose_ui_slider_100/gradlew.bat
+89
-0
test_compose_ui_slider_100/settings.gradle
test_compose_ui_slider_100/settings.gradle
+16
-0
test_compose_ui_slider_100/slider100
test_compose_ui_slider_100/slider100
+0
-0
test_compose_ui_slider_100/test_compose_ui_slider_100.apk
test_compose_ui_slider_100/test_compose_ui_slider_100.apk
+0
-0
未找到文件。
test_compose_ui_slider_100/.gitignore
0 → 100644
浏览文件 @
4b7a7868
*.iml
.gradle
/local.properties
/.idea
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
test_compose_ui_slider_100/app/.gitignore
0 → 100644
浏览文件 @
4b7a7868
/build
/release
test_compose_ui_slider_100/app/build.gradle
0 → 100644
浏览文件 @
4b7a7868
plugins
{
id
'com.android.application'
id
'org.jetbrains.kotlin.android'
}
android
{
namespace
'com.example.jetpackcompose'
compileSdk
34
defaultConfig
{
applicationId
"com.example.jetpackcompose.slider100"
minSdk
21
targetSdk
32
versionCode
1
versionName
"1.0"
testInstrumentationRunner
"androidx.test.runner.AndroidJUnitRunner"
vectorDrawables
{
useSupportLibrary
true
}
}
buildTypes
{
release
{
minifyEnabled
false
proguardFiles
getDefaultProguardFile
(
'proguard-android-optimize.txt'
),
'proguard-rules.pro'
}
}
compileOptions
{
sourceCompatibility
JavaVersion
.
VERSION_1_8
targetCompatibility
JavaVersion
.
VERSION_1_8
}
kotlinOptions
{
jvmTarget
=
'1.8'
}
buildFeatures
{
compose
true
}
composeOptions
{
kotlinCompilerExtensionVersion
'1.4.3'
}
packagingOptions
{
resources
{
excludes
+=
'/META-INF/{AL2.0,LGPL2.1}'
}
}
}
dependencies
{
implementation
'androidx.core:core-ktx:1.7.0'
implementation
'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
implementation
'androidx.activity:activity-compose:1.3.1'
implementation
"androidx.compose.ui:ui:$compose_ui_version"
implementation
"androidx.compose.ui:ui-tooling-preview:$compose_ui_version"
implementation
"androidx.compose.ui:ui-util:$compose_ui_version"
implementation
'androidx.compose.material:material:1.4.3'
implementation
'androidx.core:core-ktx:+'
implementation
'androidx.core:core-ktx:+'
testImplementation
'junit:junit:4.13.2'
androidTestImplementation
'androidx.test.ext:junit:1.1.5'
androidTestImplementation
'androidx.test.espresso:espresso-core:3.5.1'
androidTestImplementation
"androidx.compose.ui:ui-test-junit4:$compose_ui_version"
debugImplementation
"androidx.compose.ui:ui-tooling:$compose_ui_version"
debugImplementation
"androidx.compose.ui:ui-test-manifest:$compose_ui_version"
}
\ No newline at end of file
test_compose_ui_slider_100/app/proguard-rules.pro
0 → 100644
浏览文件 @
4b7a7868
# Add project specific ProGuard rules here.
#
You
can
control
the
set
of
applied
configuration
files
using
the
#
proguardFiles
setting
in
build
.
gradle
.
#
#
For
more
details
,
see
#
http
://
developer
.
android
.
com
/
guide
/
developing
/
tools
/
proguard
.
html
#
If
your
project
uses
WebView
with
JS
,
uncomment
the
following
#
and
specify
the
fully
qualified
class
name
to
the
JavaScript
interface
#
class
:
#-
keepclassmembers
class
fqcn
.
of
.
javascript
.
interface
.
for
.
webview
{
#
public
*
;
#
}
#
Uncomment
this
to
preserve
the
line
number
information
for
#
debugging
stack
traces
.
#-
keepattributes
SourceFile
,
LineNumberTable
#
If
you
keep
the
line
number
information
,
uncomment
this
to
#
hide
the
original
source
file
name
.
#-
renamesourcefileattribute
SourceFile
\ No newline at end of file
test_compose_ui_slider_100/app/src/androidTest/java/com/example/jetpackcompose/ExampleInstrumentedTest.kt
0 → 100644
浏览文件 @
4b7a7868
package
com.example.jetpackcompose
import
androidx.test.platform.app.InstrumentationRegistry
import
androidx.test.ext.junit.runners.AndroidJUnit4
import
org.junit.Test
import
org.junit.runner.RunWith
import
org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith
(
AndroidJUnit4
::
class
)
class
ExampleInstrumentedTest
{
@Test
fun
useAppContext
()
{
// Context of the app under test.
val
appContext
=
InstrumentationRegistry
.
getInstrumentation
().
targetContext
assertEquals
(
"com.example.jetpackcompose"
,
appContext
.
packageName
)
}
}
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/AndroidManifest.xml
0 → 100644
浏览文件 @
4b7a7868
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:tools=
"http://schemas.android.com/tools"
>
<application
android:allowBackup=
"true"
android:dataExtractionRules=
"@xml/data_extraction_rules"
android:fullBackupContent=
"@xml/backup_rules"
android:icon=
"@mipmap/ic_launcher"
android:label=
"@string/app_name"
android:roundIcon=
"@mipmap/ic_launcher_round"
android:supportsRtl=
"true"
android:theme=
"@style/Theme.JetpackCompose"
tools:targetApi=
"31"
>
<activity
android:name=
".MainActivity"
android:exported=
"true"
android:label=
"@string/app_name"
android:theme=
"@style/Theme.JetpackCompose"
>
<intent-filter>
<action
android:name=
"android.intent.action.MAIN"
/>
<category
android:name=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
<meta-data
android:name=
"android.app.lib_name"
android:value=
""
/>
</activity>
</application>
</manifest>
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/java/androidx/compose/material1/DragGestureDetectorCopy.kt
0 → 100644
浏览文件 @
4b7a7868
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
androidx.compose.material1
// Copy-paste version of DragGestureDetector.kt. Please don't change this file without changing
// DragGestureDetector.kt
import
androidx.compose.ui.geometry.Offset
import
androidx.compose.ui.input.pointer.AwaitPointerEventScope
import
androidx.compose.ui.input.pointer.PointerEvent
import
androidx.compose.ui.input.pointer.PointerEventPass
import
androidx.compose.ui.input.pointer.PointerId
import
androidx.compose.ui.input.pointer.PointerInputChange
import
androidx.compose.ui.input.pointer.PointerType
import
androidx.compose.ui.input.pointer.changedToUpIgnoreConsumed
import
androidx.compose.ui.platform.ViewConfiguration
import
androidx.compose.ui.unit.dp
import
androidx.compose.ui.util.fastFirstOrNull
import
kotlin.math.abs
import
kotlin.math.sign
internal
suspend
fun
AwaitPointerEventScope
.
awaitHorizontalPointerSlopOrCancellation
(
pointerId
:
PointerId
,
pointerType
:
PointerType
,
onPointerSlopReached
:
(
change
:
PointerInputChange
,
overSlop
:
Float
)
->
Unit
)
=
awaitPointerSlopOrCancellation
(
pointerId
=
pointerId
,
pointerType
=
pointerType
,
onPointerSlopReached
=
onPointerSlopReached
,
getDragDirectionValue
=
{
it
.
x
}
)
private
suspend
inline
fun
AwaitPointerEventScope
.
awaitPointerSlopOrCancellation
(
pointerId
:
PointerId
,
pointerType
:
PointerType
,
onPointerSlopReached
:
(
PointerInputChange
,
Float
)
->
Unit
,
getDragDirectionValue
:
(
Offset
)
->
Float
):
PointerInputChange
?
{
if
(
currentEvent
.
isPointerUp
(
pointerId
))
{
return
null
// The pointer has already been lifted, so the gesture is canceled
}
val
touchSlop
=
viewConfiguration
.
pointerSlop
(
pointerType
)
var
pointer
:
PointerId
=
pointerId
var
totalPositionChange
=
0f
while
(
true
)
{
val
event
=
awaitPointerEvent
()
val
dragEvent
=
event
.
changes
.
fastFirstOrNull
{
it
.
id
==
pointer
}
!!
if
(
dragEvent
.
isConsumed
)
{
return
null
}
else
if
(
dragEvent
.
changedToUpIgnoreConsumed
())
{
val
otherDown
=
event
.
changes
.
fastFirstOrNull
{
it
.
pressed
}
if
(
otherDown
==
null
)
{
// This is the last "up"
return
null
}
else
{
pointer
=
otherDown
.
id
}
}
else
{
val
currentPosition
=
dragEvent
.
position
val
previousPosition
=
dragEvent
.
previousPosition
val
positionChange
=
getDragDirectionValue
(
currentPosition
)
-
getDragDirectionValue
(
previousPosition
)
totalPositionChange
+=
positionChange
val
inDirection
=
abs
(
totalPositionChange
)
if
(
inDirection
<
touchSlop
)
{
// verify that nothing else consumed the drag event
awaitPointerEvent
(
PointerEventPass
.
Final
)
if
(
dragEvent
.
isConsumed
)
{
return
null
}
}
else
{
onPointerSlopReached
(
dragEvent
,
totalPositionChange
-
(
sign
(
totalPositionChange
)
*
touchSlop
)
)
if
(
dragEvent
.
isConsumed
)
{
return
dragEvent
}
else
{
totalPositionChange
=
0f
}
}
}
}
}
private
fun
PointerEvent
.
isPointerUp
(
pointerId
:
PointerId
):
Boolean
=
changes
.
fastFirstOrNull
{
it
.
id
==
pointerId
}
?.
pressed
!=
true
private
val
mouseSlop
=
0.125
.
dp
private
val
defaultTouchSlop
=
18
.
dp
// The default touch slop on Android devices
private
val
mouseToTouchSlopRatio
=
mouseSlop
/
defaultTouchSlop
internal
fun
ViewConfiguration
.
pointerSlop
(
pointerType
:
PointerType
):
Float
{
return
when
(
pointerType
)
{
PointerType
.
Mouse
->
touchSlop
*
mouseToTouchSlopRatio
else
->
touchSlop
}
}
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/java/androidx/compose/material1/Slider.kt
0 → 100644
浏览文件 @
4b7a7868
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
androidx.compose.material1
import
androidx.compose.animation.core.Animatable
import
androidx.compose.animation.core.TweenSpec
import
androidx.compose.foundation.Canvas
import
androidx.compose.foundation.MutatePriority
import
androidx.compose.foundation.MutatorMutex
import
androidx.compose.foundation.background
import
androidx.compose.foundation.focusable
import
androidx.compose.foundation.gestures.DragScope
import
androidx.compose.foundation.gestures.DraggableState
import
androidx.compose.foundation.gestures.GestureCancellationException
import
androidx.compose.foundation.gestures.Orientation
import
androidx.compose.foundation.gestures.awaitFirstDown
import
androidx.compose.foundation.gestures.detectTapGestures
import
androidx.compose.foundation.gestures.draggable
import
androidx.compose.foundation.gestures.awaitEachGesture
import
androidx.compose.foundation.gestures.horizontalDrag
import
androidx.compose.foundation.hoverable
import
androidx.compose.foundation.indication
import
androidx.compose.foundation.interaction.DragInteraction
import
androidx.compose.foundation.interaction.Interaction
import
androidx.compose.foundation.interaction.MutableInteractionSource
import
androidx.compose.foundation.interaction.PressInteraction
import
androidx.compose.foundation.layout.Box
import
androidx.compose.foundation.layout.BoxScope
import
androidx.compose.foundation.layout.BoxWithConstraints
import
androidx.compose.foundation.layout.Spacer
import
androidx.compose.foundation.layout.fillMaxSize
import
androidx.compose.foundation.layout.heightIn
import
androidx.compose.foundation.layout.padding
import
androidx.compose.foundation.layout.requiredSizeIn
import
androidx.compose.foundation.layout.size
import
androidx.compose.foundation.layout.widthIn
import
androidx.compose.foundation.progressSemantics
import
androidx.compose.foundation.shape.CircleShape
import
androidx.compose.material.ContentAlpha
import
androidx.compose.material.ExperimentalMaterialApi
import
androidx.compose.material.MaterialTheme
import
androidx.compose.material.contentColorFor
import
androidx.compose.material.minimumInteractiveComponentSize
import
androidx.compose.material.ripple.rememberRipple
import
androidx.compose.runtime.Composable
import
androidx.compose.runtime.Immutable
import
androidx.compose.runtime.LaunchedEffect
import
androidx.compose.runtime.MutableState
import
androidx.compose.runtime.SideEffect
import
androidx.compose.runtime.Stable
import
androidx.compose.runtime.State
import
androidx.compose.runtime.getValue
import
androidx.compose.runtime.mutableStateListOf
import
androidx.compose.runtime.mutableStateOf
import
androidx.compose.runtime.remember
import
androidx.compose.runtime.rememberCoroutineScope
import
androidx.compose.runtime.rememberUpdatedState
import
androidx.compose.runtime.setValue
import
androidx.compose.ui.Alignment
import
androidx.compose.ui.Modifier
import
androidx.compose.ui.composed
import
androidx.compose.ui.draw.shadow
import
androidx.compose.ui.geometry.Offset
import
androidx.compose.ui.geometry.lerp
import
androidx.compose.ui.graphics.Color
import
androidx.compose.ui.graphics.PointMode
import
androidx.compose.ui.graphics.StrokeCap
import
androidx.compose.ui.graphics.compositeOver
import
androidx.compose.ui.input.pointer.AwaitPointerEventScope
import
androidx.compose.ui.input.pointer.PointerId
import
androidx.compose.ui.input.pointer.PointerInputChange
import
androidx.compose.ui.input.pointer.PointerType
import
androidx.compose.ui.input.pointer.pointerInput
import
androidx.compose.ui.input.pointer.positionChange
import
androidx.compose.ui.platform.LocalDensity
import
androidx.compose.ui.platform.LocalLayoutDirection
import
androidx.compose.ui.platform.debugInspectorInfo
import
androidx.compose.ui.semantics.contentDescription
import
androidx.compose.ui.semantics.disabled
import
androidx.compose.ui.semantics.semantics
import
androidx.compose.ui.semantics.setProgress
import
androidx.compose.ui.unit.Dp
import
androidx.compose.ui.unit.LayoutDirection
import
androidx.compose.ui.unit.dp
import
androidx.compose.ui.util.lerp
import
kotlin.math.abs
import
kotlin.math.floor
import
kotlin.math.max
import
kotlin.math.min
import
kotlinx.coroutines.CancellationException
import
kotlinx.coroutines.CoroutineScope
import
kotlinx.coroutines.coroutineScope
import
kotlinx.coroutines.launch
/**
* <a href="https://material.io/components/sliders" class="external" target="_blank">Material Design slider</a>.
*
* Sliders allow users to make selections from a range of values.
*
* Sliders reflect a range of values along a bar, from which users may select a single value.
* They are ideal for adjusting settings such as volume, brightness, or applying image filters.
*
* ![Sliders image](https://developer.android.com/images/reference/androidx/compose/material/sliders.png)
*
* Use continuous sliders to allow users to make meaningful selections that don’t
* require a specific value:
*
* @sample androidx.compose.material.samples.SliderSample
*
* You can allow the user to choose only between predefined set of values by specifying the amount
* of steps between min and max values:
*
* @sample androidx.compose.material.samples.StepsSliderSample
*
* @param value current value of the Slider. If outside of [valueRange] provided, value will be
* coerced to this range.
* @param onValueChange lambda in which value should be updated
* @param modifier modifiers for the Slider layout
* @param enabled whether or not component is enabled and can be interacted with or not
* @param valueRange range of values that Slider value can take. Passed [value] will be coerced to
* this range
* @param steps if greater than 0, specifies the amounts of discrete values, evenly distributed
* between across the whole value range. If 0, slider will behave as a continuous slider and allow
* to choose any value from the range specified. Must not be negative.
* @param onValueChangeFinished lambda to be invoked when value change has ended. This callback
* shouldn't be used to update the slider value (use [onValueChange] for that), but rather to
* know when the user has completed selecting a new value by ending a drag or a click.
* @param interactionSource the [MutableInteractionSource] representing the stream of
* [Interaction]s for this Slider. You can create and pass in your own remembered
* [MutableInteractionSource] if you want to observe [Interaction]s and customize the
* appearance / behavior of this Slider in different [Interaction]s.
* @param colors [SliderColors] that will be used to determine the color of the Slider parts in
* different state. See [SliderDefaults.colors] to customize.
*/
@Composable
fun
Slider
(
value
:
Float
,
onValueChange
:
(
Float
)
->
Unit
,
modifier
:
Modifier
=
Modifier
,
enabled
:
Boolean
=
true
,
valueRange
:
ClosedFloatingPointRange
<
Float
>
=
0f
..
1f
,
/*@IntRange(from = 0)*/
steps
:
Int
=
0
,
onValueChangeFinished
:
(()
->
Unit
)?
=
null
,
interactionSource
:
MutableInteractionSource
=
remember
{
MutableInteractionSource
()
},
colors
:
SliderColors
=
SliderDefaults
.
colors
()
)
{
require
(
steps
>=
0
)
{
"steps should be >= 0"
}
val
onValueChangeState
=
rememberUpdatedState
(
onValueChange
)
val
tickFractions
=
remember
(
steps
)
{
stepsToTickFractions
(
steps
)
}
BoxWithConstraints
(
modifier
.
minimumInteractiveComponentSize
()
.
requiredSizeIn
(
minWidth
=
ThumbRadius
*
2
,
minHeight
=
ThumbRadius
*
2
)
.
sliderSemantics
(
value
,
enabled
,
onValueChange
,
onValueChangeFinished
,
valueRange
,
steps
)
.
focusable
(
enabled
,
interactionSource
)
)
{
val
isRtl
=
LocalLayoutDirection
.
current
==
LayoutDirection
.
Rtl
val
widthPx
=
constraints
.
maxWidth
.
toFloat
()
val
maxPx
:
Float
val
minPx
:
Float
with
(
LocalDensity
.
current
)
{
maxPx
=
max
(
widthPx
-
ThumbRadius
.
toPx
(),
0f
)
minPx
=
min
(
ThumbRadius
.
toPx
(),
maxPx
)
}
fun
scaleToUserValue
(
offset
:
Float
)
=
scale
(
minPx
,
maxPx
,
offset
,
valueRange
.
start
,
valueRange
.
endInclusive
)
fun
scaleToOffset
(
userValue
:
Float
)
=
scale
(
valueRange
.
start
,
valueRange
.
endInclusive
,
userValue
,
minPx
,
maxPx
)
val
scope
=
rememberCoroutineScope
()
val
rawOffset
=
remember
{
mutableStateOf
(
scaleToOffset
(
value
))
}
val
pressOffset
=
remember
{
mutableStateOf
(
0f
)
}
val
draggableState
=
remember
(
minPx
,
maxPx
,
valueRange
)
{
SliderDraggableState
{
rawOffset
.
value
=
(
rawOffset
.
value
+
it
+
pressOffset
.
value
)
pressOffset
.
value
=
0f
val
offsetInTrack
=
rawOffset
.
value
.
coerceIn
(
minPx
,
maxPx
)
onValueChangeState
.
value
.
invoke
(
scaleToUserValue
(
offsetInTrack
))
}
}
CorrectValueSideEffect
(
::
scaleToOffset
,
valueRange
,
minPx
..
maxPx
,
rawOffset
,
value
)
val
gestureEndAction
=
rememberUpdatedState
<(
Float
)
->
Unit
>
{
velocity
:
Float
->
val
current
=
rawOffset
.
value
val
target
=
snapValueToTick
(
current
,
tickFractions
,
minPx
,
maxPx
)
if
(
current
!=
target
)
{
scope
.
launch
{
animateToTarget
(
draggableState
,
current
,
target
,
velocity
)
onValueChangeFinished
?.
invoke
()
}
}
else
if
(!
draggableState
.
isDragging
)
{
// check ifDragging in case the change is still in progress (touch -> drag case)
onValueChangeFinished
?.
invoke
()
}
}
val
press
=
Modifier
.
sliderTapModifier
(
draggableState
,
interactionSource
,
widthPx
,
isRtl
,
rawOffset
,
gestureEndAction
,
pressOffset
,
enabled
)
val
drag
=
Modifier
.
draggable
(
orientation
=
Orientation
.
Horizontal
,
reverseDirection
=
isRtl
,
enabled
=
enabled
,
interactionSource
=
interactionSource
,
onDragStopped
=
{
velocity
->
gestureEndAction
.
value
.
invoke
(
velocity
)
},
startDragImmediately
=
draggableState
.
isDragging
,
state
=
draggableState
)
val
coerced
=
value
.
coerceIn
(
valueRange
.
start
,
valueRange
.
endInclusive
)
val
fraction
=
calcFraction
(
valueRange
.
start
,
valueRange
.
endInclusive
,
coerced
)
SliderImpl
(
enabled
,
fraction
,
tickFractions
,
colors
,
maxPx
-
minPx
,
interactionSource
,
modifier
=
press
.
then
(
drag
)
)
}
}
/**
* <a href="https://material.io/components/sliders" class="external" target="_blank">Material Design slider</a>.
*
* Range Sliders expand upon [Slider] using the same concepts but allow the user to select 2 values.
*
* The two values are still bounded by the value range but they also cannot cross each other.
*
* Use continuous Range Sliders to allow users to make meaningful selections that don’t
* require a specific values:
*
* @sample androidx.compose.material.samples.RangeSliderSample
*
* You can allow the user to choose only between predefined set of values by specifying the amount
* of steps between min and max values:
*
* @sample androidx.compose.material.samples.StepRangeSliderSample
*
* @param value current values of the RangeSlider. If either value is outside of [valueRange]
* provided, it will be coerced to this range.
* @param onValueChange lambda in which values should be updated
* @param modifier modifiers for the Range Slider layout
* @param enabled whether or not component is enabled and can we interacted with or not
* @param valueRange range of values that Range Slider values can take. Passed [value] will be
* coerced to this range
* @param steps if greater than 0, specifies the amounts of discrete values, evenly distributed
* between across the whole value range. If 0, range slider will behave as a continuous slider and
* allow to choose any values from the range specified. Must not be negative.
* @param onValueChangeFinished lambda to be invoked when value change has ended. This callback
* shouldn't be used to update the range slider values (use [onValueChange] for that), but rather to
* know when the user has completed selecting a new value by ending a drag or a click.
* @param colors [SliderColors] that will be used to determine the color of the Range Slider
* parts in different state. See [SliderDefaults.colors] to customize.
*/
@Composable
@ExperimentalMaterialApi
fun
RangeSlider
(
value
:
ClosedFloatingPointRange
<
Float
>,
onValueChange
:
(
ClosedFloatingPointRange
<
Float
>)
->
Unit
,
modifier
:
Modifier
=
Modifier
,
enabled
:
Boolean
=
true
,
valueRange
:
ClosedFloatingPointRange
<
Float
>
=
0f
..
1f
,
/*@IntRange(from = 0)*/
steps
:
Int
=
0
,
onValueChangeFinished
:
(()
->
Unit
)?
=
null
,
colors
:
SliderColors
=
SliderDefaults
.
colors
()
)
{
val
startInteractionSource
:
MutableInteractionSource
=
remember
{
MutableInteractionSource
()
}
val
endInteractionSource
:
MutableInteractionSource
=
remember
{
MutableInteractionSource
()
}
require
(
steps
>=
0
)
{
"steps should be >= 0"
}
val
onValueChangeState
=
rememberUpdatedState
(
onValueChange
)
val
tickFractions
=
remember
(
steps
)
{
stepsToTickFractions
(
steps
)
}
BoxWithConstraints
(
modifier
=
modifier
.
minimumInteractiveComponentSize
()
.
requiredSizeIn
(
minWidth
=
ThumbRadius
*
4
,
minHeight
=
ThumbRadius
*
2
)
)
{
val
isRtl
=
LocalLayoutDirection
.
current
==
LayoutDirection
.
Rtl
val
widthPx
=
constraints
.
maxWidth
.
toFloat
()
val
maxPx
:
Float
val
minPx
:
Float
with
(
LocalDensity
.
current
)
{
maxPx
=
widthPx
-
ThumbRadius
.
toPx
()
minPx
=
ThumbRadius
.
toPx
()
}
fun
scaleToUserValue
(
offset
:
ClosedFloatingPointRange
<
Float
>)
=
scale
(
minPx
,
maxPx
,
offset
,
valueRange
.
start
,
valueRange
.
endInclusive
)
fun
scaleToOffset
(
userValue
:
Float
)
=
scale
(
valueRange
.
start
,
valueRange
.
endInclusive
,
userValue
,
minPx
,
maxPx
)
val
rawOffsetStart
=
remember
{
mutableStateOf
(
scaleToOffset
(
value
.
start
))
}
val
rawOffsetEnd
=
remember
{
mutableStateOf
(
scaleToOffset
(
value
.
endInclusive
))
}
CorrectValueSideEffect
(
::
scaleToOffset
,
valueRange
,
minPx
..
maxPx
,
rawOffsetStart
,
value
.
start
)
CorrectValueSideEffect
(
::
scaleToOffset
,
valueRange
,
minPx
..
maxPx
,
rawOffsetEnd
,
value
.
endInclusive
)
val
scope
=
rememberCoroutineScope
()
val
gestureEndAction
=
rememberUpdatedState
<(
Boolean
)
->
Unit
>
{
isStart
->
val
current
=
(
if
(
isStart
)
rawOffsetStart
else
rawOffsetEnd
).
value
// target is a closest anchor to the `current`, if exists
val
target
=
snapValueToTick
(
current
,
tickFractions
,
minPx
,
maxPx
)
if
(
current
==
target
)
{
onValueChangeFinished
?.
invoke
()
return
@rememberUpdatedState
}
scope
.
launch
{
Animatable
(
initialValue
=
current
).
animateTo
(
target
,
SliderToTickAnimation
,
0f
)
{
(
if
(
isStart
)
rawOffsetStart
else
rawOffsetEnd
).
value
=
this
.
value
onValueChangeState
.
value
.
invoke
(
scaleToUserValue
(
rawOffsetStart
.
value
..
rawOffsetEnd
.
value
)
)
}
onValueChangeFinished
?.
invoke
()
}
}
val
onDrag
=
rememberUpdatedState
<(
Boolean
,
Float
)
->
Unit
>
{
isStart
,
offset
->
val
offsetRange
=
if
(
isStart
)
{
rawOffsetStart
.
value
=
(
rawOffsetStart
.
value
+
offset
)
rawOffsetEnd
.
value
=
scaleToOffset
(
value
.
endInclusive
)
val
offsetEnd
=
rawOffsetEnd
.
value
val
offsetStart
=
rawOffsetStart
.
value
.
coerceIn
(
minPx
,
offsetEnd
)
offsetStart
..
offsetEnd
}
else
{
rawOffsetEnd
.
value
=
(
rawOffsetEnd
.
value
+
offset
)
rawOffsetStart
.
value
=
scaleToOffset
(
value
.
start
)
val
offsetStart
=
rawOffsetStart
.
value
val
offsetEnd
=
rawOffsetEnd
.
value
.
coerceIn
(
offsetStart
,
maxPx
)
offsetStart
..
offsetEnd
}
onValueChangeState
.
value
.
invoke
(
scaleToUserValue
(
offsetRange
))
}
val
pressDrag
=
Modifier
.
rangeSliderPressDragModifier
(
startInteractionSource
,
endInteractionSource
,
rawOffsetStart
,
rawOffsetEnd
,
enabled
,
isRtl
,
widthPx
,
valueRange
,
gestureEndAction
,
onDrag
,
)
// The positions of the thumbs are dependant on each other.
val
coercedStart
=
value
.
start
.
coerceIn
(
valueRange
.
start
,
value
.
endInclusive
)
val
coercedEnd
=
value
.
endInclusive
.
coerceIn
(
value
.
start
,
valueRange
.
endInclusive
)
val
fractionStart
=
calcFraction
(
valueRange
.
start
,
valueRange
.
endInclusive
,
coercedStart
)
val
fractionEnd
=
calcFraction
(
valueRange
.
start
,
valueRange
.
endInclusive
,
coercedEnd
)
val
startSteps
=
floor
(
steps
*
fractionEnd
).
toInt
()
val
endSteps
=
floor
(
steps
*
(
1f
-
fractionStart
)).
toInt
()
val
startThumbSemantics
=
Modifier
.
sliderSemantics
(
coercedStart
,
enabled
,
{
value
->
onValueChangeState
.
value
.
invoke
(
value
..
coercedEnd
)
},
onValueChangeFinished
,
valueRange
.
start
..
coercedEnd
,
startSteps
)
val
endThumbSemantics
=
Modifier
.
sliderSemantics
(
coercedEnd
,
enabled
,
{
value
->
onValueChangeState
.
value
.
invoke
(
coercedStart
..
value
)
},
onValueChangeFinished
,
coercedStart
..
valueRange
.
endInclusive
,
endSteps
)
RangeSliderImpl
(
enabled
,
fractionStart
,
fractionEnd
,
tickFractions
,
colors
,
maxPx
-
minPx
,
startInteractionSource
,
endInteractionSource
,
modifier
=
pressDrag
,
startThumbSemantics
,
endThumbSemantics
)
}
}
/**
* Object to hold defaults used by [Slider]
*/
object
SliderDefaults
{
/**
* Creates a [SliderColors] that represents the different colors used in parts of the
* [Slider] in different states.
*
* For the name references below the words "active" and "inactive" are used. Active part of
* the slider is filled with progress, so if slider's progress is 30% out of 100%, left (or
* right in RTL) 30% of the track will be active, the rest is not active.
*
* @param thumbColor thumb color when enabled
* @param disabledThumbColor thumb colors when disabled
* @param activeTrackColor color of the track in the part that is "active", meaning that the
* thumb is ahead of it
* @param inactiveTrackColor color of the track in the part that is "inactive", meaning that the
* thumb is before it
* @param disabledActiveTrackColor color of the track in the "active" part when the Slider is
* disabled
* @param disabledInactiveTrackColor color of the track in the "inactive" part when the
* Slider is disabled
* @param activeTickColor colors to be used to draw tick marks on the active track, if `steps`
* is specified
* @param inactiveTickColor colors to be used to draw tick marks on the inactive track, if
* `steps` are specified on the Slider is specified
* @param disabledActiveTickColor colors to be used to draw tick marks on the active track
* when Slider is disabled and when `steps` are specified on it
* @param disabledInactiveTickColor colors to be used to draw tick marks on the inactive part
* of the track when Slider is disabled and when `steps` are specified on it
*/
@Composable
fun
colors
(
thumbColor
:
Color
=
MaterialTheme
.
colors
.
primary
,
disabledThumbColor
:
Color
=
MaterialTheme
.
colors
.
onSurface
.
copy
(
alpha
=
ContentAlpha
.
disabled
)
.
compositeOver
(
MaterialTheme
.
colors
.
surface
),
activeTrackColor
:
Color
=
MaterialTheme
.
colors
.
primary
,
inactiveTrackColor
:
Color
=
activeTrackColor
.
copy
(
alpha
=
InactiveTrackAlpha
),
disabledActiveTrackColor
:
Color
=
MaterialTheme
.
colors
.
onSurface
.
copy
(
alpha
=
DisabledActiveTrackAlpha
),
disabledInactiveTrackColor
:
Color
=
disabledActiveTrackColor
.
copy
(
alpha
=
DisabledInactiveTrackAlpha
),
activeTickColor
:
Color
=
contentColorFor
(
activeTrackColor
).
copy
(
alpha
=
TickAlpha
),
inactiveTickColor
:
Color
=
activeTrackColor
.
copy
(
alpha
=
TickAlpha
),
disabledActiveTickColor
:
Color
=
activeTickColor
.
copy
(
alpha
=
DisabledTickAlpha
),
disabledInactiveTickColor
:
Color
=
disabledInactiveTrackColor
.
copy
(
alpha
=
DisabledTickAlpha
)
):
SliderColors
=
DefaultSliderColors
(
thumbColor
=
thumbColor
,
disabledThumbColor
=
disabledThumbColor
,
activeTrackColor
=
activeTrackColor
,
inactiveTrackColor
=
inactiveTrackColor
,
disabledActiveTrackColor
=
disabledActiveTrackColor
,
disabledInactiveTrackColor
=
disabledInactiveTrackColor
,
activeTickColor
=
activeTickColor
,
inactiveTickColor
=
inactiveTickColor
,
disabledActiveTickColor
=
disabledActiveTickColor
,
disabledInactiveTickColor
=
disabledInactiveTickColor
)
/**
* Default alpha of the inactive part of the track
*/
const
val
InactiveTrackAlpha
=
0.24f
/**
* Default alpha for the track when it is disabled but active
*/
const
val
DisabledInactiveTrackAlpha
=
0.12f
/**
* Default alpha for the track when it is disabled and inactive
*/
const
val
DisabledActiveTrackAlpha
=
0.32f
/**
* Default alpha of the ticks that are drawn on top of the track
*/
const
val
TickAlpha
=
0.54f
/**
* Default alpha for tick marks when they are disabled
*/
const
val
DisabledTickAlpha
=
0.12f
}
/**
* Represents the colors used by a [Slider] and its parts in different states
*
* See [SliderDefaults.colors] for the default implementation that follows Material
* specifications.
*/
@Stable
interface
SliderColors
{
/**
* Represents the color used for the sliders's thumb, depending on [enabled].
*
* @param enabled whether the [Slider] is enabled or not
*/
@Composable
fun
thumbColor
(
enabled
:
Boolean
):
State
<
Color
>
/**
* Represents the color used for the sliders's track, depending on [enabled] and [active].
*
* Active part is filled with progress, so if sliders progress is 30% out of 100%, left (or
* right in RTL) 30% of the track will be active, the rest is not active.
*
* @param enabled whether the [Slider] is enabled or not
* @param active whether the part of the track is active of not
*/
@Composable
fun
trackColor
(
enabled
:
Boolean
,
active
:
Boolean
):
State
<
Color
>
/**
* Represents the color used for the sliders's tick which is the dot separating steps, if
* they are set on the slider, depending on [enabled] and [active].
*
* Active tick is the tick that is in the part of the track filled with progress, so if
* sliders progress is 30% out of 100%, left (or right in RTL) 30% of the track and the ticks
* in this 30% will be active, the rest is not active.
*
* @param enabled whether the [Slider] is enabled or not
* @param active whether the part of the track this tick is in is active of not
*/
@Composable
fun
tickColor
(
enabled
:
Boolean
,
active
:
Boolean
):
State
<
Color
>
}
@Composable
private
fun
SliderImpl
(
enabled
:
Boolean
,
positionFraction
:
Float
,
tickFractions
:
List
<
Float
>,
colors
:
SliderColors
,
width
:
Float
,
interactionSource
:
MutableInteractionSource
,
modifier
:
Modifier
)
{
Box
(
modifier
.
then
(
DefaultSliderConstraints
))
{
val
trackStrokeWidth
:
Float
val
thumbPx
:
Float
val
widthDp
:
Dp
with
(
LocalDensity
.
current
)
{
trackStrokeWidth
=
TrackHeight
.
toPx
()
thumbPx
=
ThumbRadius
.
toPx
()
widthDp
=
width
.
toDp
()
}
val
thumbSize
=
ThumbRadius
*
2
val
offset
=
widthDp
*
positionFraction
Track
(
Modifier
.
fillMaxSize
(),
colors
,
enabled
,
0f
,
positionFraction
,
tickFractions
,
thumbPx
,
trackStrokeWidth
)
SliderThumb
(
Modifier
,
offset
,
interactionSource
,
colors
,
enabled
,
thumbSize
)
}
}
@Composable
private
fun
RangeSliderImpl
(
enabled
:
Boolean
,
positionFractionStart
:
Float
,
positionFractionEnd
:
Float
,
tickFractions
:
List
<
Float
>,
colors
:
SliderColors
,
width
:
Float
,
startInteractionSource
:
MutableInteractionSource
,
endInteractionSource
:
MutableInteractionSource
,
modifier
:
Modifier
,
startThumbSemantics
:
Modifier
,
endThumbSemantics
:
Modifier
)
{
val
startContentDescription
=
getString
(
Strings
.
SliderRangeStart
)
val
endContentDescription
=
getString
(
Strings
.
SliderRangeEnd
)
Box
(
modifier
.
then
(
DefaultSliderConstraints
))
{
val
trackStrokeWidth
:
Float
val
thumbPx
:
Float
val
widthDp
:
Dp
with
(
LocalDensity
.
current
)
{
trackStrokeWidth
=
TrackHeight
.
toPx
()
thumbPx
=
ThumbRadius
.
toPx
()
widthDp
=
width
.
toDp
()
}
val
thumbSize
=
ThumbRadius
*
2
val
offsetStart
=
widthDp
*
positionFractionStart
val
offsetEnd
=
widthDp
*
positionFractionEnd
Track
(
Modifier
.
align
(
Alignment
.
CenterStart
)
.
fillMaxSize
(),
colors
,
enabled
,
positionFractionStart
,
positionFractionEnd
,
tickFractions
,
thumbPx
,
trackStrokeWidth
)
SliderThumb
(
Modifier
.
semantics
(
mergeDescendants
=
true
)
{
contentDescription
=
startContentDescription
}
.
focusable
(
true
,
startInteractionSource
)
.
then
(
startThumbSemantics
),
offsetStart
,
startInteractionSource
,
colors
,
enabled
,
thumbSize
)
SliderThumb
(
Modifier
.
semantics
(
mergeDescendants
=
true
)
{
contentDescription
=
endContentDescription
}
.
focusable
(
true
,
endInteractionSource
)
.
then
(
endThumbSemantics
),
offsetEnd
,
endInteractionSource
,
colors
,
enabled
,
thumbSize
)
}
}
@Composable
private
fun
BoxScope
.
SliderThumb
(
modifier
:
Modifier
,
offset
:
Dp
,
interactionSource
:
MutableInteractionSource
,
colors
:
SliderColors
,
enabled
:
Boolean
,
thumbSize
:
Dp
)
{
Box
(
Modifier
.
padding
(
start
=
offset
)
.
align
(
Alignment
.
CenterStart
))
{
val
interactions
=
remember
{
mutableStateListOf
<
Interaction
>()
}
LaunchedEffect
(
interactionSource
)
{
interactionSource
.
interactions
.
collect
{
interaction
->
when
(
interaction
)
{
is
PressInteraction
.
Press
->
interactions
.
add
(
interaction
)
is
PressInteraction
.
Release
->
interactions
.
remove
(
interaction
.
press
)
is
PressInteraction
.
Cancel
->
interactions
.
remove
(
interaction
.
press
)
is
DragInteraction
.
Start
->
interactions
.
add
(
interaction
)
is
DragInteraction
.
Stop
->
interactions
.
remove
(
interaction
.
start
)
is
DragInteraction
.
Cancel
->
interactions
.
remove
(
interaction
.
start
)
}
}
}
val
elevation
=
if
(
interactions
.
isNotEmpty
())
{
ThumbPressedElevation
}
else
{
ThumbDefaultElevation
}
Spacer
(
modifier
.
size
(
thumbSize
,
thumbSize
)
// .indication(
// interactionSource = interactionSource,
// indication = rememberRipple(bounded = false, radius = ThumbRippleRadius)
// )
.
hoverable
(
interactionSource
=
interactionSource
)
// .shadow(if (enabled) elevation else 0.dp, CircleShape, clip = false)
.
background
(
colors
.
thumbColor
(
enabled
).
value
,
CircleShape
)
)
}
}
@Composable
private
fun
Track
(
modifier
:
Modifier
,
colors
:
SliderColors
,
enabled
:
Boolean
,
positionFractionStart
:
Float
,
positionFractionEnd
:
Float
,
tickFractions
:
List
<
Float
>,
thumbPx
:
Float
,
trackStrokeWidth
:
Float
)
{
val
inactiveTrackColor
=
colors
.
trackColor
(
enabled
,
active
=
false
)
val
activeTrackColor
=
colors
.
trackColor
(
enabled
,
active
=
true
)
val
inactiveTickColor
=
colors
.
tickColor
(
enabled
,
active
=
false
)
val
activeTickColor
=
colors
.
tickColor
(
enabled
,
active
=
true
)
Canvas
(
modifier
)
{
val
isRtl
=
layoutDirection
==
LayoutDirection
.
Rtl
val
sliderLeft
=
Offset
(
thumbPx
,
center
.
y
)
val
sliderRight
=
Offset
(
size
.
width
-
thumbPx
,
center
.
y
)
val
sliderStart
=
if
(
isRtl
)
sliderRight
else
sliderLeft
val
sliderEnd
=
if
(
isRtl
)
sliderLeft
else
sliderRight
drawLine
(
inactiveTrackColor
.
value
,
sliderStart
,
sliderEnd
,
trackStrokeWidth
,
StrokeCap
.
Round
)
val
sliderValueEnd
=
Offset
(
sliderStart
.
x
+
(
sliderEnd
.
x
-
sliderStart
.
x
)
*
positionFractionEnd
,
center
.
y
)
val
sliderValueStart
=
Offset
(
sliderStart
.
x
+
(
sliderEnd
.
x
-
sliderStart
.
x
)
*
positionFractionStart
,
center
.
y
)
drawLine
(
activeTrackColor
.
value
,
sliderValueStart
,
sliderValueEnd
,
trackStrokeWidth
,
StrokeCap
.
Round
)
tickFractions
.
groupBy
{
it
>
positionFractionEnd
||
it
<
positionFractionStart
}
.
forEach
{
(
outsideFraction
,
list
)
->
drawPoints
(
list
.
map
{
Offset
(
lerp
(
sliderStart
,
sliderEnd
,
it
).
x
,
center
.
y
)
},
PointMode
.
Points
,
(
if
(
outsideFraction
)
inactiveTickColor
else
activeTickColor
).
value
,
trackStrokeWidth
,
StrokeCap
.
Round
)
}
}
}
private
fun
snapValueToTick
(
current
:
Float
,
tickFractions
:
List
<
Float
>,
minPx
:
Float
,
maxPx
:
Float
):
Float
{
// target is a closest anchor to the `current`, if exists
return
tickFractions
.
minByOrNull
{
abs
(
lerp
(
minPx
,
maxPx
,
it
)
-
current
)
}
?.
run
{
lerp
(
minPx
,
maxPx
,
this
)
}
?:
current
}
private
suspend
fun
AwaitPointerEventScope
.
awaitSlop
(
id
:
PointerId
,
type
:
PointerType
):
Pair
<
PointerInputChange
,
Float
>?
{
var
initialDelta
=
0f
val
postPointerSlop
=
{
pointerInput
:
PointerInputChange
,
offset
:
Float
->
pointerInput
.
consume
()
initialDelta
=
offset
}
val
afterSlopResult
=
awaitHorizontalPointerSlopOrCancellation
(
id
,
type
,
postPointerSlop
)
return
if
(
afterSlopResult
!=
null
)
afterSlopResult
to
initialDelta
else
null
}
private
fun
stepsToTickFractions
(
steps
:
Int
):
List
<
Float
>
{
return
if
(
steps
==
0
)
emptyList
()
else
List
(
steps
+
2
)
{
it
.
toFloat
()
/
(
steps
+
1
)
}
}
// Scale x1 from a1..b1 range to a2..b2 range
private
fun
scale
(
a1
:
Float
,
b1
:
Float
,
x1
:
Float
,
a2
:
Float
,
b2
:
Float
)
=
lerp
(
a2
,
b2
,
calcFraction
(
a1
,
b1
,
x1
))
// Scale x.start, x.endInclusive from a1..b1 range to a2..b2 range
private
fun
scale
(
a1
:
Float
,
b1
:
Float
,
x
:
ClosedFloatingPointRange
<
Float
>,
a2
:
Float
,
b2
:
Float
)
=
scale
(
a1
,
b1
,
x
.
start
,
a2
,
b2
)
..
scale
(
a1
,
b1
,
x
.
endInclusive
,
a2
,
b2
)
// Calculate the 0..1 fraction that `pos` value represents between `a` and `b`
private
fun
calcFraction
(
a
:
Float
,
b
:
Float
,
pos
:
Float
)
=
(
if
(
b
-
a
==
0f
)
0f
else
(
pos
-
a
)
/
(
b
-
a
)).
coerceIn
(
0f
,
1f
)
@Composable
private
fun
CorrectValueSideEffect
(
scaleToOffset
:
(
Float
)
->
Float
,
valueRange
:
ClosedFloatingPointRange
<
Float
>,
trackRange
:
ClosedFloatingPointRange
<
Float
>,
valueState
:
MutableState
<
Float
>,
value
:
Float
)
{
SideEffect
{
val
error
=
(
valueRange
.
endInclusive
-
valueRange
.
start
)
/
1000
val
newOffset
=
scaleToOffset
(
value
)
if
(
abs
(
newOffset
-
valueState
.
value
)
>
error
)
{
if
(
valueState
.
value
in
trackRange
)
{
valueState
.
value
=
newOffset
}
}
}
}
private
fun
Modifier
.
sliderSemantics
(
value
:
Float
,
enabled
:
Boolean
,
onValueChange
:
(
Float
)
->
Unit
,
onValueChangeFinished
:
(()
->
Unit
)?
=
null
,
valueRange
:
ClosedFloatingPointRange
<
Float
>
=
0f
..
1f
,
steps
:
Int
=
0
):
Modifier
{
val
coerced
=
value
.
coerceIn
(
valueRange
.
start
,
valueRange
.
endInclusive
)
return
semantics
{
if
(!
enabled
)
disabled
()
setProgress
(
action
=
{
targetValue
->
var
newValue
=
targetValue
.
coerceIn
(
valueRange
.
start
,
valueRange
.
endInclusive
)
val
originalVal
=
newValue
val
resolvedValue
=
if
(
steps
>
0
)
{
var
distance
:
Float
=
newValue
for
(
i
in
0
..
steps
+
1
)
{
val
stepValue
=
lerp
(
valueRange
.
start
,
valueRange
.
endInclusive
,
i
.
toFloat
()
/
(
steps
+
1
))
if
(
abs
(
stepValue
-
originalVal
)
<=
distance
)
{
distance
=
abs
(
stepValue
-
originalVal
)
newValue
=
stepValue
}
}
newValue
}
else
{
newValue
}
// This is to keep it consistent with AbsSeekbar.java: return false if no
// change from current.
if
(
resolvedValue
==
coerced
)
{
false
}
else
{
onValueChange
(
resolvedValue
)
onValueChangeFinished
?.
invoke
()
true
}
}
)
}.
progressSemantics
(
value
,
valueRange
,
steps
)
}
private
fun
Modifier
.
sliderTapModifier
(
draggableState
:
DraggableState
,
interactionSource
:
MutableInteractionSource
,
maxPx
:
Float
,
isRtl
:
Boolean
,
rawOffset
:
State
<
Float
>,
gestureEndAction
:
State
<
(
Float
)
-
>
Unit
>,
pressOffset
:
MutableState
<
Float
>,
enabled
:
Boolean
)
=
composed
(
factory
=
{
if
(
enabled
)
{
val
scope
=
rememberCoroutineScope
()
pointerInput
(
draggableState
,
interactionSource
,
maxPx
,
isRtl
)
{
detectTapGestures
(
onPress
=
{
pos
->
val
to
=
if
(
isRtl
)
maxPx
-
pos
.
x
else
pos
.
x
pressOffset
.
value
=
to
-
rawOffset
.
value
try
{
awaitRelease
()
}
catch
(
_
:
GestureCancellationException
)
{
pressOffset
.
value
=
0f
}
},
onTap
=
{
scope
.
launch
{
draggableState
.
drag
(
MutatePriority
.
UserInput
)
{
// just trigger animation, press offset will be applied
dragBy
(
0f
)
}
gestureEndAction
.
value
.
invoke
(
0f
)
}
}
)
}
}
else
{
this
}
},
inspectorInfo
=
debugInspectorInfo
{
name
=
"sliderTapModifier"
properties
[
"draggableState"
]
=
draggableState
properties
[
"interactionSource"
]
=
interactionSource
properties
[
"maxPx"
]
=
maxPx
properties
[
"isRtl"
]
=
isRtl
properties
[
"rawOffset"
]
=
rawOffset
properties
[
"gestureEndAction"
]
=
gestureEndAction
properties
[
"pressOffset"
]
=
pressOffset
properties
[
"enabled"
]
=
enabled
})
private
suspend
fun
animateToTarget
(
draggableState
:
DraggableState
,
current
:
Float
,
target
:
Float
,
velocity
:
Float
)
{
draggableState
.
drag
{
var
latestValue
=
current
Animatable
(
initialValue
=
current
).
animateTo
(
target
,
SliderToTickAnimation
,
velocity
)
{
dragBy
(
this
.
value
-
latestValue
)
latestValue
=
this
.
value
}
}
}
private
fun
Modifier
.
rangeSliderPressDragModifier
(
startInteractionSource
:
MutableInteractionSource
,
endInteractionSource
:
MutableInteractionSource
,
rawOffsetStart
:
State
<
Float
>,
rawOffsetEnd
:
State
<
Float
>,
enabled
:
Boolean
,
isRtl
:
Boolean
,
maxPx
:
Float
,
valueRange
:
ClosedFloatingPointRange
<
Float
>,
gestureEndAction
:
State
<
(
Boolean
)
-
>
Unit
>,
onDrag
:
State
<
(
Boolean
,
Float
)
-
>
Unit
>,
):
Modifier
=
if
(
enabled
)
{
pointerInput
(
startInteractionSource
,
endInteractionSource
,
maxPx
,
isRtl
,
valueRange
)
{
val
rangeSliderLogic
=
RangeSliderLogic
(
startInteractionSource
,
endInteractionSource
,
rawOffsetStart
,
rawOffsetEnd
,
onDrag
)
coroutineScope
{
awaitEachGesture
{
val
event
=
awaitFirstDown
(
requireUnconsumed
=
false
)
val
interaction
=
DragInteraction
.
Start
()
var
posX
=
if
(
isRtl
)
maxPx
-
event
.
position
.
x
else
event
.
position
.
x
val
compare
=
rangeSliderLogic
.
compareOffsets
(
posX
)
var
draggingStart
=
if
(
compare
!=
0
)
{
compare
<
0
}
else
{
rawOffsetStart
.
value
>
posX
}
awaitSlop
(
event
.
id
,
event
.
type
)
?.
let
{
val
slop
=
viewConfiguration
.
pointerSlop
(
event
.
type
)
val
shouldUpdateCapturedThumb
=
abs
(
rawOffsetEnd
.
value
-
posX
)
<
slop
&&
abs
(
rawOffsetStart
.
value
-
posX
)
<
slop
if
(
shouldUpdateCapturedThumb
)
{
val
dir
=
it
.
second
draggingStart
=
if
(
isRtl
)
dir
>=
0f
else
dir
<
0f
posX
+=
it
.
first
.
positionChange
().
x
}
}
rangeSliderLogic
.
captureThumb
(
draggingStart
,
posX
,
interaction
,
this
@coroutineScope
)
val
finishInteraction
=
try
{
val
success
=
horizontalDrag
(
pointerId
=
event
.
id
)
{
val
deltaX
=
it
.
positionChange
().
x
onDrag
.
value
.
invoke
(
draggingStart
,
if
(
isRtl
)
-
deltaX
else
deltaX
)
}
if
(
success
)
{
DragInteraction
.
Stop
(
interaction
)
}
else
{
DragInteraction
.
Cancel
(
interaction
)
}
}
catch
(
e
:
CancellationException
)
{
DragInteraction
.
Cancel
(
interaction
)
}
gestureEndAction
.
value
.
invoke
(
draggingStart
)
launch
{
rangeSliderLogic
.
activeInteraction
(
draggingStart
)
.
emit
(
finishInteraction
)
}
}
}
}
}
else
{
this
}
private
class
RangeSliderLogic
(
val
startInteractionSource
:
MutableInteractionSource
,
val
endInteractionSource
:
MutableInteractionSource
,
val
rawOffsetStart
:
State
<
Float
>,
val
rawOffsetEnd
:
State
<
Float
>,
val
onDrag
:
State
<
(
Boolean
,
Float
)
-
>
Unit
>,
)
{
fun
activeInteraction
(
draggingStart
:
Boolean
):
MutableInteractionSource
=
if
(
draggingStart
)
startInteractionSource
else
endInteractionSource
fun
compareOffsets
(
eventX
:
Float
):
Int
{
val
diffStart
=
abs
(
rawOffsetStart
.
value
-
eventX
)
val
diffEnd
=
abs
(
rawOffsetEnd
.
value
-
eventX
)
return
diffStart
.
compareTo
(
diffEnd
)
}
fun
captureThumb
(
draggingStart
:
Boolean
,
posX
:
Float
,
interaction
:
Interaction
,
scope
:
CoroutineScope
)
{
onDrag
.
value
.
invoke
(
draggingStart
,
posX
-
if
(
draggingStart
)
rawOffsetStart
.
value
else
rawOffsetEnd
.
value
)
scope
.
launch
{
activeInteraction
(
draggingStart
).
emit
(
interaction
)
}
}
}
@Immutable
private
class
DefaultSliderColors
(
private
val
thumbColor
:
Color
,
private
val
disabledThumbColor
:
Color
,
private
val
activeTrackColor
:
Color
,
private
val
inactiveTrackColor
:
Color
,
private
val
disabledActiveTrackColor
:
Color
,
private
val
disabledInactiveTrackColor
:
Color
,
private
val
activeTickColor
:
Color
,
private
val
inactiveTickColor
:
Color
,
private
val
disabledActiveTickColor
:
Color
,
private
val
disabledInactiveTickColor
:
Color
)
:
SliderColors
{
@Composable
override
fun
thumbColor
(
enabled
:
Boolean
):
State
<
Color
>
{
return
rememberUpdatedState
(
if
(
enabled
)
thumbColor
else
disabledThumbColor
)
}
@Composable
override
fun
trackColor
(
enabled
:
Boolean
,
active
:
Boolean
):
State
<
Color
>
{
return
rememberUpdatedState
(
if
(
enabled
)
{
if
(
active
)
activeTrackColor
else
inactiveTrackColor
}
else
{
if
(
active
)
disabledActiveTrackColor
else
disabledInactiveTrackColor
}
)
}
@Composable
override
fun
tickColor
(
enabled
:
Boolean
,
active
:
Boolean
):
State
<
Color
>
{
return
rememberUpdatedState
(
if
(
enabled
)
{
if
(
active
)
activeTickColor
else
inactiveTickColor
}
else
{
if
(
active
)
disabledActiveTickColor
else
disabledInactiveTickColor
}
)
}
override
fun
equals
(
other
:
Any
?):
Boolean
{
if
(
this
===
other
)
return
true
if
(
other
==
null
||
this
::
class
!=
other
::
class
)
return
false
other
as
DefaultSliderColors
if
(
thumbColor
!=
other
.
thumbColor
)
return
false
if
(
disabledThumbColor
!=
other
.
disabledThumbColor
)
return
false
if
(
activeTrackColor
!=
other
.
activeTrackColor
)
return
false
if
(
inactiveTrackColor
!=
other
.
inactiveTrackColor
)
return
false
if
(
disabledActiveTrackColor
!=
other
.
disabledActiveTrackColor
)
return
false
if
(
disabledInactiveTrackColor
!=
other
.
disabledInactiveTrackColor
)
return
false
if
(
activeTickColor
!=
other
.
activeTickColor
)
return
false
if
(
inactiveTickColor
!=
other
.
inactiveTickColor
)
return
false
if
(
disabledActiveTickColor
!=
other
.
disabledActiveTickColor
)
return
false
if
(
disabledInactiveTickColor
!=
other
.
disabledInactiveTickColor
)
return
false
return
true
}
override
fun
hashCode
():
Int
{
var
result
=
thumbColor
.
hashCode
()
result
=
31
*
result
+
disabledThumbColor
.
hashCode
()
result
=
31
*
result
+
activeTrackColor
.
hashCode
()
result
=
31
*
result
+
inactiveTrackColor
.
hashCode
()
result
=
31
*
result
+
disabledActiveTrackColor
.
hashCode
()
result
=
31
*
result
+
disabledInactiveTrackColor
.
hashCode
()
result
=
31
*
result
+
activeTickColor
.
hashCode
()
result
=
31
*
result
+
inactiveTickColor
.
hashCode
()
result
=
31
*
result
+
disabledActiveTickColor
.
hashCode
()
result
=
31
*
result
+
disabledInactiveTickColor
.
hashCode
()
return
result
}
}
// Internal to be referred to in tests
internal
val
ThumbRadius
=
10
.
dp
private
val
ThumbRippleRadius
=
24
.
dp
private
val
ThumbDefaultElevation
=
1
.
dp
private
val
ThumbPressedElevation
=
6
.
dp
// Internal to be referred to in tests
internal
val
TrackHeight
=
4
.
dp
private
val
SliderHeight
=
48
.
dp
private
val
SliderMinWidth
=
144
.
dp
// TODO: clarify min width
private
val
DefaultSliderConstraints
=
Modifier
.
widthIn
(
min
=
SliderMinWidth
)
.
heightIn
(
max
=
SliderHeight
)
private
val
SliderToTickAnimation
=
TweenSpec
<
Float
>(
durationMillis
=
100
)
private
class
SliderDraggableState
(
val
onDelta
:
(
Float
)
->
Unit
)
:
DraggableState
{
var
isDragging
by
mutableStateOf
(
false
)
private
set
private
val
dragScope
:
DragScope
=
object
:
DragScope
{
override
fun
dragBy
(
pixels
:
Float
):
Unit
=
onDelta
(
pixels
)
}
private
val
scrollMutex
=
MutatorMutex
()
override
suspend
fun
drag
(
dragPriority
:
MutatePriority
,
block
:
suspend
DragScope
.()
->
Unit
):
Unit
=
coroutineScope
{
isDragging
=
true
scrollMutex
.
mutateWith
(
dragScope
,
dragPriority
,
block
)
isDragging
=
false
}
override
fun
dispatchRawDelta
(
delta
:
Float
)
{
return
onDelta
(
delta
)
}
}
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/java/androidx/compose/material1/Strings.android.kt
0 → 100644
浏览文件 @
4b7a7868
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
androidx.compose.material1
import
androidx.compose.runtime.Composable
import
androidx.compose.ui.R
import
androidx.compose.ui.platform.LocalConfiguration
import
androidx.compose.ui.platform.LocalContext
@Composable
internal
fun
getString
(
string
:
Strings
):
String
{
LocalConfiguration
.
current
val
resources
=
LocalContext
.
current
.
resources
return
when
(
string
)
{
Strings
.
NavigationMenu
->
resources
.
getString
(
R
.
string
.
navigation_menu
)
Strings
.
CloseDrawer
->
resources
.
getString
(
R
.
string
.
close_drawer
)
Strings
.
CloseSheet
->
resources
.
getString
(
R
.
string
.
close_sheet
)
Strings
.
DefaultErrorMessage
->
resources
.
getString
(
R
.
string
.
default_error_message
)
Strings
.
ExposedDropdownMenu
->
resources
.
getString
(
R
.
string
.
dropdown_menu
)
Strings
.
SliderRangeStart
->
resources
.
getString
(
R
.
string
.
range_start
)
Strings
.
SliderRangeEnd
->
resources
.
getString
(
R
.
string
.
range_end
)
else
->
""
}
}
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/java/androidx/compose/material1/Strings.kt
0 → 100644
浏览文件 @
4b7a7868
/*
* Copyright 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
androidx.compose.material1
import
androidx.compose.runtime.Immutable
@Immutable
@
kotlin
.
jvm
.
JvmInline
internal
value
class
Strings
private
constructor
(
@Suppress
(
"unused"
)
private
val
value
:
Int
)
{
companion
object
{
val
NavigationMenu
=
Strings
(
0
)
val
CloseDrawer
=
Strings
(
1
)
val
CloseSheet
=
Strings
(
2
)
val
DefaultErrorMessage
=
Strings
(
3
)
val
ExposedDropdownMenu
=
Strings
(
4
)
val
SliderRangeStart
=
Strings
(
5
)
val
SliderRangeEnd
=
Strings
(
6
)
}
}
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/MainActivity.kt
0 → 100644
浏览文件 @
4b7a7868
package
com.example.jetpackcompose
import
android.os.Bundle
import
androidx.activity.ComponentActivity
import
androidx.activity.compose.setContent
import
androidx.compose.foundation.layout.*
import
androidx.compose.material1.Slider
import
androidx.compose.material.Text
import
androidx.compose.runtime.*
import
androidx.compose.ui.Alignment
import
androidx.compose.ui.Modifier
import
androidx.compose.ui.tooling.preview.Preview
import
androidx.compose.ui.unit.dp
import
com.example.jetpackcompose.ui.theme.JetpackComposeTheme
class
MainActivity
:
ComponentActivity
()
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
setContent
{
JetpackComposeTheme
{
// A surface container using the 'background' color from the theme
Row
{
var
sliderPosition
by
remember
{
mutableStateOf
(
0f
)
}
repeat
(
4
)
{
Column
(
modifier
=
Modifier
.
weight
(
1f
)
)
{
for
(
i
in
1
..
25
)
{
Slider
(
value
=
sliderPosition
,
modifier
=
Modifier
.
height
(
25
.
dp
),
onValueChange
=
{
sliderPosition
=
it
})
}
}
}
}
}
}
}
}
@Composable
fun
Greeting
(
name
:
String
)
{
Text
(
text
=
"Hello $name!"
)
}
@Preview
(
showBackground
=
true
)
@Composable
fun
DefaultPreview
()
{
JetpackComposeTheme
{
Greeting
(
"Android"
)
}
}
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/ui/theme/Color.kt
0 → 100644
浏览文件 @
4b7a7868
package
com.example.jetpackcompose.ui.theme
import
androidx.compose.ui.graphics.Color
val
Purple200
=
Color
(
0xFFBB86FC
)
val
Purple500
=
Color
(
0xFF6200EE
)
val
Purple700
=
Color
(
0xFF3700B3
)
val
Teal200
=
Color
(
0xFF03DAC5
)
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/ui/theme/Shape.kt
0 → 100644
浏览文件 @
4b7a7868
package
com.example.jetpackcompose.ui.theme
import
androidx.compose.foundation.shape.RoundedCornerShape
import
androidx.compose.material.Shapes
import
androidx.compose.ui.unit.dp
val
Shapes
=
Shapes
(
small
=
RoundedCornerShape
(
4
.
dp
),
medium
=
RoundedCornerShape
(
4
.
dp
),
large
=
RoundedCornerShape
(
0
.
dp
)
)
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/ui/theme/Theme.kt
0 → 100644
浏览文件 @
4b7a7868
package
com.example.jetpackcompose.ui.theme
import
androidx.compose.foundation.isSystemInDarkTheme
import
androidx.compose.material.MaterialTheme
import
androidx.compose.material.darkColors
import
androidx.compose.material.lightColors
import
androidx.compose.runtime.Composable
private
val
DarkColorPalette
=
darkColors
(
primary
=
Purple200
,
primaryVariant
=
Purple700
,
secondary
=
Teal200
)
private
val
LightColorPalette
=
lightColors
(
primary
=
Purple500
,
primaryVariant
=
Purple700
,
secondary
=
Teal200
/* Other default colors to override
background = Color.White,
surface = Color.White,
onPrimary = Color.White,
onSecondary = Color.Black,
onBackground = Color.Black,
onSurface = Color.Black,
*/
)
@Composable
fun
JetpackComposeTheme
(
darkTheme
:
Boolean
=
isSystemInDarkTheme
(),
content
:
@Composable
()
->
Unit
)
{
val
colors
=
if
(
darkTheme
)
{
DarkColorPalette
}
else
{
LightColorPalette
}
MaterialTheme
(
colors
=
colors
,
typography
=
Typography
,
shapes
=
Shapes
,
content
=
content
)
}
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/java/com/example/jetpackcompose/ui/theme/Type.kt
0 → 100644
浏览文件 @
4b7a7868
package
com.example.jetpackcompose.ui.theme
import
androidx.compose.material.Typography
import
androidx.compose.ui.text.TextStyle
import
androidx.compose.ui.text.font.FontFamily
import
androidx.compose.ui.text.font.FontWeight
import
androidx.compose.ui.unit.sp
// Set of Material typography styles to start with
val
Typography
=
Typography
(
body1
=
TextStyle
(
fontFamily
=
FontFamily
.
Default
,
fontWeight
=
FontWeight
.
Normal
,
fontSize
=
16
.
sp
)
/* Other default text styles to override
button = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.W500,
fontSize = 14.sp
),
caption = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 12.sp
)
*/
)
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
0 → 100644
浏览文件 @
4b7a7868
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:aapt=
"http://schemas.android.com/aapt"
android:width=
"108dp"
android:height=
"108dp"
android:viewportWidth=
"108"
android:viewportHeight=
"108"
>
<path
android:pathData=
"M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z"
>
<aapt:attr
name=
"android:fillColor"
>
<gradient
android:endX=
"85.84757"
android:endY=
"92.4963"
android:startX=
"42.9492"
android:startY=
"49.59793"
android:type=
"linear"
>
<item
android:color=
"#44000000"
android:offset=
"0.0"
/>
<item
android:color=
"#00000000"
android:offset=
"1.0"
/>
</gradient>
</aapt:attr>
</path>
<path
android:fillColor=
"#FFFFFF"
android:fillType=
"nonZero"
android:pathData=
"M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth=
"1"
android:strokeColor=
"#00000000"
/>
</vector>
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/res/drawable/ic_launcher_background.xml
0 → 100644
浏览文件 @
4b7a7868
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:width=
"108dp"
android:height=
"108dp"
android:viewportWidth=
"108"
android:viewportHeight=
"108"
>
<path
android:fillColor=
"#3DDC84"
android:pathData=
"M0,0h108v108h-108z"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M9,0L9,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M19,0L19,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M29,0L29,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M39,0L39,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M49,0L49,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M59,0L59,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M69,0L69,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M79,0L79,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M89,0L89,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M99,0L99,108"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,9L108,9"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,19L108,19"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,29L108,29"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,39L108,39"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,49L108,49"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,59L108,59"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,69L108,69"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,79L108,79"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,89L108,89"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M0,99L108,99"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M19,29L89,29"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M19,39L89,39"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M19,49L89,49"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M19,59L89,59"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M19,69L89,69"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M19,79L89,79"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M29,19L29,89"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M39,19L39,89"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M49,19L49,89"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M59,19L59,89"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M69,19L69,89"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
<path
android:fillColor=
"#00000000"
android:pathData=
"M79,19L79,89"
android:strokeWidth=
"0.8"
android:strokeColor=
"#33FFFFFF"
/>
</vector>
test_compose_ui_slider_100/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
0 → 100644
浏览文件 @
4b7a7868
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<background
android:drawable=
"@drawable/ic_launcher_background"
/>
<foreground
android:drawable=
"@drawable/ic_launcher_foreground"
/>
</adaptive-icon>
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
0 → 100644
浏览文件 @
4b7a7868
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon
xmlns:android=
"http://schemas.android.com/apk/res/android"
>
<background
android:drawable=
"@drawable/ic_launcher_background"
/>
<foreground
android:drawable=
"@drawable/ic_launcher_foreground"
/>
</adaptive-icon>
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/res/mipmap-hdpi/ic_launcher.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/mipmap-mdpi/ic_launcher.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/app/src/main/res/values/colors.xml
0 → 100644
浏览文件 @
4b7a7868
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color
name=
"purple_200"
>
#FFBB86FC
</color>
<color
name=
"purple_500"
>
#FF6200EE
</color>
<color
name=
"purple_700"
>
#FF3700B3
</color>
<color
name=
"teal_200"
>
#FF03DAC5
</color>
<color
name=
"teal_700"
>
#FF018786
</color>
<color
name=
"black"
>
#FF000000
</color>
<color
name=
"white"
>
#FFFFFFFF
</color>
</resources>
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/res/values/strings.xml
0 → 100644
浏览文件 @
4b7a7868
<resources>
<string
name=
"app_name"
>
ComposeUISlider100
</string>
</resources>
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/res/values/themes.xml
0 → 100644
浏览文件 @
4b7a7868
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style
name=
"Theme.JetpackCompose"
parent=
"android:Theme.Material.Light.NoActionBar"
>
<item
name=
"android:statusBarColor"
>
@color/purple_700
</item>
</style>
</resources>
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/res/xml/backup_rules.xml
0 → 100644
浏览文件 @
4b7a7868
<?xml version="1.0" encoding="utf-8"?>
<!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>
\ No newline at end of file
test_compose_ui_slider_100/app/src/main/res/xml/data_extraction_rules.xml
0 → 100644
浏览文件 @
4b7a7868
<?xml version="1.0" encoding="utf-8"?>
<!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>
\ No newline at end of file
test_compose_ui_slider_100/app/src/test/java/com/example/jetpackcompose/ExampleUnitTest.kt
0 → 100644
浏览文件 @
4b7a7868
package
com.example.jetpackcompose
import
org.junit.Test
import
org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class
ExampleUnitTest
{
@Test
fun
addition_isCorrect
()
{
assertEquals
(
4
,
2
+
2
)
}
}
\ No newline at end of file
test_compose_ui_slider_100/build.gradle
0 → 100644
浏览文件 @
4b7a7868
buildscript
{
ext
{
compose_ui_version
=
'1.3.2'
agp_version
=
'8.1.0'
}
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins
{
id
'com.android.application'
version
'8.1.0'
apply
false
id
'com.android.library'
version
'7.4.2'
apply
false
id
'org.jetbrains.kotlin.android'
version
'1.8.10'
apply
false
}
\ No newline at end of file
test_compose_ui_slider_100/gradle.properties
0 → 100644
浏览文件 @
4b7a7868
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs
=
-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX
=
true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style
=
official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass
=
true
\ No newline at end of file
test_compose_ui_slider_100/gradle/wrapper/gradle-wrapper.jar
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/gradle/wrapper/gradle-wrapper.properties
0 → 100644
浏览文件 @
4b7a7868
#Fri Jul 28 13:40:34 CST 2023
distributionBase
=
GRADLE_USER_HOME
distributionPath
=
wrapper/dists
distributionUrl
=
https
\:
//services.gradle.org/distributions/gradle-8.2.1-bin.zip
zipStoreBase
=
GRADLE_USER_HOME
zipStorePath
=
wrapper/dists
test_compose_ui_slider_100/gradlew
0 → 100644
浏览文件 @
4b7a7868
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG
=
"
$0
"
# Need this for relative symlinks.
while
[
-h
"
$PRG
"
]
;
do
ls
=
`
ls
-ld
"
$PRG
"
`
link
=
`
expr
"
$ls
"
:
'.*-> \(.*\)$'
`
if
expr
"
$link
"
:
'/.*'
>
/dev/null
;
then
PRG
=
"
$link
"
else
PRG
=
`
dirname
"
$PRG
"
`
"/
$link
"
fi
done
SAVED
=
"
`
pwd
`
"
cd
"
`
dirname
\"
$PRG
\"
`
/"
>
/dev/null
APP_HOME
=
"
`
pwd
-P
`
"
cd
"
$SAVED
"
>
/dev/null
APP_NAME
=
"Gradle"
APP_BASE_NAME
=
`
basename
"
$0
"
`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS
=
'"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD
=
"maximum"
warn
()
{
echo
"
$*
"
}
die
()
{
echo
echo
"
$*
"
echo
exit
1
}
# OS specific support (must be 'true' or 'false').
cygwin
=
false
msys
=
false
darwin
=
false
nonstop
=
false
case
"
`
uname
`
"
in
CYGWIN
*
)
cygwin
=
true
;;
Darwin
*
)
darwin
=
true
;;
MINGW
*
)
msys
=
true
;;
NONSTOP
*
)
nonstop
=
true
;;
esac
CLASSPATH
=
$APP_HOME
/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if
[
-n
"
$JAVA_HOME
"
]
;
then
if
[
-x
"
$JAVA_HOME
/jre/sh/java"
]
;
then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD
=
"
$JAVA_HOME
/jre/sh/java"
else
JAVACMD
=
"
$JAVA_HOME
/bin/java"
fi
if
[
!
-x
"
$JAVACMD
"
]
;
then
die
"ERROR: JAVA_HOME is set to an invalid directory:
$JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD
=
"java"
which java
>
/dev/null 2>&1
||
die
"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if
[
"
$cygwin
"
=
"false"
-a
"
$darwin
"
=
"false"
-a
"
$nonstop
"
=
"false"
]
;
then
MAX_FD_LIMIT
=
`
ulimit
-H
-n
`
if
[
$?
-eq
0
]
;
then
if
[
"
$MAX_FD
"
=
"maximum"
-o
"
$MAX_FD
"
=
"max"
]
;
then
MAX_FD
=
"
$MAX_FD_LIMIT
"
fi
ulimit
-n
$MAX_FD
if
[
$?
-ne
0
]
;
then
warn
"Could not set maximum file descriptor limit:
$MAX_FD
"
fi
else
warn
"Could not query maximum file descriptor limit:
$MAX_FD_LIMIT
"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if
$darwin
;
then
GRADLE_OPTS
=
"
$GRADLE_OPTS
\"
-Xdock:name=
$APP_NAME
\"
\"
-Xdock:icon=
$APP_HOME
/media/gradle.icns
\"
"
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if
[
"
$cygwin
"
=
"true"
-o
"
$msys
"
=
"true"
]
;
then
APP_HOME
=
`
cygpath
--path
--mixed
"
$APP_HOME
"
`
CLASSPATH
=
`
cygpath
--path
--mixed
"
$CLASSPATH
"
`
JAVACMD
=
`
cygpath
--unix
"
$JAVACMD
"
`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW
=
`
find
-L
/
-maxdepth
1
-mindepth
1
-type
d 2>/dev/null
`
SEP
=
""
for
dir
in
$ROOTDIRSRAW
;
do
ROOTDIRS
=
"
$ROOTDIRS$SEP$dir
"
SEP
=
"|"
done
OURCYGPATTERN
=
"(^(
$ROOTDIRS
))"
# Add a user-defined pattern to the cygpath arguments
if
[
"
$GRADLE_CYGPATTERN
"
!=
""
]
;
then
OURCYGPATTERN
=
"
$OURCYGPATTERN
|(
$GRADLE_CYGPATTERN
)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i
=
0
for
arg
in
"
$@
"
;
do
CHECK
=
`
echo
"
$arg
"
|egrep
-c
"
$OURCYGPATTERN
"
-
`
CHECK2
=
`
echo
"
$arg
"
|egrep
-c
"^-"
`
### Determine if an option
if
[
$CHECK
-ne
0
]
&&
[
$CHECK2
-eq
0
]
;
then
### Added a condition
eval
`
echo
args
$i
`
=
`
cygpath
--path
--ignore
--mixed
"
$arg
"
`
else
eval
`
echo
args
$i
`
=
"
\"
$arg
\"
"
fi
i
=
`
expr
$i
+ 1
`
done
case
$i
in
0
)
set
--
;;
1
)
set
--
"
$args0
"
;;
2
)
set
--
"
$args0
"
"
$args1
"
;;
3
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
;;
4
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
;;
5
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
;;
6
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
;;
7
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
"
$args6
"
;;
8
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
"
$args6
"
"
$args7
"
;;
9
)
set
--
"
$args0
"
"
$args1
"
"
$args2
"
"
$args3
"
"
$args4
"
"
$args5
"
"
$args6
"
"
$args7
"
"
$args8
"
;;
esac
fi
# Escape application args
save
()
{
for
i
do
printf
%s
\\
n
"
$i
"
|
sed
"s/'/'
\\\\
''/g;1s/^/'/;
\$
s/
\$
/'
\\\\
/"
;
done
echo
" "
}
APP_ARGS
=
`
save
"
$@
"
`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set
--
$DEFAULT_JVM_OPTS
$JAVA_OPTS
$GRADLE_OPTS
"
\"
-Dorg.gradle.appname=
$APP_BASE_NAME
\"
"
-classpath
"
\"
$CLASSPATH
\"
"
org.gradle.wrapper.GradleWrapperMain
"
$APP_ARGS
"
exec
"
$JAVACMD
"
"
$@
"
test_compose_ui_slider_100/gradlew.bat
0 → 100644
浏览文件 @
4b7a7868
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if
"
%DEBUG%
"
==
""
@echo
off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if
"
%OS%
"
==
"Windows_NT"
setlocal
set
DIRNAME
=
%~dp0
if
"
%DIRNAME%
"
==
""
set
DIRNAME
=
.
set
APP_BASE_NAME
=
%~n0
set
APP_HOME
=
%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for
%%i
in
(
"
%APP_HOME%
"
)
do
set
APP_HOME
=
%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set
DEFAULT_JVM_OPTS
=
"-Xmx64m"
"-Xms64m"
@rem Find java.exe
if
defined
JAVA_HOME
goto
findJavaFromJavaHome
set
JAVA_EXE
=
java
.exe
%JAVA_EXE%
-version
>
NUL
2
>&
1
if
"
%ERRORLEVEL%
"
==
"0"
goto
execute
echo
.
echo
ERROR
:
JAVA_HOME
is
not
set
and
no
'java'
command
could
be
found
in
your
PATH
.
echo
.
echo
Please
set
the
JAVA_HOME
variable
in
your
environment
to
match
the
echo
location
of
your
Java
installation
.
goto
fail
:findJavaFromJavaHome
set
JAVA_HOME
=
%JAVA
_HOME:
"=
%
set JAVA_EXE=
%JAVA_HOME%
/bin/java.exe
if exist "
%JAVA_EXE%
" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory:
%JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=
%APP_HOME%
\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"
%JAVA_EXE%
"
%DEFAULT_JVM_OPTS%
%JAVA_OPTS%
%GRADLE_OPTS%
"
-Dorg
.gradle.appname
=
%APP_BASE_NAME%
" -classpath "
%CLASSPATH%
" org.gradle.wrapper.GradleWrapperMain
%
*
:end
@rem End local scope for the variables with windows NT shell
if "
%ERRORLEVEL%
"=="
0
" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code
!
if not "" == "
%GRADLE_EXIT_CONSOLE%
" exit 1
exit /b 1
:mainEnd
if "
%OS%
"=="
Windows_NT
" endlocal
:omega
test_compose_ui_slider_100/settings.gradle
0 → 100644
浏览文件 @
4b7a7868
pluginManagement
{
repositories
{
gradlePluginPortal
()
google
()
mavenCentral
()
}
}
dependencyResolutionManagement
{
repositoriesMode
.
set
(
RepositoriesMode
.
FAIL_ON_PROJECT_REPOS
)
repositories
{
google
()
mavenCentral
()
}
}
rootProject
.
name
=
"JetpackCompose"
include
':app'
test_compose_ui_slider_100/slider100
0 → 100644
浏览文件 @
4b7a7868
文件已添加
test_compose_ui_slider_100/test_compose_ui_slider_100.apk
0 → 100644
浏览文件 @
4b7a7868
文件已添加
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录