Skip to content

Commit

Permalink
Added Placeholder for Material3 Themes
Browse files Browse the repository at this point in the history
  • Loading branch information
CaptnBlubber committed Sep 4, 2022
1 parent 4d367af commit 9e8315b
Show file tree
Hide file tree
Showing 9 changed files with 345 additions and 0 deletions.
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ coil = "1.3.2"
androidxtest = "1.4.0"
androidxnavigation = "2.5.0-rc02"
androidxWindow = "1.0.0"
material3 = "1.0.0-beta01"

[libraries]
compose-ui-ui = { module = "androidx.compose.ui:ui", version.ref = "compose" }
Expand All @@ -28,6 +29,7 @@ compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest", ve
compose-foundation-foundation = { module = "androidx.compose.foundation:foundation", version.ref = "compose" }
compose-foundation-layout = { module = "androidx.compose.foundation:foundation-layout", version.ref = "compose" }
compose-material-material = { module = "androidx.compose.material:material", version.ref = "compose" }
compose-material-material3 = { module = "androidx.compose.material3:material3", version.ref = "material3" }
compose-material-iconsext = { module = "androidx.compose.material:material-icons-extended", version.ref = "compose" }
compose-animation-animation = { module = "androidx.compose.animation:animation", version.ref = "compose" }

Expand Down
21 changes: 21 additions & 0 deletions placeholder-material3/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Placeholder for Jetpack Compose (Material3)

[![Maven Central](https://img.shields.io/maven-central/v/com.google.accompanist/accompanist-placeholder)](https://search.maven.org/search?q=g:com.google.accompanist)

For more information, visit the documentation: https://google.github.io/accompanist/placeholder

## Download

```groovy
repositories {
mavenCentral()
}
dependencies {
implementation "com.google.accompanist:accompanist-placeholder-material3:<version>"
}
```

Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap]. These are updated on every commit.

[snap]: https://oss.sonatype.org/content/repositories/snapshots/com/google/accompanist/accompanist-placeholder-material3/
17 changes: 17 additions & 0 deletions placeholder-material3/api/current.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Signature format: 4.0
package com.google.accompanist.placeholder.material3 {

public final class PlaceholderHighlightKt {
method @androidx.compose.runtime.Composable public static com.google.accompanist.placeholder.PlaceholderHighlight fade(com.google.accompanist.placeholder.PlaceholderHighlight.Companion, optional androidx.compose.animation.core.InfiniteRepeatableSpec<java.lang.Float> animationSpec);
method @androidx.compose.runtime.Composable public static com.google.accompanist.placeholder.PlaceholderHighlight shimmer(com.google.accompanist.placeholder.PlaceholderHighlight.Companion, optional androidx.compose.animation.core.InfiniteRepeatableSpec<java.lang.Float> animationSpec, optional @FloatRange(from=0.0, to=1.0) float progressForMaxAlpha);
}

public final class PlaceholderKt {
method @androidx.compose.runtime.Composable public static long color(com.google.accompanist.placeholder.PlaceholderDefaults, optional long backgroundColor, optional long contentColor, optional float contentAlpha);
method @androidx.compose.runtime.Composable public static long fadeHighlightColor(com.google.accompanist.placeholder.PlaceholderDefaults, optional long backgroundColor, optional float alpha);
method public static androidx.compose.ui.Modifier placeholder(androidx.compose.ui.Modifier, boolean visible, optional long color, optional androidx.compose.ui.graphics.Shape? shape, optional com.google.accompanist.placeholder.PlaceholderHighlight? highlight, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.core.Transition.Segment<java.lang.Boolean>,? extends androidx.compose.animation.core.FiniteAnimationSpec<java.lang.Float>> placeholderFadeTransitionSpec, optional kotlin.jvm.functions.Function1<? super androidx.compose.animation.core.Transition.Segment<java.lang.Boolean>,? extends androidx.compose.animation.core.FiniteAnimationSpec<java.lang.Float>> contentFadeTransitionSpec);
method @androidx.compose.runtime.Composable public static long shimmerHighlightColor(com.google.accompanist.placeholder.PlaceholderDefaults, optional long backgroundColor, optional float alpha);
}

}

95 changes: 95 additions & 0 deletions placeholder-material3/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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
*
* 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.
*/

plugins {
id 'com.android.library'
id 'kotlin-android'
id 'org.jetbrains.dokka'
}

kotlin {
explicitApi()
}

android {
compileSdkVersion 33

defaultConfig {
minSdkVersion 21
// targetSdkVersion has no effect for libraries. This is only used for the test APK
targetSdkVersion 33
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

buildFeatures {
buildConfig false
compose true
}

composeOptions {
kotlinCompilerExtensionVersion libs.versions.composeCompiler.get()
}

lintOptions {
textReport true
textOutput 'stdout'
// We run a full lint analysis as build part in CI, so skip vital checks for assemble tasks
checkReleaseBuilds false
}

packagingOptions {
// Some of the META-INF files conflict with coroutines-test. Exclude them to enable
// our test APK to build (has no effect on our AARs)
excludes += "/META-INF/AL2.0"
excludes += "/META-INF/LGPL2.1"
}

testOptions {
unitTests {
includeAndroidResources = true
}
animationsDisabled true
}
}

dependencies {
implementation libs.compose.material.material3
api project(':placeholder')
implementation libs.napier
implementation libs.kotlin.coroutines.android

// ======================
// Test dependencies
// ======================

androidTestImplementation libs.junit
androidTestImplementation libs.truth

androidTestImplementation libs.compose.ui.test.junit4
androidTestImplementation libs.compose.ui.test.manifest
androidTestImplementation libs.compose.foundation.foundation

androidTestImplementation libs.androidx.test.core
androidTestImplementation libs.androidx.test.rules
androidTestImplementation libs.androidx.test.runner
}

apply plugin: "com.vanniktech.maven.publish"
3 changes: 3 additions & 0 deletions placeholder-material3/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
POM_ARTIFACT_ID=accompanist-placeholder-material3
POM_NAME=Accompanist Placeholder Material3
POM_PACKAGING=aar
18 changes: 18 additions & 0 deletions placeholder-material3/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!--
~ 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
~
~ 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.
-->

<manifest package="com.google.accompanist.placeholder.material3">
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* Copyright 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
*
* 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.
*/

package com.google.accompanist.placeholder.material3

import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.spring
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.graphics.isSpecified
import com.google.accompanist.placeholder.PlaceholderDefaults
import com.google.accompanist.placeholder.PlaceholderHighlight
import com.google.accompanist.placeholder.placeholder

/**
* Returns the value used as the the `color` parameter value on [Modifier.placeholder].
*
* @param backgroundColor The current background color of the layout. Defaults to
* `MaterialTheme.colorScheme.surface`.
* @param contentColor The content color to be used on top of [backgroundColor].
* @param contentAlpha The alpha component to set on [contentColor] when compositing the color
* on top of [backgroundColor]. Defaults to `0.1f`.
*/
@Composable
fun PlaceholderDefaults.color(
backgroundColor: Color = MaterialTheme.colorScheme.surface,
contentColor: Color = contentColorFor(backgroundColor),
contentAlpha: Float = 0.1f,
): Color = contentColor.copy(contentAlpha).compositeOver(backgroundColor)

/**
* Returns the value used as the the `highlightColor` parameter value of
* [PlaceholderHighlight.Companion.fade].
*
* @param backgroundColor The current background color of the layout. Defaults to
* `MaterialTheme.colorScheme.surface`.
* @param alpha The alpha component to set on [backgroundColor]. Defaults to `0.3f`.
*/
@Composable
fun PlaceholderDefaults.fadeHighlightColor(
backgroundColor: Color = MaterialTheme.colorScheme.surface,
alpha: Float = 0.3f,
): Color = backgroundColor.copy(alpha = alpha)

/**
* Returns the value used as the the `highlightColor` parameter value of
* [PlaceholderHighlight.Companion.shimmer].
*
* @param backgroundColor The current background color of the layout. Defaults to
* `MaterialTheme.colorScheme.inverseSurface`.
* @param alpha The alpha component to set on [backgroundColor]. Defaults to `0.75f`.
*/
@Composable
fun PlaceholderDefaults.shimmerHighlightColor(
backgroundColor: Color = MaterialTheme.colorScheme.inverseSurface,
alpha: Float = 0.75f,
): Color {
return backgroundColor.copy(alpha = alpha)
}

/**
* Draws some skeleton UI which is typically used whilst content is 'loading'.
*
* To customize the color and shape of the placeholder, you can use the foundation version of
* [Modifier.placeholder], along with the values provided by [PlaceholderDefaults].
*
* A cross-fade transition will be applied to the content and placeholder UI when the [visible]
* value changes. The transition can be customized via the [contentFadeTransitionSpec] and
* [placeholderFadeTransitionSpec] parameters.
*
* You can provide a [PlaceholderHighlight] which runs an highlight animation on the placeholder.
* The [shimmer] and [fade] implementations are provided for easy usage.
*
* You can find more information on the pattern at the Material Theming
* [Placeholder UI](https://material.io/design/communication/launch-screen.html#placeholder-ui)
* guidelines.
*
* @param visible whether the placeholder should be visible or not.
* @param color the color used to draw the placeholder UI. If [Color.Unspecified] is provided,
* the placeholder will use [PlaceholderDefaults.color].
* @param shape desired shape of the placeholder. If null is provided the placeholder
* will use the small shape set in [MaterialTheme.shapes].
* @param highlight optional highlight animation.
* @param placeholderFadeTransitionSpec The transition spec to use when fading the placeholder
* on/off screen. The boolean parameter defined for the transition is [visible].
* @param contentFadeTransitionSpec The transition spec to use when fading the content
* on/off screen. The boolean parameter defined for the transition is [visible].
*/
fun Modifier.placeholder(
visible: Boolean,
color: Color = Color.Unspecified,
shape: Shape? = null,
highlight: PlaceholderHighlight? = null,
placeholderFadeTransitionSpec: @Composable Transition.Segment<Boolean>.() -> FiniteAnimationSpec<Float> = { spring() },
contentFadeTransitionSpec: @Composable Transition.Segment<Boolean>.() -> FiniteAnimationSpec<Float> = { spring() },
): Modifier = composed {
Modifier.placeholder(
visible = visible,
color = if (color.isSpecified) color else PlaceholderDefaults.color(),
shape = shape ?: MaterialTheme.shapes.small,
highlight = highlight,
placeholderFadeTransitionSpec = placeholderFadeTransitionSpec,
contentFadeTransitionSpec = contentFadeTransitionSpec,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 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
*
* 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.
*/

package com.google.accompanist.placeholder.material3

import androidx.annotation.FloatRange
import androidx.compose.animation.core.AnimationSpec
import androidx.compose.animation.core.InfiniteRepeatableSpec
import androidx.compose.runtime.Composable
import com.google.accompanist.placeholder.PlaceholderDefaults
import com.google.accompanist.placeholder.PlaceholderHighlight
import com.google.accompanist.placeholder.fade
import com.google.accompanist.placeholder.material3.fadeHighlightColor
import com.google.accompanist.placeholder.material3.shimmerHighlightColor
import com.google.accompanist.placeholder.shimmer

/**
* Creates a [PlaceholderHighlight] which fades in an appropriate color, using the
* given [animationSpec].
*
* @param animationSpec the [AnimationSpec] to configure the animation.
*/
@Composable
fun PlaceholderHighlight.Companion.fade(
animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.fadeAnimationSpec,
): PlaceholderHighlight = PlaceholderHighlight.fade(
highlightColor = PlaceholderDefaults.fadeHighlightColor(),
animationSpec = animationSpec,
)

/**
* Creates a [PlaceholderHighlight] which 'shimmers', using a default color.
*
* The highlight starts at the top-start, and then grows to the bottom-end during the animation.
* During that time it is also faded in, from 0f..progressForMaxAlpha, and then faded out from
* progressForMaxAlpha..1f.
*
* @param animationSpec the [AnimationSpec] to configure the animation.
* @param progressForMaxAlpha The progress where the shimmer should be at it's peak opacity.
* Defaults to 0.6f.
*/
@Composable
fun PlaceholderHighlight.Companion.shimmer(
animationSpec: InfiniteRepeatableSpec<Float> = PlaceholderDefaults.shimmerAnimationSpec,
@FloatRange(from = 0.0, to = 1.0) progressForMaxAlpha: Float = 0.6f,
): PlaceholderHighlight = PlaceholderHighlight.shimmer(
highlightColor = PlaceholderDefaults.shimmerHighlightColor(),
animationSpec = animationSpec,
progressForMaxAlpha = progressForMaxAlpha,
)
1 change: 1 addition & 0 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ include ':permissions'
include ':permissions-lint'
include ':placeholder'
include ':placeholder-material'
include ':placeholder-material3'
include ':flowlayout'
include ':systemuicontroller'
include ':swiperefresh'
Expand Down

0 comments on commit 9e8315b

Please sign in to comment.