Add ProgressBar and LoadingBar widgets to SPA and create gallery samples
for them. The loading bar is indeterminate, and expresses the loading status or waiting time. The progress bar is reflecting the progress of a process, and need a progress fraction input. Test: Unit test and manually test on device Bug: 254364764 Change-Id: I7faf20beab1e46c5c9d4a9ab07a916a7f506412c
This commit is contained in:
@@ -25,6 +25,7 @@ import com.android.settingslib.spa.gallery.home.HomePageProvider
|
||||
import com.android.settingslib.spa.gallery.page.ArgumentPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.FooterPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.IllustrationPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.ProgressBarPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.SliderPageProvider
|
||||
import com.android.settingslib.spa.gallery.preference.MainSwitchPreferencePageProvider
|
||||
@@ -66,6 +67,7 @@ object GallerySpaEnvironment : SpaEnvironment() {
|
||||
IllustrationPageProvider,
|
||||
CategoryPageProvider,
|
||||
ActionButtonPageProvider,
|
||||
ProgressBarPageProvider,
|
||||
),
|
||||
rootPages = listOf(
|
||||
HomePageProvider.createSettingsPage(),
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.android.settingslib.spa.gallery.page.ArgumentPageModel
|
||||
import com.android.settingslib.spa.gallery.page.ArgumentPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.FooterPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.IllustrationPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.ProgressBarPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.SettingsPagerPageProvider
|
||||
import com.android.settingslib.spa.gallery.page.SliderPageProvider
|
||||
import com.android.settingslib.spa.gallery.preference.PreferenceMainPageProvider
|
||||
@@ -54,6 +55,7 @@ object HomePageProvider : SettingsPageProvider {
|
||||
IllustrationPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
|
||||
CategoryPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
|
||||
ActionButtonPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
|
||||
ProgressBarPageProvider.buildInjectEntry().setLink(fromPage = owner).build(),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 com.android.settingslib.spa.gallery.page
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material.icons.outlined.SystemUpdate
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.android.settingslib.spa.framework.common.SettingsEntryBuilder
|
||||
import com.android.settingslib.spa.framework.common.SettingsPage
|
||||
import com.android.settingslib.spa.framework.common.SettingsPageProvider
|
||||
import com.android.settingslib.spa.framework.compose.navigator
|
||||
import com.android.settingslib.spa.framework.theme.SettingsTheme
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import com.android.settingslib.spa.widget.preference.ProgressBarPreference
|
||||
import com.android.settingslib.spa.widget.preference.ProgressBarPreferenceModel
|
||||
import com.android.settingslib.spa.widget.preference.ProgressBarWithDataPreference
|
||||
import com.android.settingslib.spa.widget.scaffold.RegularScaffold
|
||||
import com.android.settingslib.spa.widget.ui.CircularLoadingBar
|
||||
import com.android.settingslib.spa.widget.ui.CircularProgressBar
|
||||
import com.android.settingslib.spa.widget.ui.LinearLoadingBar
|
||||
import kotlinx.coroutines.delay
|
||||
|
||||
private const val TITLE = "Sample ProgressBar"
|
||||
|
||||
object ProgressBarPageProvider : SettingsPageProvider {
|
||||
override val name = "ProgressBar"
|
||||
|
||||
fun buildInjectEntry(): SettingsEntryBuilder {
|
||||
return SettingsEntryBuilder.createInject(owner = SettingsPage.create(name))
|
||||
.setIsAllowSearch(true)
|
||||
.setUiLayoutFn {
|
||||
Preference(object : PreferenceModel {
|
||||
override val title = TITLE
|
||||
override val onClick = navigator(name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun Page(arguments: Bundle?) {
|
||||
// Mocks a loading time of 2 seconds.
|
||||
var loading by remember { mutableStateOf(true) }
|
||||
LaunchedEffect(Unit) {
|
||||
delay(2000)
|
||||
loading = false
|
||||
}
|
||||
|
||||
RegularScaffold(title = TITLE) {
|
||||
// Auto update the progress and finally jump tp 0.4f.
|
||||
var progress by remember { mutableStateOf(0f) }
|
||||
LaunchedEffect(Unit) {
|
||||
delay(2000)
|
||||
while (progress < 1f) {
|
||||
delay(100)
|
||||
progress += 0.01f
|
||||
}
|
||||
delay(500)
|
||||
progress = 0.4f
|
||||
}
|
||||
|
||||
// Show as a placeholder for progress bar
|
||||
LargeProgressBar(progress)
|
||||
// The remaining information only shows after loading complete.
|
||||
if (!loading) {
|
||||
SimpleProgressBar()
|
||||
ProgressBarWithData()
|
||||
CircularProgressBar(progress = progress, radius = 160f)
|
||||
}
|
||||
}
|
||||
|
||||
// Add loading bar examples, running for 2 seconds.
|
||||
LinearLoadingBar(isLoading = loading, yOffset = 64.dp)
|
||||
CircularLoadingBar(isLoading = loading)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LargeProgressBar(progress: Float) {
|
||||
ProgressBarPreference(object : ProgressBarPreferenceModel {
|
||||
override val title = "Large Progress Bar"
|
||||
override val progress = progress
|
||||
override val height = 20f
|
||||
})
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SimpleProgressBar() {
|
||||
ProgressBarPreference(object : ProgressBarPreferenceModel {
|
||||
override val title = "Simple Progress Bar"
|
||||
override val progress = 0.2f
|
||||
override val icon = Icons.Outlined.SystemUpdate
|
||||
})
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ProgressBarWithData() {
|
||||
ProgressBarWithDataPreference(model = object : ProgressBarPreferenceModel {
|
||||
override val title = "Progress Bar with Data"
|
||||
override val progress = 0.2f
|
||||
override val icon = Icons.Outlined.Delete
|
||||
}, data = "25G")
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
private fun ProgressBarPagePreview() {
|
||||
SettingsTheme {
|
||||
ProgressBarPageProvider.Page(null)
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ internal fun BaseLayout(
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BaseIcon(
|
||||
internal fun BaseIcon(
|
||||
icon: @Composable (() -> Unit)?,
|
||||
modifier: Modifier,
|
||||
paddingStart: Dp,
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 com.android.settingslib.spa.widget.preference
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import com.android.settingslib.spa.framework.theme.SettingsDimension
|
||||
import com.android.settingslib.spa.widget.ui.LinearProgressBar
|
||||
import com.android.settingslib.spa.widget.ui.SettingsTitle
|
||||
|
||||
/**
|
||||
* The widget model for [ProgressBarPreference] widget.
|
||||
*/
|
||||
interface ProgressBarPreferenceModel {
|
||||
/**
|
||||
* The title of this [ProgressBarPreference].
|
||||
*/
|
||||
val title: String
|
||||
|
||||
/**
|
||||
* The progress fraction of the ProgressBar. Should be float in range [0f, 1f]
|
||||
*/
|
||||
val progress: Float
|
||||
|
||||
/**
|
||||
* The icon image for [ProgressBarPreference]. If not specified, hides the icon by default.
|
||||
*/
|
||||
val icon: ImageVector?
|
||||
get() = null
|
||||
|
||||
/**
|
||||
* The height of the ProgressBar.
|
||||
*/
|
||||
val height: Float
|
||||
get() = 4f
|
||||
|
||||
/**
|
||||
* Indicates whether to use rounded corner for the progress bars.
|
||||
*/
|
||||
val roundedCorner: Boolean
|
||||
get() = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Progress bar preference widget.
|
||||
*
|
||||
* Data is provided through [ProgressBarPreferenceModel].
|
||||
*/
|
||||
@Composable
|
||||
fun ProgressBarPreference(model: ProgressBarPreferenceModel) {
|
||||
ProgressBarPreference(
|
||||
title = model.title,
|
||||
progress = model.progress,
|
||||
icon = model.icon,
|
||||
height = model.height,
|
||||
roundedCorner = model.roundedCorner,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Progress bar with data preference widget.
|
||||
*/
|
||||
@Composable
|
||||
fun ProgressBarWithDataPreference(model: ProgressBarPreferenceModel, data: String) {
|
||||
val icon = model.icon
|
||||
ProgressBarWithDataPreference(
|
||||
title = model.title,
|
||||
data = data,
|
||||
progress = model.progress,
|
||||
icon = if (icon != null) ({
|
||||
Icon(imageVector = icon, contentDescription = null)
|
||||
}) else null,
|
||||
height = model.height,
|
||||
roundedCorner = model.roundedCorner,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun ProgressBarPreference(
|
||||
title: String,
|
||||
progress: Float,
|
||||
icon: ImageVector? = null,
|
||||
height: Float = 4f,
|
||||
roundedCorner: Boolean = true,
|
||||
) {
|
||||
BaseLayout(
|
||||
title = title,
|
||||
subTitle = {
|
||||
LinearProgressBar(progress, height, roundedCorner)
|
||||
},
|
||||
icon = if (icon != null) ({
|
||||
Icon(imageVector = icon, contentDescription = null)
|
||||
}) else null,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
internal fun ProgressBarWithDataPreference(
|
||||
title: String,
|
||||
data: String,
|
||||
progress: Float,
|
||||
icon: (@Composable () -> Unit)? = null,
|
||||
height: Float = 4f,
|
||||
roundedCorner: Boolean = true,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(end = SettingsDimension.itemPaddingEnd),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
BaseIcon(icon, Modifier, SettingsDimension.itemPaddingStart)
|
||||
TitleWithData(
|
||||
title = title,
|
||||
data = data,
|
||||
subTitle = {
|
||||
LinearProgressBar(progress, height, roundedCorner)
|
||||
},
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(vertical = SettingsDimension.itemPaddingVertical),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TitleWithData(
|
||||
title: String,
|
||||
data: String,
|
||||
subTitle: @Composable () -> Unit,
|
||||
modifier: Modifier
|
||||
) {
|
||||
Column(modifier) {
|
||||
Row {
|
||||
Box(modifier = Modifier.weight(1f)) {
|
||||
SettingsTitle(title)
|
||||
}
|
||||
Text(
|
||||
text = data,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
)
|
||||
}
|
||||
subTitle()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 com.android.settingslib.spa.widget.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.absoluteOffset
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* Indeterminate linear progress bar. Expresses an unspecified wait time.
|
||||
*/
|
||||
@Composable
|
||||
fun LinearLoadingBar(
|
||||
isLoading: Boolean,
|
||||
xOffset: Dp = 0.dp,
|
||||
yOffset: Dp = 0.dp
|
||||
) {
|
||||
if (isLoading) {
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.absoluteOffset(xOffset, yOffset)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indeterminate circular progress bar. Expresses an unspecified wait time.
|
||||
*/
|
||||
@Composable
|
||||
fun CircularLoadingBar(isLoading: Boolean) {
|
||||
if (isLoading) {
|
||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
CircularProgressIndicator()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 com.android.settingslib.spa.widget.ui
|
||||
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.progressSemantics
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.CornerRadius
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* Determinate linear progress bar. Displays the current progress of the whole process.
|
||||
*
|
||||
* Rounded corner is supported and enabled by default.
|
||||
*/
|
||||
@Composable
|
||||
fun LinearProgressBar(
|
||||
progress: Float,
|
||||
height: Float = 4f,
|
||||
roundedCorner: Boolean = true
|
||||
) {
|
||||
Box(modifier = Modifier.padding(top = 8.dp, bottom = 8.dp)) {
|
||||
val color = MaterialTheme.colorScheme.onSurface
|
||||
val trackColor = MaterialTheme.colorScheme.surfaceVariant
|
||||
Canvas(
|
||||
Modifier
|
||||
.progressSemantics(progress)
|
||||
.fillMaxWidth()
|
||||
.height(height.dp)
|
||||
) {
|
||||
drawLinearBarTrack(trackColor, roundedCorner)
|
||||
drawLinearBar(progress, color, roundedCorner)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun DrawScope.drawLinearBar(
|
||||
endFraction: Float,
|
||||
color: Color,
|
||||
roundedCorner: Boolean
|
||||
) {
|
||||
val width = endFraction * size.width
|
||||
drawRoundRect(
|
||||
color = color,
|
||||
size = Size(width, size.height),
|
||||
cornerRadius = if (roundedCorner) CornerRadius(
|
||||
size.height / 2,
|
||||
size.height / 2
|
||||
) else CornerRadius.Zero,
|
||||
)
|
||||
}
|
||||
|
||||
private fun DrawScope.drawLinearBarTrack(
|
||||
color: Color,
|
||||
roundedCorner: Boolean
|
||||
) = drawLinearBar(1f, color, roundedCorner)
|
||||
|
||||
/**
|
||||
* Determinate circular progress bar. Displays the current progress of the whole process.
|
||||
*
|
||||
* Displayed in default material3 style, and rounded corner is not supported.
|
||||
*/
|
||||
@Composable
|
||||
fun CircularProgressBar(progress: Float, radius: Float = 40f) {
|
||||
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
|
||||
CircularProgressIndicator(
|
||||
progress = progress,
|
||||
modifier = Modifier.size(radius.dp, radius.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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 com.android.settingslib.spa.widget.preference
|
||||
|
||||
import androidx.compose.ui.semantics.ProgressBarRangeInfo
|
||||
import androidx.compose.ui.semantics.SemanticsProperties.ProgressBarRangeInfo
|
||||
import androidx.compose.ui.test.SemanticsMatcher
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ProgressBarPreferenceTest {
|
||||
@get:Rule
|
||||
val composeTestRule = createComposeRule()
|
||||
|
||||
@Test
|
||||
fun title_displayed() {
|
||||
composeTestRule.setContent {
|
||||
ProgressBarPreference(object : ProgressBarPreferenceModel {
|
||||
override val title = "Title"
|
||||
override val progress = 0.2f
|
||||
})
|
||||
}
|
||||
composeTestRule.onNodeWithText("Title").assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun data_displayed() {
|
||||
composeTestRule.setContent {
|
||||
ProgressBarWithDataPreference(model = object : ProgressBarPreferenceModel {
|
||||
override val title = "Title"
|
||||
override val progress = 0.2f
|
||||
}, data = "Data")
|
||||
}
|
||||
composeTestRule.onNodeWithText("Title").assertIsDisplayed()
|
||||
composeTestRule.onNodeWithText("Data").assertIsDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun progressBar_displayed() {
|
||||
composeTestRule.setContent {
|
||||
ProgressBarPreference(object : ProgressBarPreferenceModel {
|
||||
override val title = "Title"
|
||||
override val progress = 0.2f
|
||||
})
|
||||
}
|
||||
|
||||
fun progressEqualsTo(progress: Float): SemanticsMatcher =
|
||||
SemanticsMatcher.expectValue(
|
||||
ProgressBarRangeInfo,
|
||||
ProgressBarRangeInfo(progress, 0f..1f, 0)
|
||||
)
|
||||
composeTestRule.onNode(progressEqualsTo(0.2f)).assertIsDisplayed()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user