PrepareFor
PrepareFor

Reputation: 2598

How to make Inner shadow in SwiftUI

I'd like to make View's (Text, Button, etc) Inner shadow in SwiftUI

There is Outer shadow but there is no Inner shadow in SwiftUI

What I want to make is Neumorphism UI using SwiftUI

Image from "Neumorphism in user interfaces" by Michal Malewicz

I'd like to make button pressed UI

but I don't know where to start to make inner shadow

Upvotes: 27

Views: 18946

Answers (3)

pawello2222
pawello2222

Reputation: 54426

iOS 16+

There is now a new ShapeStyle called shadow:

From the documentation - the following example creates a circle filled with the current foreground style that uses an inner shadow:

Circle().fill(.shadow(.inner(radius: 1, y: 1)))

In most contexts the current style is the foreground, but not always. For example, when setting the value of the background style, that becomes the current implicit style.

Circle()
    .fill(.shadow(.inner(radius: 1, y: 1)))
    .foregroundStyle(.red)

Upvotes: 15

zhangao88
zhangao88

Reputation: 161

iOS 16+ only

For Buttons

You could use a SwiftUI shape as background.

Use .fill(.shadow(.inner(radius: 1, y: 1))) for inner shadow.

The .foregroundColor of the shape is the background color of the button.

Here's my example using pawello2222's answer

For a RoundedRectangle Button same as the question

Button(action: {}){
        Image(systemName: "heart.fill")
            .resizable()
            .frame(width: 40, height: 40)
            .padding(25)
            .foregroundColor(Color(red: 52/255, green: 57/255, blue: 133/255))
            .background(
                RoundedRectangle(cornerRadius: 20, style: .continuous)
                    .fill(
                        .shadow(.inner(color: Color(red: 197/255, green: 197/255, blue: 197/255),radius: 3, x:3, y: 3))
                        .shadow(.inner(color: .white, radius: 3, x: -3, y: -3))
                    )
                    .foregroundColor(Color(red: 236/255, green: 234/255, blue: 235/255)))
          }
}

RoundedRectangle Button

For a Circle Button

Button(action: {}){
            Image(systemName: "heart.fill")
                .resizable()
                .frame(width: 40, height: 40)
                .padding(25)
                .foregroundColor(Color(red: 52/255, green: 57/255, blue: 133/255))
                .background(
                    Circle()
                        .fill(
                            .shadow(.inner(color: Color(red: 197/255, green: 197/255, blue: 197/255),radius: 5, x:3, y: 3))
                            .shadow(.inner(color: .white, radius:5, x: -3, y: -3))
                        )
                        .foregroundColor(Color(red: 236/255, green: 234/255, blue: 235/255)))
}

Circle Button

Upvotes: 16

A.Cal
A.Cal

Reputation: 306

This is what I did to create an inner shadow like the one in the picture. I created it in another swiftui file and just called in in my main content view but you can display it however you'd like.

I created a Button in a ZStack only because I first recreated it with a rounded rectangle but I think this would would in a HStack or VStack as well just haven't tried them. To create the inner shadow I created an overlay and clipped the shadows to the shape.

ZStack{
        
        Button(action: {}){
            Image(systemName: "heart.fill")
                .resizable()
                .frame(width: 40, height: 40)
                .padding(25)
                .foregroundColor(Color(red: 52/255, green: 57/255, blue: 133/255))
                .overlay(
                    RoundedRectangle(cornerRadius: 15)
                        .stroke(Color(red: 236/255, green: 234/255, blue: 235/255), 
                                lineWidth: 4)
                        .shadow(color: Color(red: 192/255, green: 189/255, blue: 191/255), 
                                radius: 3, x: 5, y: 5)
                        .clipShape(
                            RoundedRectangle(cornerRadius: 15)
                        )
                        .shadow(color: Color.white, radius: 2, x: -2, y: -2)
                        .clipShape(
                            RoundedRectangle(cornerRadius: 15)
                        )
                )
                .background(Color(red: 236/255, green: 234/255, blue: 235/255))
                .cornerRadius(20)
        }

The end result looked like this: enter image description here

You can play around with the colors and the shadows to get exactly what you want but hopefully this helps!

Upvotes: 27

Related Questions