UISegmentControl Programmatically segments frame - ios

I'm using a segment control in the following manner.
CGFloat segmentWidth = 70;
CGFloat segmentHeight = 40;
NSMutableArray *arr = [[NSMutableArray alloc] init];
for (HCIPGRentDetail *object in self.pgHouse.rents) {
[arr addObject:object.roomTypeId];
}
UISegmentedControl *sharingSegmentControl = [[UISegmentedControl alloc] initWithItems:arr];
[sharingSegmentControl setApportionsSegmentWidthsByContent:YES];
sharingSegmentControl.frame = CGRectMake(0, 0, self.pgHouse.rents.count * segmentWidth, segmentHeight);
for (int i = 0; i < sharingSegmentControl.numberOfSegments; i++) {
[sharingSegmentControl setWidth:segmentWidth forSegmentAtIndex:i];
[sharingSegmentControl setTitle:arr[i] forSegmentAtIndex:i];
}
sharingSegmentControl.center = CGPointMake(self.view.center.x, currentHeight + sharingSegmentControl.frame.size.height/2);
currentHeight += sharingSegmentControl.frame.size.height;
[sharingSegmentControl.layer setBorderColor:[UIColor redColor].CGColor];
[sharingSegmentControl.layer setBorderWidth:1.0f];
[sharingSegmentControl setSelectedSegmentIndex:0];
[sharingSegmentControl setBackgroundColor:[UIColor blueColor]];
[sharingSegmentControl setSegmentedControlStyle:UISegmentedControlStyleBar];
[self.mainScrollView addSubview:sharingSegmentControl];
It just displays the segment control with blue colour background and red colour, the segments get a frame (debugger) like {{0,0},{0,29}}. Doesn't understand what I'm missing.
The debugger says this
<__NSArrayM 0x1411be30>(
<UISegment: 0x1411bd60; frame = (0 0; 0 29); opaque = NO; layer = <CALayer: 0x1411bd30>>,
<UISegment: 0x1411a1c0; frame = (0 0; 0 29); opaque = NO; layer = <CALayer: 0x1411b220>>
)

I copied your code and edited it just a bit, so this works for me :
CGFloat segmentWidth = 70;
CGFloat segmentHeight = 40;
UISegmentedControl *sharingSegmentControl = [[UISegmentedControl alloc] initWithItems:#[#"AAA", #"BBB"]];
//[sharingSegmentControl setApportionsSegmentWidthsByContent:YES];
sharingSegmentControl.frame = CGRectMake(0, 0, sharingSegmentControl.numberOfSegments * segmentWidth, segmentHeight);
for (int i = 0; i < sharingSegmentControl.numberOfSegments; i++) {
[sharingSegmentControl setWidth:segmentWidth forSegmentAtIndex:i];
//[sharingSegmentControl setTitle:arr[i] forSegmentAtIndex:i];
}
[sharingSegmentControl.layer setBorderColor:[UIColor redColor].CGColor];
[sharingSegmentControl.layer setBorderWidth:1.0f];
[sharingSegmentControl setSelectedSegmentIndex:0];
[sharingSegmentControl setBackgroundColor:[UIColor blueColor]];
[sharingSegmentControl setSegmentedControlStyle:UISegmentedControlStyleBar];
[self.view addSubview:sharingSegmentControl];

Turns out that tint colour was the problem. Maybe segment control take the tint colour default as clear colour or so.
Somehow, when I just set the tint colour. I got the frame correct, the display correct.

Related

How to make a UIButton grid according to size of superview in iOS?

I am trying to make a UIButton Grid with respect to size of superView.Most of the solutions that I have seen are such where buttons are added to scrollView .But what if I don't want scrollable grid and just a normal grid .How can I resize my buttons depending on the size of its superview where they are plotted?.Has anyone tried it?Any help is really appreciated.
-(void)createLayout{
int width =30;
int height =30;
int leftMargin =10;
int topMargin =10;
int xTile;
int yTile;
int xSpacing = 50;
int ySpacing = 50;
for (int c=1; c<=5; c++) {
for (int r=1; r<=10; r++) {
NSLog(#"row : %d col : %d",r,c);
yTile = ((c*ySpacing)+topMargin);
xTile = ((r*xSpacing)+leftMargin);
Test *btn = [Test buttonWithType:UIButtonTypeCustom];
btn.row = r;
btn.column =c;
[btn setTitle:[NSString stringWithFormat:#"%d,%d",btn.row,btn.column] forState:UIControlStateNormal ];
[btn.titleLabel setFont:[UIFont fontWithName:#"Arial" size:14]];
[btn setBackgroundColor:[UIColor redColor]];
[btn setFrame:CGRectMake(xTile, yTile, width, height)];
[self.scrollView addSubview:btn];
xTile=xTile+10;
}
yTile = yTile+10;
}
}
Well to answer your question I wrote a code. Something like this will help you. I have created this project for you here. Check that. Also it's not completely fine I would like you to work on it and made a commit when you have made it perfect.
- (UIView *) view : (CGSize) viewSize withButtons : (int) numberOfButtons{
CGRect frame = CGRectZero;
frame.size = viewSize;
UIView *view = [[UIView alloc]initWithFrame:frame];//considering View size is after margine
CGSize buttonSize = [self getButton:numberOfButtons sizeFor:viewSize];
for (int i = 1; i <= numberOfButtons; i++) {
UIButton *button = [[UIButton alloc] initWithFrame:[self getButton:buttonSize frameForIndex:i inView:viewSize]];
[button setTitle:[[NSNumber numberWithInt:i] stringValue] forState:UIControlStateNormal];
[button setTitleColor:[UIColor darkGrayColor] forState:UIControlStateNormal];
[button.layer setBorderColor:[UIColor lightGrayColor].CGColor];
[button.layer setBorderWidth:1.0f];
[view addSubview:button];
}
return view;
}
- (CGRect) getButton : (CGSize) buttonSize frameForIndex : (int) buttonIndex inView : (CGSize) containerSize{
int x = buttonIndex % (int)(containerSize.width / buttonSize.width);
x *= buttonSize.width;
int y = buttonIndex % (int)(containerSize.height / buttonSize.height);
y *= buttonSize.height;
CGRect frame = CGRectZero;
frame.origin = CGPointMake(x, y);
frame.size = buttonSize;
return frame;
}
- (CGSize) getButton : (int) numberOfButtons sizeFor : (CGSize) containerSize{
double containerArea = containerSize.width * containerSize.height;
double areaOfOneButton = containerArea / numberOfButtons;
double edgeOfOneButton = sqrt(areaOfOneButton);
edgeOfOneButton = (edgeOfOneButton > containerSize.width) ? containerSize.width : edgeOfOneButton;
return CGSizeMake(edgeOfOneButton, edgeOfOneButton);
}

How to rotate button back to horizontal?

I'm making a circle with different buttons all over, spaced out at equal intervals.
Here's what it looks like :
I want to make it so that the picture doesn't rotate. How do I achieve that ? Here's the code.
- (void)drawWheel
{
// Drawing the Wheel view
wheelView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 275, 275)];
wheelView.center = self.view.center;
wheelView.layer.cornerRadius = wheelView.frame.size.width / 2.0;
wheelView.layer.borderColor = [UIColor whiteColor].CGColor;
//wheelView.layer.borderWidth = 0.5f;
CGFloat angleSize = 2 * M_PI / self.buttons.count;
for(int i = 0; i < self.buttons.count; i++)
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, wheelView.frame.size.width / 2.0, 40)];
label.layer.anchorPoint = CGPointMake(1.0f, 0.5f);
label.layer.position = CGPointMake(wheelView.bounds.size.width / 2.0, wheelView.bounds.size.height / 2.0);
label.transform = CGAffineTransformMakeRotation(angleSize * i);
label.backgroundColor = [UIColor clearColor];
UIButton *button = [self.buttons objectAtIndex:i];
button.center = CGPointMake(label.center.x, label.center.y + 15);
button.transform = CGAffineTransformRotate(label.transform, 2 * (angleSize * i));
[label addSubview:button];
[wheelView addSubview:label];
}
[self.view addSubview:wheelView];
}
I didn't check it, but could you change following code
button.transform = CGAffineTransformRotate(label.transform, 2 * (angleSize * i));
to
button.transform = CGAffineTransformMakeRotation(-1 * angleSize * i);
Here I am just rotating your button to opposite direction
You could do something like this I think...
- (void)drawWheel
{
// Drawing the Wheel view
wheelView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 275, 275)];
wheelView.center = self.view.center;
wheelView.layer.cornerRadius = wheelView.frame.size.width / 2.0;
wheelView.layer.borderColor = [UIColor whiteColor].CGColor;
//wheelView.layer.borderWidth = 0.5f;
CGFloat angleSize = 2 * M_PI / self.buttons.count;
for(int i = 0; i < self.buttons.count; i++)
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, wheelView.frame.size.width / 2.0, 40)];
label.layer.anchorPoint = CGPointMake(1.0f, 0.5f);
label.layer.position = CGPointMake(wheelView.bounds.size.width / 2.0, wheelView.bounds.size.height / 2.0);
label.transform = CGAffineTransformMakeRotation(angleSize * i);
label.backgroundColor = [UIColor clearColor];
UIButton *button = [self.buttons objectAtIndex:i];
button.center = CGPointMake(label.center.x, label.center.y + 15);
// change this line
button.transform = CGAffineTransformMakeRotation(-angleSize * i);
[label addSubview:button];
[wheelView addSubview:label];
}
[self.view addSubview:wheelView];
}
Here I am just transforming the button in the other direction with the same angle.
i.e. if the label is rotated 35 degrees then the button is rotated -35 degrees. This will mean the button is rotated 0 degrees relative to the sup review of the label.

Certain placement of UIButtons created in for loop

I want to create UIButtons and have them separated inside a UIScrollView with pages such as:
The buttons will go from left to right then down in rows until it gets to bottom of view. It will then go to next page of the UIScrollView and continue on.
Here's my code so far:
for(NSString *num in nums) {
UIButton *test = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[test addTarget:self action:#selector(numPressed:) forControlEvents:UIControlEventTouchUpInside];
test.frame = CGRectMake(0, 0, 70, 70);
[self.view addSubview:test];
}
Some code like this:
int xOff = 10;
int yOff = 50;
int btnGap = 20;
int page = 0;
for (NSString *num in nums) {
xOff += page * _scrollView.width;
for (int row = 0; row < 3; row++) {
for (int col = 0; col < 3; col++) {
UIButton *test = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[test addTarget:self action:#selector(numPressed:) forControlEvents:UIControlEventTouchUpInside];
test.frame = CGRectMake(xOff+col*(70+btnGap) , yOff+row*(70+btnGap), 70, 70);
test.backgroundColor = [UIColor redColor];
[test setTitle:num forState:UIControlStateNormal];
[_scrollView addSubview:test];
}
}
page++;
}
You need to change the coordinates when invokint CGRectMake:
NSInteger i, x, y;
for(NSString *num in nums) {
...
i = i%3;
if (i==0)
{
x = 0;
y += 70;
}
x += 80;
test.frame = CGRectMake(x, y, 70, 70);
...
}
This should give you an idea on how to proceed. Also, don't forget to place the title to each button.
If you're creating and setting UIButton objects by frame then I, personally, would do it this way (surely it can be improved / optimized)
Note: This does not incorporate any page logic so you'll need to adapt it yourself.
-(void)createButtonGrid
{
int i_btnWidth = 70;
int i_btnHeight = 70;
int i_btnX = 0;
int i_btnY = -70; //offset (for first iteration in for loop) [1]
int i_btnPadding = 20;
//number of columns
int i_screenDivisions = 3;
//width of every column
int i_screenDivisionWidth = self.view.frame.size.width / i_screenDivisions;
int i_count = 40; //or, maybe, nums.count as per your logic
for (int i = 0; i < i_count; i++) {
//which column a button goes in
int i_index = (i+i_screenDivisions)%i_screenDivisions;
//increase Y position when new row begins
if (i_index == 0) { //[1]
i_btnY += i_btnHeight + i_btnPadding;
}
//calculate X position (which will be placed at the centre of every column)
i_btnX = (i_index*i_screenDivisionWidth) + (i_screenDivisionWidth/2) - (i_btnWidth/2);
//----Button creation logic----
UIButton *btnTemp = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTemp setFrame:CGRectMake(i_btnX, i_btnY, i_btnWidth, i_btnHeight)];
NSString *strTitle = [NSString stringWithFormat:#"%d",i];
//or, maybe, as per your logic
//NSString *strTitle = nums[i];
[btnTemp setTitle:strTitle forState:UIControlStateNormal];
[btnTemp.titleLabel setTextColor:[UIColor yellowColor]];
//[btnTemp addTarget:self action:nil forControlEvents:UIControlEventTouchUpInside];
[btnTemp setTag:i]; //might need it later
[btnTemp setBackgroundColor:[UIColor colorWithRed:(float)(arc4random()%255)/255
green:(float)(arc4random()%255)/255
blue:(float)(arc4random()%255)/255
alpha:1.0f]];
[scrollView addSubview:btnTemp];
}
[scrollView setContentSize:CGSizeMake(self.view.frame.size.width, i_btnY + i_btnHeight)];
}

Create a dynamic row of UITextfields

I would like some help creating a dynamic row of UITextfields, I have been trying to do it myself with some success but mostly failure.
I set a number of rows between 1 - 13 and I would like to create UITextfields that fit inside the width of an iPhone frame width evenly spaced with an even gap to the left and right.
Here is what I have done so far:
- (void) displayViews {
// add scrollview
htmlContainerScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 60.0, self.view.frame.size.width, 293.0)];
NSInteger viewcount = [axisString integerValue];
color = 200;
for(int i = 0; i< viewcount; i++) {
color = color + 20;
NSLog(#"%f", color);
CGFloat y = i * 91;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, y,self.view.frame.size.width, 90.0)];
view.backgroundColor = [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:(1.0/i)];;
[htmlContainerScrollView addSubview:view];
int cutCount = [cutsString integerValue];
int positions = (self.view.frame.size.width/cutCount);
for (int i = 0; i < cutCount; i++) {
//first one
UITextField *cutField = [[UITextField alloc] initWithFrame:CGRectMake((positions*i)+(20/2), 25, 20, 20)];
cutField.textColor = [UIColor colorWithRed:0/256.0 green:84/256.0 blue:129/256.0 alpha:1.0];
cutField.font = [UIFont fontWithName:#"Helvetica-Bold" size:25];
cutField.backgroundColor=[UIColor whiteColor];
[view addSubview:cutField];
}
}
htmlContainerScrollView.contentSize = CGSizeMake(self.view.frame.size.width, 91 *viewcount);
[self.view addSubview:htmlContainerScrollView];
}
The biggest problem with mine is that it does not evenly space them; they are always to the left.
change your cutField's frame x coordinate value calculation from
(positions*i)+(20/2)
to
((positions*i)-(20/2)+(positions/2)).
that should do the trick.
it's just a matter of the x coordinate calculation and i am sure there is room to optimize that a bit.

Poor UIScrollView Performance with Many Subviews

I am building a simple app which displays a users Contacts with photos like this -
The contacts are each a positioned subview, with another subview inside containing a UIImageView to generate the images w/rounded corners and a UILabel.
Scrolling becomes rather choppy on both iPhone 4/4s and iPhone 5, however, even with only 6-7 contacts. Also, the choppyness seems to be constant. It doesn't matter if they have 8 contacts or 500 contacts, it doesn't get worse or better either way.
Does anybody know why this might be? The algorithm that generated this grid can be seen below. Are there any specific properties on the UIScrollView I haven't set, etc?
- (void) generateContactGrid
{
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(self.addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(self.addressBook);
int peopleInARow = 0;
int maxPeopleInARow = 3;
int positionFromTop = 20;
int IMAGE_SIZE = 70;
float animationOffset = .5;
float animationOffsetChange = .3;
float animationDuration = .5;
int scaleOffset = 40;
int screenWidth = 320;
int startingPositionFromLeft = 26;
int positionFromLeft = startingPositionFromLeft;
int topOffset = 40;
int leftOffset = 26;
int numberOfRows = 0;
UIView *contactContainer;
UIImage* image;
CALayer *l;
NSString *name;
NSString *lastName;
NSString *firstName;
UIImageView *newimageview;
UILabel *label;
UIView *contactImageContainer;
for ( int i = 0; i < nPeople; i++ )
{
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
firstName = (__bridge_transfer NSString*)ABRecordCopyValue(person,kABPersonFirstNameProperty);
lastName = (__bridge_transfer NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
name = [NSString stringWithFormat:#"%# %#", firstName, lastName];
if(ABPersonHasImageData(person)){
NSLog(#"Current Contact Being Generated: %#", name);
image = [UIImage imageWithData:(__bridge NSData *)ABPersonCopyImageData(person)];
NSLog(#"Contact's Position From Left: %i", positionFromLeft);
newimageview = [[UIImageView alloc] initWithFrame:CGRectMake(-scaleOffset/2, -scaleOffset/2, IMAGE_SIZE+scaleOffset, IMAGE_SIZE+scaleOffset)];
newimageview.contentMode = UIViewContentModeScaleAspectFit;
[newimageview setImage: image];
contactContainer = [[UIView alloc] initWithFrame:CGRectMake(positionFromLeft, positionFromTop + 20, IMAGE_SIZE, 200)];
contactImageContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, IMAGE_SIZE, IMAGE_SIZE)];
contactImageContainer.clipsToBounds = YES;
l = [contactImageContainer layer];
[l setMasksToBounds:YES];
[l setCornerRadius:IMAGE_SIZE/2];
[l setBorderWidth:0.0];
[l setBorderColor:[[UIColor colorWithRed:234.0/255.0 green:234.0/255.0 blue:234.0/255.0 alpha:.6] CGColor]];
[contactImageContainer addSubview:newimageview];
[contactContainer addSubview:contactImageContainer];
label = [[UILabel alloc] initWithFrame: CGRectMake(0, IMAGE_SIZE + 10, IMAGE_SIZE, 20)];
label.text = firstName;
label.backgroundColor = [UIColor colorWithRed:0/255.0 green:0/255.0 blue:0/255.0 alpha:0];
label.textColor = [UIColor whiteColor];
[label setTextAlignment:NSTextAlignmentCenter];
[label setFont:[UIFont fontWithName:#"Arial-BoldMT" size:14]];
[contactContainer addSubview:label];
contactContainer.alpha = 0;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationDelay:animationOffset];
animationOffset+= animationOffsetChange;
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
contactContainer.alpha = 1;
CGRect temp = contactContainer.frame;
temp.origin.y = positionFromTop;
contactContainer.frame = temp;
[UIView commitAnimations];
if(peopleInARow >= 2){
positionFromTop += IMAGE_SIZE + topOffset;
peopleInARow = 0;
positionFromLeft = startingPositionFromLeft;
numberOfRows++;
} else {
peopleInARow += 1;
positionFromLeft += IMAGE_SIZE + leftOffset;
}
[self.scrollView addSubview:contactContainer];
[self.scrollView bringSubviewToFront:contactContainer];
}
}
NSLog(#"%i", numberOfRows);
self.scrollView.contentSize = CGSizeMake(screenWidth, 150 * numberOfRows);
}
Use Instruments to measure what exactly makes your app slow. Everything else is just guessing.
But I will guess anyways. This most likely is the masking you apply to your UIImageViews. Try disabling that and see if it is still slow (and by see I mean measure, of course). If that is indeed the cause there are two things you can try. First you can set the shouldRasterize property of the masked layer and see if that actually is enough. This could make things worse though if your layers get changed a lot. The other option would be to render those masked pictures with Core Graphics instead of using layers.

Resources