Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Placeholder] Added M3 Theme Support #1321

Merged
merged 2 commits into from
Jan 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}

}

97 changes: 97 additions & 0 deletions placeholder-material3/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* 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 {
namespace "com.google.accompanist.placeholder.material3"

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.material3.material3
api project(':placeholder')
CaptnBlubber marked this conversation as resolved.
Show resolved Hide resolved
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
20 changes: 20 additions & 0 deletions placeholder-material3/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!--
~ 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.
-->

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-sdk android:minSdkVersion="21" tools:ignore="GradleOverrides" />
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* 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.
*
* @sample com.google.accompanist.sample.placeholder.DocSample_Material_Placeholder
*
* @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,65 @@
/*
* 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.shimmer

/**
* Creates a [PlaceholderHighlight] which fades in an appropriate color, using the
* given [animationSpec].
*
* @sample com.google.accompanist.sample.placeholder.DocSample_Material_PlaceholderFade
*
* @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.
*
* @sample com.google.accompanist.sample.placeholder.DocSample_Material_PlaceholderShimmer
*
* @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