Skip to content

Commit

Permalink
Insets library (#131)
Browse files Browse the repository at this point in the history
* Add Insetter skeleton project

* Import goo.gle/compose-insets

* Split out Padding and Size modifiers

* Add some rough docs

* Rename library to Insets

* Simplify size modifier structure

* Fix sample after removing AppCompat

* Simplify Sample activity creation

* Add insets basic sample

* Move to DisposableEffect

* Move Insets.toPaddingValues to Padding.kt

* Add comment InsetsSizeModifier

* Fix code style

* More docs

* Add very basic tests

* Add edge-to-edge lazy list sample

* Link to new sample

* Fix API

* Expand README for insets

* Update Edge to Edge sample to use translucent app bar

* Tweak website generation for insets

* Update insets/README.md

Co-authored-by: Nick Butcher <nickbutcher@users.noreply.github.com>

Co-authored-by: Nick Butcher <nickbutcher@users.noreply.github.com>
  • Loading branch information
chrisbanes and nickbutcher committed Oct 30, 2020
1 parent 1ff905b commit 7329268
Show file tree
Hide file tree
Showing 35 changed files with 1,466 additions and 155 deletions.
11 changes: 8 additions & 3 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 12 additions & 3 deletions README.md
Expand Up @@ -2,9 +2,18 @@

Accompanist is a group of libraries that contains some utilities which I've found myself copying around projects which use [Jetpack Compose][compose]. Currently, it contains:

- 🖼️ [Coil image loading composables](./coil/README.md)
- 🖼️ [Picasso image loading composables](./picasso/README.md)
- 🖼️ [Glide image loading composables](./glide/README.md)
### Image loading
A number of libraries which integrate popular image loading libraries into Jetpack Compose:

- 🖼️ [Coil image loading composables](./coil/)
- 🖼️ [Picasso image loading composables](./picasso/)
- 🖼️ [Glide image loading composables](./glide/)

### 📐 [Insets](./insets/)
A library which brings [WindowInsets](https://developer.android.com/reference/kotlin/android/view/WindowInsets) support to Jetpack Compose.


---

[Jetpack Compose][compose] is a fast-moving project and I'll be updating these libraries to match the
latest tagged release as quickly as possible. Each [release listing](https://github.com/chrisbanes/accompanist/releases) will outline what version of Compose libraries it depends on.
Expand Down
Expand Up @@ -85,7 +85,7 @@ object Libs {
const val core = "androidx.core:core:1.2.0"
const val coreKtx = "androidx.core:core-ktx:1.2.0"

const val appcompat = "androidx.appcompat:appcompat:1.3.0-alpha02"
const val coreAlpha = "androidx.core:core:1.5.0-alpha04"
}

object Coil {
Expand Down
21 changes: 10 additions & 11 deletions generate_docs.sh
Expand Up @@ -25,28 +25,27 @@ cp CONTRIBUTING.md $DOCS_ROOT/contributing.md
cp images/social.png $DOCS_ROOT/header.png

sed -i.bak 's/CONTRIBUTING.md/contributing/' $DOCS_ROOT/index.md
sed -i.bak 's/coil\/README.md/glide/' $DOCS_ROOT/index.md
sed -i.bak 's/glide\/README.md/coil/' $DOCS_ROOT/index.md
sed -i.bak 's/picasso\/README.md/picasso/' $DOCS_ROOT/index.md
sed -i.bak 's/README.md//' $DOCS_ROOT/index.md
sed -i.bak 's/images\/social.png/header.png/' $DOCS_ROOT/index.md

# Convert docs/xxx.md links to just xxx/
sed -i.bak 's/docs\/\([a-zA-Z-]*\).md/\1/' $DOCS_ROOT/index.md

cp coil/README.md $DOCS_ROOT/coil.md
mkdir -p $DOCS_ROOT/coil
cp coil/images/crossfade.gif $DOCS_ROOT/coil/crossfade.gif
sed -i.bak 's/images\/crossfade.gif/crossfade.gif/' $DOCS_ROOT/coil.md
cp -r coil/images $DOCS_ROOT/coil

cp picasso/README.md $DOCS_ROOT/picasso.md
mkdir -p $DOCS_ROOT/picasso
cp picasso/images/crossfade.gif $DOCS_ROOT/picasso/crossfade.gif
sed -i.bak 's/images\/crossfade.gif/crossfade.gif/' $DOCS_ROOT/picasso.md
cp -r picasso/images $DOCS_ROOT/picasso

cp glide/README.md $DOCS_ROOT/glide.md
mkdir -p $DOCS_ROOT/glide
cp glide/images/crossfade.gif $DOCS_ROOT/glide/crossfade.gif
sed -i.bak 's/images\/crossfade.gif/crossfade.gif/' $DOCS_ROOT/glide.md
cp -r glide/images $DOCS_ROOT/glide

# Convert docs/xxx.md links to just xxx/
sed -i.bak 's/docs\/\([a-zA-Z-]*\).md/\1/' $DOCS_ROOT/index.md
cp insets/README.md $DOCS_ROOT/insets.md
mkdir -p $DOCS_ROOT/insets
cp -r insets/images $DOCS_ROOT/insets

#########################
# Tidy up Dokka output
Expand Down
119 changes: 119 additions & 0 deletions insets/README.md
@@ -0,0 +1,119 @@
# Insets for Jetpack Compose

[![Maven Central](https://maven-badges.herokuapp.com/maven-central/dev.chrisbanes.accompanist/accompanist-insets/badge.svg)](https://search.maven.org/search?q=g:dev.chrisbanes.accompanist)

Insets for Jetpack Compose takes a lot of the ideas which drove [Insetter][insetter-view] for views, and applies them for use in composables.

## Usage
To setup Insets in your composables, you need to call the `ProvideWindowInsets` function and
wrap your content. This would typically be done near the top level of your composable hierarchy:

``` kotlin
setContent {
MaterialTheme {
ProvideWindowInsets {
// your content
}
}
}
```

> Note: Whether `ProvideWindowInsets` is called outside or within `MaterialTheme` doesn't particularly matter.
`ProvideWindowInsets` allows the library to set an [`OnApplyWindowInsetsListener`][insetslistener] on your content's host view. That listener is used to update the value of an ambient bundled in this library: `AmbientWindowInsets`.

`AmbientWindowInsets` holds an instance of `WindowInsets` which contains the value of various [WindowInsets][insets] [types][insettypes]. You can use the values manually like so:

``` kotlin
@Composable
fun ImeAvoidingBox() {
val insets = AmbientWindowInsets.current

Box(Modifier.padding(bottom = insets.ime.bottom))
}
```

...but we also provide some easy-to-use [Modifier][modifier]s.

### Modifiers

We provide two types of modifiers for easy handling of insets: padding and size.

#### Padding modifiers
The padding modifiers allow you to apply padding to a composable which matches a specific type of inset. Currently we provide:

- `Modifier.statusBarsPadding()`
- `Modifier.navigationBarsPadding()`
- `Modifier.systemBarsPadding()`

These are commonly used to move composables out from under the system bars. The common example would be a [`FloatingActionButton`][fab]:

``` kotlin
FloatingActionButton(
icon = { Icon(...) },
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(16.dp) // normal 16dp of padding for FABs
.navigationBarsPadding() // Move it out from under the nav bar
)
```

#### Size modifiers
The size modifiers allow you to match the size of a composable to a specific type of inset. Currently we provide:

- `Modifier.statusBarsHeight()`
- `Modifier.navigationBarsHeight()`
- `Modifier.navigationBarsWidth()`

These are commonly used to allow composables behind the system bars, to provide background protection, or similar:

``` kotlin
Spacer(
Modifier
.background(Color.Black.copy(alpha = 0.7f))
.statusBarsHeight() // Match the height of the status bar
.fillMaxWidth()
)
```

### PaddingValues
Compose also provides the concept of [`PaddingValues`][paddingvalues], a data class which contains the padding values to be applied on all dimensions (similar to a rect). This is commonly used with container composables, such as [`LazyColumn`][lazycolumn], to set the content padding.

You may want to use inset values for content padding, so this library provides the `Insets.toPaddingValues()` extension function to convert between `Insets` and `PaddingValues`. Here's an example of using the system bars insets:

``` kotlin
LazyColumn(
contentPadding = AmbientWindowInsets.current.systemBars.toPaddingValues()
)
```

For a more complex example, see the [`EdgeToEdgeLazyColumn`](./sample/src/main/java/dev/chrisbanes/accompanist/sample/insets/EdgeToEdgeLazyColumn.kt) example:

<a href="images/edge-to-edge-list.jpg">
<img src="images/edge-to-edge-list.jpg" width=300>
</a>

## Download

```groovy
repositories {
mavenCentral()
}
dependencies {
implementation "dev.chrisbanes.accompanist:accompanist-insets:<version>"
}
```

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

[compose]: https://developer.android.com/jetpack/compose
[snap]: https://oss.sonatype.org/content/repositories/snapshots/dev/chrisbanes/accompanist/accompanist-insets/
[insetter-view]: https://github.com/chrisbanes/insetter
[insets]: https://developer.android.com/reference/kotlin/androidx/core/view/WindowInsetsCompat
[insettypes]: https://developer.android.com/reference/kotlin/androidx/core/view/WindowInsetsCompat.Type
[insetslistener]: https://developer.android.com/reference/kotlin/androidx/core/view/OnApplyWindowInsetsListener
[modifier]: https://developer.android.com/reference/kotlin/androidx/ui/core/Modifier
[paddingvalues]: https://developer.android.com/reference/kotlin/androidx/compose/foundation/layout/PaddingValues
[lazycolumn]: https://developer.android.com/reference/kotlin/androidx/compose/foundation/lazy/package-summary#lazycolumn
[fab]: https://developer.android.com/reference/kotlin/androidx/compose/material/package-summary#floatingactionbutton
51 changes: 51 additions & 0 deletions insets/api/insets.api
@@ -0,0 +1,51 @@
public final class dev/chrisbanes/accompanist/insets/ComposeInsets {
public static final fun ProvideWindowInsets (ZLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
public static final fun add-L4cKpv0 (Landroidx/compose/foundation/layout/PaddingValues;FFFF)Landroidx/compose/foundation/layout/PaddingValues;
public static final fun add-L4cKpv0$default (Landroidx/compose/foundation/layout/PaddingValues;FFFFILjava/lang/Object;)Landroidx/compose/foundation/layout/PaddingValues;
public static final fun getAmbientWindowInsets ()Landroidx/compose/runtime/ProvidableAmbient;
public static final fun navigationBarsHeight-wxomhCo (Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier;
public static final fun navigationBarsHeight-wxomhCo$default (Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier;
public static final fun navigationBarsPadding (Landroidx/compose/ui/Modifier;ZZZ)Landroidx/compose/ui/Modifier;
public static final fun navigationBarsPadding$default (Landroidx/compose/ui/Modifier;ZZZILjava/lang/Object;)Landroidx/compose/ui/Modifier;
public static final fun navigationBarsWidth-UTaBBDU (Landroidx/compose/ui/Modifier;Ldev/chrisbanes/accompanist/insets/HorizontalSide;F)Landroidx/compose/ui/Modifier;
public static final fun navigationBarsWidth-UTaBBDU$default (Landroidx/compose/ui/Modifier;Ldev/chrisbanes/accompanist/insets/HorizontalSide;FILjava/lang/Object;)Landroidx/compose/ui/Modifier;
public static final fun statusBarsHeight-wxomhCo (Landroidx/compose/ui/Modifier;F)Landroidx/compose/ui/Modifier;
public static final fun statusBarsHeight-wxomhCo$default (Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier;
public static final fun statusBarsPadding (Landroidx/compose/ui/Modifier;)Landroidx/compose/ui/Modifier;
public static final fun systemBarsPadding (Landroidx/compose/ui/Modifier;Z)Landroidx/compose/ui/Modifier;
public static final fun systemBarsPadding$default (Landroidx/compose/ui/Modifier;ZILjava/lang/Object;)Landroidx/compose/ui/Modifier;
public static final fun toPaddingValues (Ldev/chrisbanes/accompanist/insets/Insets;ZZZZLandroidx/compose/runtime/Composer;II)Landroidx/compose/foundation/layout/PaddingValues;
}

public final class dev/chrisbanes/accompanist/insets/HorizontalSide : java/lang/Enum {
public static final field Left Ldev/chrisbanes/accompanist/insets/HorizontalSide;
public static final field Right Ldev/chrisbanes/accompanist/insets/HorizontalSide;
public static final fun valueOf (Ljava/lang/String;)Ldev/chrisbanes/accompanist/insets/HorizontalSide;
public static final fun values ()[Ldev/chrisbanes/accompanist/insets/HorizontalSide;
}

public final class dev/chrisbanes/accompanist/insets/Insets {
public fun <init> ()V
public final fun getBottom ()I
public final fun getLeft ()I
public final fun getRight ()I
public final fun getTop ()I
public final fun isVisible ()Z
}

public final class dev/chrisbanes/accompanist/insets/VerticalSide : java/lang/Enum {
public static final field Bottom Ldev/chrisbanes/accompanist/insets/VerticalSide;
public static final field Top Ldev/chrisbanes/accompanist/insets/VerticalSide;
public static final fun valueOf (Ljava/lang/String;)Ldev/chrisbanes/accompanist/insets/VerticalSide;
public static final fun values ()[Ldev/chrisbanes/accompanist/insets/VerticalSide;
}

public final class dev/chrisbanes/accompanist/insets/WindowInsets {
public fun <init> ()V
public final fun getIme ()Ldev/chrisbanes/accompanist/insets/Insets;
public final fun getNavigationBars ()Ldev/chrisbanes/accompanist/insets/Insets;
public final fun getStatusBars ()Ldev/chrisbanes/accompanist/insets/Insets;
public final fun getSystemBars ()Ldev/chrisbanes/accompanist/insets/Insets;
public final fun getSystemGestures ()Ldev/chrisbanes/accompanist/insets/Insets;
}

93 changes: 93 additions & 0 deletions insets/build.gradle
@@ -0,0 +1,93 @@
/*
* Copyright 2020 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.
*/

import dev.chrisbanes.accompanist.buildsrc.Libs

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

kotlin {
explicitApi()
}

android {
compileSdkVersion 30

defaultConfig {
minSdkVersion 21
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}

buildFeatures {
buildConfig false
compose true
}

composeOptions {
kotlinCompilerVersion Libs.Kotlin.version
kotlinCompilerExtensionVersion Libs.AndroidX.Compose.version
}

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
}

testOptions {
unitTests {
includeAndroidResources = true
}
}
}

afterEvaluate {
tasks.withType(org.jetbrains.dokka.gradle.DokkaTask).configureEach {
outputDirectory.set(rootProject.file('docs/api'))
}
}

dependencies {
implementation Libs.AndroidX.coreAlpha
implementation Libs.AndroidX.Compose.runtime
implementation Libs.AndroidX.Compose.foundation

implementation Libs.Kotlin.stdlib
// implementation Libs.Coroutines.android

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

androidTestImplementation Libs.junit
androidTestImplementation Libs.truth

androidTestImplementation Libs.AndroidX.Compose.test
androidTestImplementation Libs.AndroidX.Compose.ui
androidTestImplementation Libs.AndroidX.Test.rules
androidTestImplementation Libs.AndroidX.Test.runner
}

apply plugin: "com.vanniktech.maven.publish"
3 changes: 3 additions & 0 deletions insets/gradle.properties
@@ -0,0 +1,3 @@
POM_ARTIFACT_ID=accompanist-insets
POM_NAME=Accompanist Insets library
POM_PACKAGING=aar
Binary file added insets/images/edge-to-edge-list.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions insets/src/androidTest/AndroidManifest.xml
@@ -0,0 +1,28 @@
<!--
~ Copyright 2020 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"
package="dev.chrisbanes.accompanist.insets.test">

<uses-sdk android:targetSdkVersion="30" />

<application>
<activity
android:name="dev.chrisbanes.accompanist.insets.InsetsTestActivity"
android:theme="@android:style/Theme.Material.NoActionBar" />
</application>

</manifest>

0 comments on commit 7329268

Please sign in to comment.