Create Grid of UIVews in NSArray - objective-c

What I am trying to do is align views in a grid that are in an array. I have created the views and the array.
for (int i = 0; i < [directoryContents count]; i++){
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0,0,100,120)];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(0, 0, 100, 100);
button.accessibilityIdentifier = [directoryContents objectAtIndex:i];
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, 100, 20)];
label.textAlignment = NSTextAlignmentCenter;
label.text = [directoryContents objectAtIndex:i];
[containerView addSubview:button];
[containerView addSubview:label];
[self.view addSubview:containerView];
[_containerViewArray addObject:containerView];
}
[self layoutViews:_containerViewArray inView:self.view];
What I have working is aligning them next to each other the problem I am having is I need to have them wrap down instead of going off the edge. What I am doing to algin them is this
- (void)layoutViews:(NSArray *)views inView:(UIView *)contentView
{
NSInteger overallWidth = 0;
for ( UIView *view in views ) {
overallWidth += view.frame.size.width;
}
CGSize contentSize = contentView.frame.size;
CGFloat startOffset = (contentSize.height - overallWidth)/2.0;
CGFloat offset = startOffset;
for ( UIView *view in views ) {
CGRect frame = view.frame;
frame.origin.x = offset;
view.frame = frame;
offset += view.frame.size.width;
}
}

If we assumed that we have an array of sections (your views) and you need to layout 3 item per row the view has size 98*98 and spacing 6.5px horizontally and 8px Vertically
for (int i = 0; i< [sectionsArray count]; i++) {
int row = (int)i/3;
int col = i%3;
float x = 6.5 + (104.5*col);
float y = 8 + (106*row);
UIView *sectionView = [[UIView alloc] initWithFrame:CGRectMake(x, y, 98, 98)];
sectionView.backgroundColor = [UIColor clearColor];
//button
UIButton *sectionButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[sectionButton setTintColor:[UIColor grayColor]];
sectionButton.frame = CGRectMake(0, 0, 98, 98);
sectionButton.tag = i+100;
[sectionButton addTarget:self action:#selector(showSectionDetail:) forControlEvents:UIControlEventTouchUpInside];
[sectionView addSubview:sectionButton];
//adding title
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 75, 98, 20)];
titleLabel.textAlignment = UITextAlignmentCenter;
titleLabel.backgroundColor=[UIColor clearColor];
titleLabel.font=[UIFont fontWithName:#"Helvetica" size:14];
titleLabel.textColor = [UIColor colorWithRed:241.0/255.0 green:124.0/255.0 blue:22.0/255.0 alpha:1.0];
titleLabel.text = [[sectionsArray objectAtIndex:i] objectForKey:#"Title"];
[sectionView addSubview:titleLabel];
[titleLabel release];
[scroll addSubview:sectionView];
[sectionView release];
}
int numberOfRows;
if ([sectionsArray count]/3.0f == 0) {
numberOfRows = [sectionsArray count]/3;
}else{
numberOfRows = [sectionsArray count]/3 +1;
}
scroll setContentSize:CGSizeMake(320, numberOfRows*106);

Here's what I used until the UICollectionView was released, easy to modify to accommodate for how many rows you want in the grid, and the size of the views.
NSUInteger buttonWidth = 100;
NSUInteger buttonHeight = 100;
NSUInteger space = 5;
float scrollContentY = (ceilf((float)imageNames.count / 3.0f) * (buttonHeight + space));
[myArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
int row = idx / 3;
int column = idx % 3;
UIView *view = [UIView new];
[view setBackgroundColor:[UIColor redColor]];
view.frame = CGRectMake((buttonWidth + space) * column + space, (buttonHeight + space) * row + space , buttonWidth, buttonHeight);
[view setTag:(NSInteger)idx];
[self.scrollView addSubview:view];
[self.scrollView setContentSize:CGSizeMake(self.scrollView.frame.size.width, scrollContentY)];
}];
Mind you, this might not be advisable if you have a large array to enumerate because this doesn't have any kind of reusable views. It will alloc/init a view for every item in the array.

Related

UIButton is not setting text

I seem to have a problem in my Objective C iOS app where I am creating multiple buttons depending on the amount of objects in an array. I know Swift, so I replicated the logic into Swift, and it worked. Yet in Objective C, I am unable to see the text of the button (after I remove the for loop) or create multiple buttons. For example, I have an array full of three names. I would like to create a button for each name with the title set to the corresponding name. So far, I have this:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *ages = [[NSMutableArray alloc] init];
for (int i = 0; i > 10; i++) {
[ages addObject:[NSString stringWithFormat:#"%i", i]];
}
UIScrollView *scrollView= [[UIScrollView alloc]initWithFrame:self.view.frame];
scrollView.delegate= self;
self.automaticallyAdjustsScrollViewInsets= NO;
scrollView.backgroundColor= [UIColor clearColor];
scrollView.scrollEnabled= YES;
scrollView.userInteractionEnabled= YES;
[scrollView setShowsHorizontalScrollIndicator:NO];
[scrollView setShowsVerticalScrollIndicator:NO];
CGFloat xValue = 0;
for(int x=0; x > ages.count; x++){
UIButton *button= [[UIButton alloc] initWithFrame:CGRectMake(xValue ,0 , 172 ,65)];
UIColor *buttonOutline = [[UIColor redColor] CGColor];
button.layer.borderColor = [buttonOutline CGColor];
button.layer.backgroundColor = [[UIColor clearColor] CGColor];
button.layer.borderWidth = 1.0;
button.layer.cornerRadius = 6.0;
[button.titleLabel setFont:[UIFont fontWithName:#"Helvetica" size:13.0]];
button.titleLabel.text = [ages objectAtIndex:x];
[button addTarget:self action:#selector(test:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
NSLog(#"Button Added");
xValue = button.frame.size.width + 40;
}
scrollView.contentSize = CGSizeMake(xValue, 65);
[self.view addSubview:scrollView];
}
- (void)test:(UIButton*)sender{
NSLog(#"Clicked %#", sender.titleLabel.text);
}
#end
If anyone sees anything wrong with this code, please point it out!
Thanks,
Arnav K.
I found four problems (there may be others) that stop this working correctly:
1) The for loop bound when setting up the ages array is incorrect.
2) The for loop bound when creating the buttons is incorrect.
3) You are setting the buttonOutline colour incorrectly.
4) xValue is being updated incorrectly.
Here is the viewDidLoad method after the changes have been made:
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *ages = [[NSMutableArray alloc] init];
for (int i = 0; i < 10; i++) { // UPDATED
[ages addObject:[NSString stringWithFormat:#"%i", i]];
}
UIScrollView *scrollView= [[UIScrollView alloc]initWithFrame:self.view.frame];
scrollView.delegate= self;
self.automaticallyAdjustsScrollViewInsets= NO;
scrollView.backgroundColor= [UIColor clearColor];
scrollView.scrollEnabled= YES;
scrollView.userInteractionEnabled= YES;
[scrollView setShowsHorizontalScrollIndicator:NO];
[scrollView setShowsVerticalScrollIndicator:NO];
CGFloat xValue = 0;
for(int x=0; x < ages.count; x++){ // UPDATED
UIButton *button= [[UIButton alloc] initWithFrame:CGRectMake(xValue ,0 , 172 ,65)];
UIColor *buttonOutline = [UIColor redColor]; // UPDATED
button.layer.borderColor = [buttonOutline CGColor];
button.layer.backgroundColor = [[UIColor clearColor] CGColor];
button.layer.borderWidth = 1.0;
button.layer.cornerRadius = 6.0;
[button.titleLabel setFont:[UIFont fontWithName:#"Helvetica" size:13.0]];
button.titleLabel.text = [ages objectAtIndex:x];
[button addTarget:self action:#selector(test:) forControlEvents:UIControlEventTouchUpInside];
[scrollView addSubview:button];
NSLog(#"Button Added");
xValue += button.frame.size.width + 40; // UPDATED
}
scrollView.contentSize = CGSizeMake(xValue, 65);
[self.view addSubview:scrollView];
}
I have marked the four lines I changed with a UPDATED comment so you can compare them to the original.
EDIT
To change the text and text colour use the following:
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
[button setTitle:[ages objectAtIndex:x] forState:UIControlStateNormal];
and remove this:
button.titleLabel.text = [ages objectAtIndex:x];
You need to do this because you can set different text for the different states of the button and this is all handled automatically for you.

Horizontal UIScrollView with multiple textfields to display

I'm new to Xcode. I want to make a UIScrollView with multiple pages and each page having multiple UITextFields which vary on each page. I made UIScrollView with paging enabled. Now I'm stuck at displaying textfield's on scroll pages.
Here is my code so far:
//set the paging to yes
self.scrollview.pagingEnabled = YES;
// create 5 pages
NSUInteger numberOfViews = 5;
for (int i = 0; i < numberOfViews; i++)
{
//set the origin of the sub view
CGFloat myOrigin = i * self.view.frame.size.width;
//create the sub view and allocate memory
myView = [[UIView alloc] initWithFrame:CGRectMake(myOrigin, 0, self.view.frame.size.width, self.view.frame.size.height)];
//create a label and add to the sub view
CGRect myFrame = CGRectMake(10.0f, 10.0f, 200.0f, 25.0f);
textLabel = [[UILabel alloc] initWithFrame:myFrame];
textLabel.font = [UIFont boldSystemFontOfSize:16.0f];
textLabel.textAlignment = NSTextAlignmentLeft;
[myView addSubview:textLabel];
//create a text field and add to the sub view
myFrame.origin.y += myFrame.size.height + 10.0f;
textField = [[UITextField alloc] initWithFrame:myFrame];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.tag = i+1;
[myView addSubview:textField];
//set the background to different color
//set the scroll view delegate to self so that we can listen for changes
self.scrollview.delegate = self;
//add the subview to the scroll view
[self.scrollview addSubview:myView];
}
//scroll horizontally
self.scrollview.contentSize = CGSizeMake(self.view.frame.size.width * numberOfViews,
self.scrollview.frame.size.height);
//we set the origin to the 1rd page
CGPoint scrollPoint = CGPointMake(self.view.frame.size.width * 0, 0);
//change the scroll view offset the the 1rd page so it will start from there
[scrollview setContentOffset:scrollPoint animated:YES];
[self.view addSubview:self.scrollview];
}
Use This code here textfieldCount is
for (int j=0; j < textFieldCount; j++)
{
myFrame.origin.y += myFrame.size.height + 10.0f*(j+1);
UITextField *textField = [[UITextField alloc] initWithFrame:myFrame];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.tag = j+1;
[myView addSubview:textField];
}
Hope you got your answer.

Setting uibutton frame not working

I have values in dictionaries that will make a frame of a uibutton
tags = (
{
height = "15.513672";
text = jeans;
width = "39.808105";
x = "225.500000";
y = "265.000000";
},
{
height = "15.513672";
text = jacket;
width = "44.080078";
x = "190.000000";
y = "156.500000";
}
);
I set the frame of uibuttons with the values from the dictionaries
for (int i = 0; i<[tags count]; i++) {
NSLog(#"adding tags");
NSMutableDictionary *propertiesdict = [[NSMutableDictionary alloc] init];
propertiesdict = [[tags objectAtIndex:i] mutableCopy];
float x = [[dict objectForKey:#"x"] floatValue];
float y = [[dict objectForKey:#"y"] floatValue];
float width = [[dict objectForKey:#"width"] floatValue];
float height = [[dict objectForKey:#"height"] floatValue];
NSString *title = [dict objectForKey:#"text"];
UIButton *button = [[UIButton alloc] init];
[button setFrame:CGRectMake(x, y, width, height)];
[button setTitle:title forState:UIControlStateNormal];
button.layer.cornerRadius = 2.5;
//button.alpha = 0.9;
[button.titleLabel setFont:[UIFont systemFontOfSize:13]];
[button setBackgroundColor:[UIColor viewFlipsideBackgroundColor]];
button.tag = i;
[button addTarget:self action:#selector(tappedOnTag:) forControlEvents:UIControlEventTouchUpInside];
[tagsView addSubview:button];
}
After adding the buttons to the subview, the NSLog shows that each button has a frame (0,0,0,0) which differs from when I set the frame in the for loop.
2015-10-15 12:25:17.787 kyss[1018:316548] tapped on tags view. Number of subviews = 2. Subviews: (
"<UIButton: 0x15f732330; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x15f72eb60>>",
"<UIButton: 0x15f6d10e0; frame = (0 0; 0 0); opaque = NO; tag = 1; layer = <CALayer: 0x15f6b3790>>"
)
Let's take a look at the code...
for (int i = 0; i<[tags count]; i++) {
NSLog(#"adding tags");
NSMutableDictionary *propertiesdict = [[NSMutableDictionary alloc] init];
propertiesdict = [[tags objectAtIndex:i] mutableCopy];
You create a new dictionary and immediately overwrite the reference with an item from the tags array.
float x = [[dict objectForKey:#"x"] floatValue];
float y = [[dict objectForKey:#"y"] floatValue];
float width = [[dict objectForKey:#"width"] floatValue];
float height = [[dict objectForKey:#"height"] floatValue];
You reference dict, which isn't defined in the code you posted. It's safe to assume that it's not the same as propertiesdict, so you're getting nil references, thus the value 0 for each assignment.
NSString *title = [dict objectForKey:#"text"];
Again with the dict.
UIButton *button = [[UIButton alloc] init];
[button setFrame:CGRectMake(x, y, width, height)];
[button setTitle:title forState:UIControlStateNormal];
button.layer.cornerRadius = 2.5;
//button.alpha = 0.9;
[button.titleLabel setFont:[UIFont systemFontOfSize:13]];
[button setBackgroundColor:[UIColor viewFlipsideBackgroundColor]];
button.tag = i;
[button addTarget:self action:#selector(tappedOnTag:) forControlEvents:UIControlEventTouchUpInside];
[tagsView addSubview:button];
}
The rest of the code is ok.
Anyway, your problem is referencing the wrong dictionary. Did you not notice that the title is wrong too?

UIScrollView subview not always clickable

I'm adding subviews to an UIScrollView. For this question I'm simplifying the added view : testView it contains an UIButton
My Scroll View is working great, but the touch on the buttons is not working well.
I can click on the first button but only on the (approximative) 100 first pixels.
the scrolling is working very well.
I cannot click on the end of the first button
I cannot click on the other buttons
here is my code :
__block CGFloat scrollViewContentSize = 0;
__block CGFloat buttonRectOrigineY = 0;
[self.itemsToDisplay enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
CGRect frameTest = CGRectMake(0, buttonRectOrigineY/2, 320, 200);
UIButton *testButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
testButton.frame = frameTest;
UIView *testView = [[UIView alloc] initWithFrame:frameTest];
[testView addSubview:testButton];
[self.articleScrollView addSubview:testView];
buttonRectOrigineY += 200;
scrollViewContentSize += 200;
}];
[self.articleScrollView setContentSize:CGSizeMake(320, scrollViewContentSize)];
here is image to understand well my problem :
You can use bringSubviewToFront to avoid the issue
CGRect frameTest = CGRectMake(0, buttonRectOrigineY/2, 320, 200);
UIButton *testButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
testButton.frame = frameTest;
UIView *testView = [[UIView alloc] initWithFrame:frameTest];
[testView addSubview:testButton];
[testView bringSubviewToFront:testButton];
[self.articleScrollView addSubview:testView];
[self.articleScrollView bringSubviewToFront:testView];
If you have issues again, apply boarder around the button and check it the button area that visible manually.
I was mistaking the frame of my button and view. Here a working code if it can help anyone.
__block CGFloat scrollViewContentSize = 0;
__block CGFloat buttonRectOrigineY = 0;
[self.itemsToDisplay enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
CGRect frameTestButton = CGRectMake(0, 0, 300, 150);
CGRect frameTestView = CGRectMake(10, buttonRectOrigineY, 300, 200);
UIButton *testButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
testButton.frame = frameTestButton;
testButton.backgroundColor = [UIColor greenColor];
UIView *testView = [[UIView alloc] initWithFrame:frameTestView];
if(idx == 0)
testView.backgroundColor = [UIColor yellowColor];
if(idx == 1)
testView.backgroundColor = [UIColor orangeColor];
if(idx == 2)
testView.backgroundColor = [UIColor redColor];
if(idx == 3)
testView.backgroundColor = [UIColor magentaColor];
if(idx == 4)
testView.backgroundColor = [UIColor purpleColor];
if(idx <= 4){
LogDebug(#"idx : %lu", (unsigned long)idx);
[testView addSubview:testButton];
[self.articleScrollView addSubview:testView];
[self.articleScrollView bringSubviewToFront:testView];
buttonRectOrigineY += 200;
scrollViewContentSize += 200;
}
}];
[self.articleScrollView setContentSize:CGSizeMake(320, scrollViewContentSize)];

More than 1 image on a subview not loading

I'm trying to add images over a ScrollView. I have the x and y point in a plist file and they are called by an enum.
enum {
kLogoImage = 1,
kNewLogoImage,
};
#implementation
- (void) _setupStaticViews
{
UIButton *image = [UIButton buttonWithType:UIButtonTypeCustom];
[image setBackgroundImage:[UIImage imageNamed:#"logo.png"] forState:UIControlStateNormal];
[image addTarget:self action:#selector(_addContactButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
image.frame = CGRectMake(0.0 ,0.0, 150.0, 150.0);
image.tag = kLogoImage;
[_mapImageView addSubview:image];
_staticViews = #[image];
UIButton *image2 = [UIButton buttonWithType:UIButtonTypeCustom];
[image2 setBackgroundImage:[UIImage imageNamed:#"Time Bakground.png"] forState:UIControlStateNormal];
[image2 addTarget:self action:#selector(_addContactButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
image2.frame = CGRectMake(0.0 ,0.0, 250.0, 150.0);
image2.tag = kNewLogoImage;
[_mapImageView addSubview:image2];
_staticViews = #[image2];
for ( UIView *view in _staticViews ) {
CGPoint point = [self _basePositionForView:view];
CGRect frame = view.frame;
frame.origin = point;
view.frame = frame;
}
}
If I have only image showing, it works fine. But I need to add more than one and adding the second one causes the first one to be at xy point 0,0, and Image2 isn't visible.
How would I go about adding another image?
- (CGPoint) _basePositionForView:(UIView *)view {
NSString *key = [NSString stringWithFormat:#"%d", view.tag];
NSString *stringValue = [_coordinates objectForKey:key];
NSArray *values = [stringValue componentsSeparatedByString:#":"];
if ( [values count] < 2 ) return CGPointZero;
CGPoint result = CGPointMake([[values objectAtIndex:0] floatValue], [[values objectAtIndex:1] floatValue]);
return result;
}
I noticed that you first make
_staticViews = #[image];
and later
_staticViews = #[image2];
Don't you rather mean to have
_staticViews = #[image, image2];
?
You should iterate and change x accordingly in the frame:
for ( int iterator=0; iterator< [[_staticViews subviews] count]; iterator++){
...
current_image.frame = CGRectMake(YOUR_IMG_WIDTH * iterator ,0.0, YOUR_IMG_WIDTH, 150.0);
...}