0

I am just getting into the world of SwiftUI, so I don't know if there is a very obvious answer to this question, but basically I have created a button and tried to make the button two concentric circles. However once I run my code on the simulator I found out that I could click literally anywhere on the screen and the button would be "pressed" (I tested it using a print statement). I want to confine the clickable area of the button to the just the area of the circles or maybe the square that bounds both circles.

Here is my code:

    Button(action: {
    print("Do Something")

}) {
    
    Circle().stroke(Color.white, lineWidth: 3)
        .frame(width: 65, height: 65)
        .position(x: x, y: y)
        .overlay(
            Circle().stroke(Color.white, lineWidth: 3)
                .frame(width: 55, height: 55)
                .position(x: x, y: y)
    )

}

This is what it looks like when I click on it in my live preview window:

enter image description here

1
  • Hi, I'm sorry this comment is not about the solution to your question. Could you change the title of this question to: "How to assign an action to a Button." Commented Sep 28, 2022 at 19:59

2 Answers 2

1

You should remove .position modifier, because it switches view location (in your case button content) into global coordinates.

Instead use layout by stack, like below

    VStack {
        Spacer()          // << pushes button down
        Button(action: {
            print("Do Something")

        }) {

            Circle().stroke(Color.white, lineWidth: 3)
                .frame(width: 65, height: 65)
                .overlay(
                    Circle().stroke(Color.white, lineWidth: 3)
                        .frame(width: 55, height: 55)
                )

        }
    }
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the quick response. I was trying to get the button a certain distance from the bottom of the screen and in the center in terms of x axis. Your code pushed the button all the way to the bottom of the screen so I added a `.offset' to the VStack to move the button up a little bit and it seems to work.
use instead some variant of .padding(), because .offset does not change layout, so you could later get unexpected overlapping.
I changed the .offset to .padding and got it to work. However the VStack in your code seem to stretch from the bottom of the screen to the top, with the same width as the button. Is there any way for me to change the code to get the VStack so that it only contains the button and nothing else? I have to add other views above this button so confining the VStack to the button would be helpful.
there should be some root container for alignment child views... if you need something above, use ZStack
You should keep the VStack and update the layout later when you add your other elements. You shouldn't think of layouts in therms of how UIKit works because you're going to run into a lot of issues. Instead try to think about how you can use the provided containers (VStack, HStack, ZStack) in combination with Spacer() and .padding() in order to create the overall layout you need. Try to let the views size themselves as much as possible. Whenever you try to fight against the system, you make it harder for yourself.
0

Here is another implementation for two concentric circles which to me looks a little better.

      //Red Button Elements
            ZStack(alignment: .center){
                VStack {
                    Spacer()          // << pushes button down
                    Button(action: {
                        print("Press Circle")
                        
                    }) {
                        
                        Circle().stroke(Color.white, lineWidth: 40)
                            .frame(width: 200, height: 200)
                            .overlay(
                                Circle().stroke(Color.red, lineWidth: 100)
                                    .frame(width: 100, height: 100)
                            )
                            .foregroundColor(/*@START_MENU_TOKEN@*/.red/*@END_MENU_TOKEN@*/).padding(.bottom, 100.0)
                        
                    }
                }
                
            }
            .padding(.all)

enter image description here

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.