Modal Sheet library for Jetpack Compose

Overview

Modal Sheet

Modal Sheet library for Jetpack Compose.

Motivation

Sometimes we want bottom sheets to behave as real modals, thus overlaying all content on the screen. Official ModalBottomSheetState however, is laid out only in bounds of the parent Composable. This means that to display a bottom sheet above, for example bottom bar navigation, it must be placed "higher" in the hierarchy than usage in one of the tab screen.

The ModalSheet Composable from this library allows creating real modal bottom sheets which could be placed anywhere in the hierarchy.

Solution

The ModalSheet Composable internally uses FullScreenPopup which is basically a window placed above the current window and allows placing Composables inside. Then ModalSheet adds swipe-to-dismiss, scrim and shaping to simulate bottom sheet behavior.

The FullScreenPopup is public, thus can be used to create own "modal" Composables.

Usage

Get a dependency

Step 1. Add the JitPack repository to your build file. Add it in your root build.gradle at the end of repositories:

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

Step 2. Add the dependency. Check latest version on the releases page.

dependencies {
    implementation 'com.github.oleksandrbalan:modalsheet:$version'
}

Use in Composable

The ModalSheet has 2 mandatory arguments:

  • visible - True if modal should be visible.
  • onDismiss - Lambda which is called when user touches the scrim or swipes the sheet away.
var visible by remember { mutableStateOf(false) }

Button(onClick = { visible = true }) {
    Text(text = "Show modal sheet")
}

ModalSheet(
    visible = visible,
    onDismiss = { visible = false },
) {
    
    Box(Modifier.height(200.dp))
}

See Demo application and examples for more usage examples.

Authors

TODO list

  • Add support for LazyColumn and LazyVerticalGrid inside modal sheet.
  • Provide swipe state to ModalSheetScope
Comments
  • [ModalSheet] Add data based ModalSheet for dynamic content

    [ModalSheet] Add data based ModalSheet for dynamic content

    Should fix #1

    Do not really like the API though :/

    @wooodenleg What do you think?

    ModalSheet(
        data = error,
        visible = { this != null },
        onDismiss = onDismiss
    ) { data ->
        if (data == null) {
            return@ModalSheet
        }
        // Use `data` for content
    }
    

    https://user-images.githubusercontent.com/20944869/167252435-6a31b477-d1a1-40bb-b6fb-9c14f65aee05.mp4

    opened by oleksandrbalan 4
  • [ModalSheet] Observability of sheet state

    [ModalSheet] Observability of sheet state

    Description

    Currently there is no way to observe the state of the modal sheet.

    The use case for having this information is for example observing the "hidden" state of the sheet to chain appearance of other UI components like Dialog or even other bottom sheet. Another use case might be to modify/animate the content of the sheet in response to the expanded state. Feature request to the material bottom sheet by Colton Idle in Kotlin Slack:

    I have a bottom sheet. When collapsed the padding on top of the text is perfect (according to my designer), but when it's fully expanded, we want to add extra padding so that the text is pushed down. We want the bottom sheet to go all the way up because that's what our designer wants in our edge to edge application.

    Implementation

    No thoughts about implementation yet but we could take "inspiration" from Material ModalBottomSheetState

    enhancement 
    opened by wooodenleg 2
  • statusBarsPadding and navigationBarsPadding method from Compose Inset API not working.

    statusBarsPadding and navigationBarsPadding method from Compose Inset API not working.

    Hi, i am using this API in bottom sheet content like this, but it's not working.

    Column(
            Modifier
                .fillMaxSize()
                .background(MaterialTheme.colors.background)
                .statusBarsPadding()
                .navigationBarsPadding()
        ) {
        
        }
    
    opened by shakil807g 1
  • Update dependencies

    Update dependencies

    kotlin = "1.7.10"
    compose_version = "1.2.1"
    compose_compiler_version = "1.3.0"
    lifecycle_version = "2.5.1"
    accompanist = "0.25.1"
    activity = "1.5.1"
    
    opened by oleksandrbalan 0
  • Add observable state

    Add observable state

    Fixes https://github.com/oleksandrbalan/modalsheet/issues/5

    I have added swipeState to the content scope and also add derived normalizedFraction for ease-of-use.

    https://user-images.githubusercontent.com/20944869/168338837-4c2cc92f-4cc8-405a-9cf8-eac1d66167f5.mp4

    opened by oleksandrbalan 0
  • Make fullscreen popup internal

    Make fullscreen popup internal

    Fixes https://github.com/oleksandrbalan/modalsheet/issues/4

    I would keep FullscreenPopup inside this library for now to not support 2 small libraries at once.

    Also:

    • Remove cusom example 🪦
    • Change name a bit
    opened by oleksandrbalan 0
  • Change custom implementation to ModalBottomSheetLayout

    Change custom implementation to ModalBottomSheetLayout

    This PR replaces custom implementation of the bottom sheet with ModalBottomSheetLayout, take it as a suggestion.

    Pros:

    • Identical look&feel as official component.
    • Out-of-box same configuration options (shape, elevation, scrim).
    • Out-of-box LazyColumn and LazyVerticalGrid support.
    • Less code - less support 🤷‍♂️

    Cons:

    • ModalSheet is less configurable, because bound to possibilities and API of ModalBottomSheetLayout.
    • Could not provide content for scrim overlay (can be added in future).
    opened by oleksandrbalan 0
  • Move FullScreenPopup into separate artifact

    Move FullScreenPopup into separate artifact

    FullScreenPopup feels more like implementation detail for "modal sheet" rather than a feature I would look for in this library. Consider making it internal or moving it to separate public artifact so the API is opt-in.

    enhancement 
    opened by wooodenleg 0
  • [ModalSheet] No exit animation when ModalSheet has dynamic content

    [ModalSheet] No exit animation when ModalSheet has dynamic content

    Description

    Sometimes it is needed to show dynamic data in modal sheet content. Imagine error bottom sheet use-case, where if Error is not null we need to show modal, otherwise hide it. We could either wrap ModalSheet in "if" condition to show only for non-null error, or adjust content (which is animated) for null error.

    Both possible solutions did not provide good experience. Either there is no exit animation, or content is "blinking" when animating out.

    Sample

    
    data class ErrorData(val title: String, val message: String)
    
    val error = rememberSaveable { mutableStateOf<ErrorData?>(null) }
    
    Box(
        contentAlignment = Alignment.Center,
        modifier = Modifier
            .fillMaxSize()
            .padding(padding)
    ) {
        Button(onClick = {
            error.value = ErrorData(
                title = "Error",
                message = "Oops, an error occurred"
            )
        }) {
            Text(text = "Error!")
        }
    }
    
    // Solution #1 - wrap in if condition
    val errorValue = error.value
    if (errorValue != null) {
        ModalSheet(
            visible = true,
            onDismiss = { error.value = null }
        ) {
            Column(
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.spacedBy(SpacingSmall),
                modifier = Modifier
                    .fillMaxWidth()
                    .navigationBarsPadding()
                    .padding(SpacingMedium)
            ) {
                Text(
                    text = errorValue.title,
                    style = MaterialTheme.typography.h4
                )
                Text(
                    text = errorValue.message,
                )
            }
        }
    }
    
    // Solution #2 - null content is visible when animated out
    ModalSheet(
        visible = error.value != null,
        onDismiss = { error.value = null }
    ) {
        Column(
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.spacedBy(SpacingSmall),
            modifier = Modifier
                .fillMaxWidth()
                .navigationBarsPadding()
                .padding(SpacingMedium)
        ) {
            Text(
                text = error.value?.title.orEmpty(),
                style = MaterialTheme.typography.h4
            )
            Text(
                text = error.value?.message.orEmpty(),
            )
        }
    }
    

    Video

    First solution to wrap in if condition, results in no exit animation. https://user-images.githubusercontent.com/20944869/167183075-409de54f-6954-4206-bc90-b488755e6958.mp4

    Second solution to use null in content, results in "empty" content during exit animation. https://user-images.githubusercontent.com/20944869/167187758-c1d16bb1-d21e-44ec-adf1-78bf76763c3a.mp4

    enhancement 
    opened by oleksandrbalan 0
Releases(v0.2.0)
Owner
Oleksandr Balan
Oleksandr Balan
A collection of animations, compositions, UIs using Jetpack Compose. You can say Jetpack Compose cookbook or play-ground if you want!

Why Not Compose! A collection of animations, compositions, UIs using Jetpack Compose. You can say Jetpack Compose cookbook or play-ground if you want!

Md. Mahmudul Hasan Shohag 186 Jan 1, 2023
Learn Jetpack Compose for Android by Examples. Learn how to use Jetpack Compose for Android App Development. Android’s modern toolkit for building native UI.

Learn Jetpack Compose for Android by Examples. Learn how to use Jetpack Compose for Android App Development. Android’s modern toolkit for building native UI.

MindOrks 382 Jan 5, 2023
This is a sample app(For beginners - App #2) built using Jetpack Compose. It demonstrates the concept of State Hoisting in Jetpack Compose.

JetBMICalculator This is a sample app(For beginners - App #2) built using Jetpack Compose. It demonstrates the concept of State Hoisting in Jetpack Co

BHAVNA THACKER 3 Dec 31, 2022
Jetpack-Compose-Demo - Instagram Profile UI using Jetpack Compose

Jetpack-Compose-Demo Instagram Profile UI using Jetpack Compose

omar 1 Aug 11, 2022
Jetpack-compose-animations-examples - Cool animations implemented with Jetpack compose

Jetpack-compose-animations-examples This repository consists of 4 animations: St

Canopas Software 180 Jan 2, 2023
Compose-navigation - Set of utils to help with integrating Jetpack Compose and Jetpack's Navigation

Jetpack Compose Navigation Set of utils to help with integrating Jetpack Compose

Adam Kobus 5 Apr 5, 2022
Jetpack-compose-uis - A collection of some UIs using Jetpack Compose. built using Katalog

Jetpack Compose UIs This is a collection of some UIs using Jetpack Compose. It i

Mori Atsushi 3 Dec 15, 2022
A simple authentication application using Jetpack compose to illustrate signin and sign up using Mvvm, Kotlin and jetpack compose

Authentication A simple authentication application using Jetpack compose to illustrate signin and sign up using Mvvm, Kotlin and jetpack compose Scree

Felix Kariuki 5 Dec 29, 2022
A Kotlin library to use Jetpack Compose in Android and iOS. Allow to write UI for both in Kotin. Still experimental as many compose features are not yet available.

Multiplatform Compose A Kotlin library to use Jetpack Compose in Android and iOS. Allow to write UI for both in Kotin. Still experimental as many comp

Clément Beffa 548 Jan 7, 2023
Compose-Ratingbar-library - A simple implementation for rating bar in Jetpack Compose

Compose-Ratingbar-library - A simple implementation for rating bar in Jetpack Compose

Mahmoud Hussein 14 Dec 21, 2022
Compose Curved-Scroll is an Android Jetpack Compose library made with ❤️

Compose-Curved-Scroll-library Compose Curved-Scroll is an Android Jetpack Compos

mohamed tamer 23 Aug 24, 2022
Android.compose.squircle - Android LightWeight Squircle Library for JetPack Compose

Android LightWeight Squircle Library for JetPack Compose Usage Based on Compose

Quang Nguyen 9 Jul 5, 2022
Compose-html - An Android library which provides HTML support for Jetpack Compose texts

HtmlCompose An Android library which provides HTML support for Jetpack Compose t

iRewardHealth 43 Dec 29, 2022
An application that i developed with a aim of learning Jetpack compose and many other jetpack libraries

An application that i developed with a aim of learning Jetpack compose and many other jetpack libraries, The application make use of jikan Api which displays a list of animations,there more details and even trailers of the animations.

Odhiambo Brandy 10 Nov 23, 2022
Lightweight library to tweak the fling behaviour in Android. This library is only compatible with Jetpack-Compose.

Flinger (Only compatible with compose) What is Flinger? Flinger is a plugin that is made on top of jetpack compose that will help the developer to twe

Joseph James 73 Dec 24, 2022
K5-compose is a sketchy port of p5.js for Jetpack Compose

k5-compose k5-compose is a sketchy port of P5.js for Jetpack Compose Desktop. This library provides you a playground to play with your sketches so you

Nikhil Chaudhari 176 Nov 22, 2022
Jetpack Compose based project, used to stress-testing compose features / integrations and explore non-trivial functionality

Project containing Jetpack Compose samples For pagination & network images it uses CATAAS. Known issues Navigation-Compose Issue with fast tapping on

Denis Rudenko 59 Dec 14, 2022
Pokedex Compose is an independent re-write of a demo application by the name of Pokedex, but written in jetpack compose.

Pokedex Compose Pokedex Compose is an independent re-write of a similar project by the name of Pokedex. I am recreating the UI but I am doing it using

Jose Patino 4 May 1, 2022
Compose-Instagram-Profile-UI - Instagram profile screen UI using android jetpack compose

Compose-Intsgram-Profile-UI Instagram profile screen UI using android jetpack co

TILLERN 1 Mar 8, 2022