Neumorphism UI on Android with Jetpack Compose.

Overview

Neumorphism UI with Jetpack Compose

This library is an experimentation with Neumorphism UI (New + Skeuomorphism) on Android with Jetpack Compose.

List of Awesome List Badge Awesome Kotlin Badge

How to use?

1. Add the dependency

And your app level build.gradle. (Make sure you have compose dependencies as well)

  implementation("me.nikhilchaudhari:composeNeumorphism:1.0.0-alpha")

2. Use

Just add modifier = Modifier.neumorphic(context) to any of your UI element of Jetpack-Compose (just like you do for other modifiers).

image

How do I configure shape, color, etc.?

1. Shapes

You've three basic Neu shapes available -

  1. Punched, 2. Pressed, 3. Pot

These are not standard names for Neumorphism UI, I just named them based on how they look (at least to me).

And you can also configure the corner families of those shapes as Oval or Rounded

image

Card(
  backgroundColor = Color(236, 234, 235),
  shape = RoundedCornerShape(12.dp),
  modifier = Modifier
      .padding(16.dp)
      .size(300.dp, 100.dp)
      .neumorphic(
        context,
        neuShape = 
          // Punched shape
         Punched.Rounded(radius = 8.dp) 
         Punched.Oval()

         // Presssed Shape
         Pressed.Rounded(radius = 4.dp)
         Presssed.Oval()

        // Pot shape
        Pot.Rounded(radius = 8.dp)
        Pot.Oval()
      )
    ){/*card content */} 

For Rounded corner-family, you can configure the radius of how much rounded corner you want. The default Neu shape is Punched.Rounded(radius = 12.dp).
The Punched shape would work with Cards, Buttons, etc.
You should use Modifier.clip() while using Pressed shape, because there's known issue of shadow placeents for Pressed shape. Check the sample app for more code snippets.

P.S: Even I'm yet to experiment it with all UI elements.

2. Shadows

The idea of Neumorphism UI is simple, just create two shadows light and dark and draw those around the UI component from top-left and bottom-right corners.
Just make sure you are using the same colors for your Surface and for the UI elements. You can configure the shadow insets, color and elevation

Params Description
lightShadowColor Default value - Color.White - Set the light shadow color you want
darkShadowColor Default value - Color.Gray - Set the dark shadow color you want.
elevation Default value - 6.dp - Set the elevation for the shadow.
neuInsets Default values - NeuInsets(6.dp, 6.dp) - Insets = Horizontal, Vertical - Placements of your shadows i.e How do you want to place your
strokeWidth Default value - 6.dp - Stroke width of the internal shadows. Stroke width is for only Pressed and Punched.
  Button(
       onClick = { /*TODO*/ },
       modifier = Modifier
           .padding(12.dp)
           .neumorphic(
               context,
               // assing neuShape
               //...
               lightShadowColor = Color.White,
               darkShadowColor = Color.Gray,
               elevation = 4.dp,
               strokeWidth: Dp = 6.dp,
               neuInsets = NeuInsets(6.dp, 6.dp)
           )
   ) 

The overall configutation image

ToDos

  • Add LightSource option and place the shadows accordingly (It is, by default, top-left right now)
  • Migrate from RenderScript
  • Fix clipping and shadow positioning with insets
  • Update sample app and code with Jetpack-Compose guidelines

FAQs

What's the idea? Is there any performance overhead?

Idea is simple - just draw the two shadows light and dark around the UI element. I'm using RenderScript to blur two GradientDrawables (that's why the context parameter). I know it's going to be deprecated in the Android 12. I'll surely update the code to migrate from RenderScript. If Renderscript throws any exception / not able to blur the drawable, I'm using StackBlur algorithm from Mario Klingemann as a workaround.

Does this library work with all the Jetpack Compose UI elements?

I can't surely say. I'm already experimenting drawing shadow on UIs with Jetpack Compose and improving this library. I request you to try and please help to make it work.

When can I use this?

You can use this right now if you want to play with shiny Neumorphism UI. The library is in alpha and there are some known issues regarding shadow rendering and clipping. Please raise issue if you found any.

Contribution Guide

Please contribute! I'm just getting my hands dirty with Jetpack-Compose.
There is heavy chance that the code may/may not be correct/holding best practices. I request you to contribute/ raise issues/ send PRs so I can learn too. You can use the Github Discussion to discuss and ask questions. Or you can reach out to me on Twitter @CuriousNikhil.

  • Current release branch - release/1.0.0-alpha02

License

Licensed under Apache License, Version 2.0 here

You might also like...
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.
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

Compose-Instagram-Profile-UI - Instagram profile screen UI using android jetpack compose
Compose-Instagram-Profile-UI - Instagram profile screen UI using android jetpack compose

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

Compose Curved-Scroll is an Android Jetpack Compose library made with ❤️
Compose Curved-Scroll is an Android Jetpack Compose library made with ❤️

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

Compose-html - An Android library which provides HTML support for Jetpack Compose texts
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

Svg-to-compose-intellij - A simple Android Studio plugin to generate Jetpack Compose ImageVector icons

svg-to-compose-intellij A simple Android Studio plugin to generate Jetpack Compo

📱 WhatsApp clone project demonstrates modern Android development built with Jetpack Compose and Stream Chat SDK for Compose.
📱 WhatsApp clone project demonstrates modern Android development built with Jetpack Compose and Stream Chat SDK for Compose.

This is a WhatsApp clone app built with Jetpack Compose and Stream Chat SDK for Compose. The purpose of this repository is to demonstrate below: Imple

K5-compose is a sketchy port of p5.js for Jetpack Compose
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

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

Pokedex Compose is an independent re-write of a demo application by the name of Pokedex, but written in jetpack compose.
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

Comments
  • Neomorphism Accessibility Concerns

    Neomorphism Accessibility Concerns

    Hey @CuriousNikhil! First off, thanks for your public, exploratory work on implementing this relatively new online aesthetic. If nothing else, it's been exciting reading through the codebase as a form of reference for other UI patterns.

    With that said, I’m curious how you see someone implementing this with accessibility in mind. There are some issues when it comes to the neuromorphic design patterns and accessibility. Among the issues, there are: • Lack of proper contrast • Lack of distinct contrasting component states • Increased cognitive load in app usage

    I’d love to see more focus on those concerns as you continue building this out! I think it would be a great way to further explore the viability of something like this. If you have any thoughts or questions I’d love to discuss them!

    opened by crutchcorn 4
  • Facing a crash due to IllegalArgumentException

    Facing a crash due to IllegalArgumentException

    java.lang.IllegalArgumentException: Width and height must be greater than or equal to zero at androidx.compose.ui.graphics.drawscope.CanvasDrawScopeKt$asDrawTransform$1.inset(CanvasDrawScope.kt:749) at me.nikhilchaudhari.library.shapes.DrawingKt.drawOnBackground(Drawing.kt:244) at me.nikhilchaudhari.library.shapes.Punched.drawShadows(Punched.kt:22) at me.nikhilchaudhari.library.NeumorphicModifier.draw(Neumorphic.kt:84) at androidx.compose.ui.node.ModifiedDrawNode.performDraw(ModifiedDrawNode.kt:102) at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:255) at androidx.compose.ui.node.LayoutNodeDrawScope.drawContent(LayoutNodeDrawScope.kt:42) at androidx.compose.foundation.Background.draw(Background.kt:107) at androidx.compose.ui.node.ModifiedDrawNode.performDraw(ModifiedDrawNode.kt:102) at androidx.compose.ui.node.LayoutNodeWrapper$invoke$1.invoke(LayoutNodeWrapper.kt:267) at androidx.compose.ui.node.LayoutNodeWrapper$invoke$1.invoke(LayoutNodeWrapper.kt:266) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:126) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:88) at androidx.compose.ui.node.LayoutNodeWrapper.invoke(LayoutNodeWrapper.kt:266) at androidx.compose.ui.node.LayoutNodeWrapper.invoke(LayoutNodeWrapper.kt:59) at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:168) at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:245) at androidx.compose.ui.platform.RenderNodeLayer.drawLayer(RenderNodeLayer.android.kt:226) at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:250) at androidx.compose.ui.node.ModifiedLayoutNode.performDraw(ModifiedLayoutNode.kt:98) at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:255) at androidx.compose.ui.node.ModifiedLayoutNode.performDraw(ModifiedLayoutNode.kt:98) at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:255) at androidx.compose.ui.node.ModifiedLayoutNode.performDraw(ModifiedLayoutNode.kt:98) at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:255) at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:828) at androidx.compose.ui.node.InnerPlaceable.performDraw(InnerPlaceable.kt:137) at androidx.compose.ui.node.LayoutNodeWrapper$invoke$1.invoke(LayoutNodeWrapper.kt:267) at androidx.compose.ui.node.LayoutNodeWrapper$invoke$1.invoke(LayoutNodeWrapper.kt:266) at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:126) at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:88) at androidx.compose.ui.node.LayoutNodeWrapper.invoke(LayoutNodeWrapper.kt:266) at androidx.compose.ui.node.LayoutNodeWrapper.invoke(LayoutNodeWrapper.kt:59) at androidx.compose.ui.platform.RenderNodeApi29.record(RenderNodeApi29.android.kt:168) at androidx.compose.ui.platform.RenderNodeLayer.updateDisplayList(RenderNodeLayer.android.kt:245) at androidx.compose.ui.platform.RenderNodeLayer.drawLayer(RenderNodeLayer.android.kt:226) at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:250) at androidx.compose.ui.node.ModifiedLayoutNode.performDraw(ModifiedLayoutNode.kt:98) at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:255) at androidx.compose.ui.node.ModifiedLayoutNode.performDraw(ModifiedLayoutNode.kt:98) at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:255) at androidx.compose.ui.node.ModifiedLayoutNode.performDraw(ModifiedLayoutNode.kt:98) at androidx.compose.ui.node.LayoutNodeWrapper.draw(LayoutNodeWrapper.kt:255) at androidx.compose.ui.node.LayoutNode.draw$ui_release(LayoutNode.kt:828) at androidx.compose.ui.node.InnerPlaceable.performDraw(InnerPlaceable.kt:137)

    opened by sanjeet131 3
  • Error in using the latest library version

    Error in using the latest library version

    /home/zbs/.gradle/caches/transforms-2/files-2.1/543eaf0df6ddea7b3bbea1e33f72e020/jetified-kotlin-stdlib-1.5.21.jar!/META-INF/kotlin-stdlib.kotlin_module: Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.1, expected version is 1.1.16. how can i do thx

    opened by zhubinsheng 1
  • Punched is not working proprrly

    Punched is not working proprrly

    this is the code

    Card( modifier = Modifier // .paint( // painterResource(id = R.drawable.primary_button_bg_light), // contentScale = ContentScale.FillBounds) .neumorphic( neuShape = Punched.Rounded(radius = 12.dp) ) .padding(20.dp) .size(80.dp), backgroundColor = MaterialTheme.colors.background, shape = RoundedCornerShape(12.dp) )

    Screenshot_20221117_112801

    opened by venkat-clone 0
Releases(v1.0.0-alpha02)
  • v1.0.0-alpha02(Aug 12, 2021)

  • v1.0.0-alpha(May 30, 2021)

Owner
Nikhil Chaudhari
programming and percussions !!
Nikhil Chaudhari
Jetpack Compose Boids | Flocking Insect 🐜. bird or Fish simulation using Jetpack Compose Desktop 🚀, using Canvas API 🎨

?? ?? ?? Compose flocking Ants(boids) ?? ?? ?? Jetpack compose Boids | Flocking Insect. bird or Fish simulation using Jetpack Compose Desktop ?? , usi

Chetan Gupta 38 Sep 25, 2022
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
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
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
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