ghostrider
ghostrider

Reputation: 5259

IOS - dynamic placement of uibutton

I have a weird issue :

I am dynamically setting some buttons positions in either ViewDidLoad or ViewDidAppear (tried them both) and set the dimensions manually. Then whenever a button is pressed, I change the frame of the buttons. But even when I set the original one - they are not in the same position on the screen but they look kind of "moved some px down". I am attaching code and sceenshot :

viewDidAppear :

    self.twoTeamsBtn = [[UIButton alloc] init];
    self.twoTeamsBtn.frame = CGRectMake(156/2, (94/2), selected2Image.size.width, selected2Image.size.height);
    self.threeTeamsBtn = [[UIButton alloc] init];
    self.threeTeamsBtn.frame = CGRectMake(331/2, (132/2), unselected3Image.size.width, unselected3Image.size.height);
    self.fourTeamsBtn = [[UIButton alloc] init];
    self.fourTeamsBtn.frame = CGRectMake(505/2, (132/2), unselected4Image.size.width, unselected4Image.size.height);

So, twoTeams is at 94/2 (Y) and thee at 132/2. Both images are of the same height. (selected2 is the same as selected3 and unselected3 is the same as unselected3 and so on).

Then inside my click method I have :

 if (button.tag == self.twoTeamsBtn.tag) {
   self.threeTeamsBtn.frame = CGRectMake(331/2, (132/2), self.threeTeamsBtn.frame.size.width, self.threeTeamsBtn.frame.size.height);
    self.fourTeamsBtn.frame = CGRectMake(505/2, (132/2), self.fourTeamsBtn.frame.size.width, self.fourTeamsBtn.frame.size.height);
    self.twoTeamsBtn.frame = CGRectMake(156/2, (94/2), selected2Image.size.width, selected2Image.size.height);

    [self.threeTeamsBtn setImage:unselected3Image forState:UIControlStateNormal];
    [self.twoTeamsBtn setImage:selected2Image forState:UIControlStateNormal];
    [self.fourTeamsBtn setImage:unselected4Image forState:UIControlStateNormal];

} else if (button.tag == self.threeTeamsBtn.tag) {
    self.threeTeamsBtn.frame = CGRectMake(331/2, (94/2), selected3Image.size.width, selected3Image.size.height);
    self.fourTeamsBtn.frame = CGRectMake(505/2, (132/2), self.fourTeamsBtn.frame.size.width, self.fourTeamsBtn.frame.size.height);
    self.twoTeamsBtn.frame = CGRectMake(156/2, (132/2), self.twoTeamsBtn.frame.size.width, self.twoTeamsBtn.frame.size.height);

    [self.threeTeamsBtn setImage:selected3Image forState:UIControlStateNormal];
    [self.twoTeamsBtn setImage:unselected2Image forState:UIControlStateNormal];
    [self.fourTeamsBtn setImage:unselected4Image forState:UIControlStateNormal];

} else if (button.tag == self.fourTeamsBtn.tag) {
    self.threeTeamsBtn.frame = CGRectMake(331/2, (132/2), self.threeTeamsBtn.frame.size.width, self.threeTeamsBtn.frame.size.height);
    self.fourTeamsBtn.frame = CGRectMake(505/2, (94/2), selected4Image.size.width, selected4Image.size.height);

    self.twoTeamsBtn.frame = CGRectMake(156/2, (132/2), self.twoTeamsBtn.frame.size.width, self.twoTeamsBtn.frame.size.height);

    [self.threeTeamsBtn setImage:unselected3Image forState:UIControlStateNormal];
    [self.twoTeamsBtn setImage:unselected2Image forState:UIControlStateNormal];
    [self.fourTeamsBtn setImage:selected4Image forState:UIControlStateNormal];

}

Screenshots are as follow :

button 2 selected button 3 selected button 3 selected

So, if you see in the 2nd picture, the button 2 and button 4, are not in the same level, although their frames are identical. In the 3rd one the 2 and 3 are on the same level.

It's like the original 132/2 for example, is not the same like the one set later on.

Am I missing something?

Upvotes: 2

Views: 435

Answers (3)

Flexicoder
Flexicoder

Reputation: 8511

I appreciate that you might of already found an answer thanks to TwoStraws, but I think the issue is down to the way you are setting the frame width/height

if (button.tag == self.twoTeamsBtn.tag) {
    self.threeTeamsBtn.frame = CGRectMake(331/2, (132/2), self.threeTeamsBtn.frame.size.width, self.threeTeamsBtn.frame.size.height);
    self.fourTeamsBtn.frame = CGRectMake(505/2, (132/2),  self.fourTeamsBtn.frame.size.width, self.fourTeamsBtn.frame.size.height);
    self.twoTeamsBtn.frame = CGRectMake(156/2, (94/2), selected2Image.size.width, selected2Image.size.height);

    [self.threeTeamsBtn setImage:unselected3Image forState:UIControlStateNormal];
    [self.twoTeamsBtn setImage:selected2Image forState:UIControlStateNormal];
    [self.fourTeamsBtn setImage:unselected4Image forState:UIControlStateNormal];
} 

for the unselected images you are setting the frame to whatever it was before, but if the selected/unselected images are different sizes then the last one that was selected (and now unselected would be off). You need to set the frame size based on the image you are using.

i.e.

if (button.tag == self.twoTeamsBtn.tag) {
    self.threeTeamsBtn.frame = CGRectMake(331/2, (132/2), unselected3Image.size.width, unselected3Image.size.height);
    self.fourTeamsBtn.frame = CGRectMake(505/2, (132/2),  unselected4Image.size.width, unselected4Image.size.height);
    self.twoTeamsBtn.frame = CGRectMake(156/2, (94/2), selected2Image.size.width, selected2Image.size.height);

    [self.threeTeamsBtn setImage:unselected3Image forState:UIControlStateNormal];
    [self.twoTeamsBtn setImage:selected2Image forState:UIControlStateNormal];
    [self.fourTeamsBtn setImage:unselected4Image forState:UIControlStateNormal];
} 

Upvotes: 2

TwoStraws
TwoStraws

Reputation: 13127

Changing frames of things is best avoided if you're able to – it's preferable to adjust thebounds and center instead, which in turn recalculates the frame for you.

In your particular example, animating the transform property is even easier, using something like this:

// animate upwards
btn.transform = CGAffineTransformMakeTranslation(0, -50)

// go back to where it was
btn.transform = CGAffineTransformIdentity

The CGAffineTransformIdentity transform automatically puts the button back where it was, which is what makes this solution so easy.

If you are also changing the image of the button, the best thing to do if you can is make sure your before and after pictures are the same size, perhaps by adding a small amount of whitespace to the smaller of the two. This way your buttons never change in size, which means you have one less thing to worry about.

Upvotes: 1

Mohit Mathur
Mohit Mathur

Reputation: 62

btn1 = [[UIButton alloc] init];
    btn1.frame = CGRectMake(156/2, (94/2), 50, 50);
    btn2 = [[UIButton alloc] init];
    btn2.frame = CGRectMake(331/2, (132/2), 50, 50);
    btn3 = [[UIButton alloc] init];
    btn3.frame = CGRectMake(505/2, (132/2), 50, 50);


    [btn1 setBackgroundColor:[UIColor blackColor]];
    [btn2 setBackgroundColor:[UIColor redColor]];
    [btn3 setBackgroundColor:[UIColor blueColor]];

    [btn1 addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
    [btn2 addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];
    [btn3 addTarget:self action:@selector(action:) forControlEvents:UIControlEventTouchUpInside];

    btn1.tag=1000;
    btn2.tag=2000;
    btn3.tag=3000;

    [self.view addSubview:btn1];
    [self.view addSubview:btn2];
    [self.view addSubview:btn3];

Put this code in ViewDidAppear or ViewDidLoad. It will work

Upvotes: -1

Related Questions