i want to fill area (UIView) with buttons(UIButton) so that they do not intersect with each others.
My idea:
create initial button at random position in view;
fill view with other buttons from initial button (count < 20) that they do not intersect ~10 pixels from each other.
What have i done so far:
I created method:
-(void)generateButtonsForView:(UIView *)view buttonCount:(int)count
{
//get size of main view
float viewWidth = view.frame.size.width;
float viewHeight = view.frame.size.height;
//set button at random position
UIButton *initialButton = [[UIButton alloc] initWithFrame:CGRectMake(arc4random() % (int)viewWidth,
arc4random() % (int)viewHeight,
buttonWidth, buttonHeight)];
[initialButton setBackgroundImage:[UIImage imageNamed:#"button"] forState:UIControlStateNormal];
[view addSubview:initialButton];
// set count to 20 - max number of buttons on screen
if (count > 20)
count = 20;
//fill view with buttons from initial button +- 10 pixels
for (int i=0;i<=count;i++)
{
//button
UIButton *otherButtons = [[UIButton alloc] init];
[otherButtons setBackgroundImage:[UIImage imageNamed:#"button"] forState:UIControlStateNormal];
...//have no idea what to do here
}
}
So i'm confused on the place where i want to generate the position of the other buttons, depending on the initial button. I do not know how to generate theirs position that they were at a distance of 5-10 pixels from each other... Any ideas how to realise this? Thanks!
Here's an example with views rather than buttons, but the concept is the same. I use CGRectInset to give the new potential view a buffer of 10 points around it, then look for whether the new view intersects any of the other views. If there's no intersection, add the subview, if there is, try again with a new random location.
-(void)generateButtonsForView {
float viewWidth = self.view.frame.size.width;
float viewHeight = self.view.frame.size.height;
UIView *initialView = [[UIView alloc] initWithFrame:CGRectMake(arc4random() % (int)viewWidth, arc4random() % (int)viewHeight, 50, 30)];
initialView.backgroundColor = [UIColor redColor];
[self.view addSubview:initialView];
int numViews = 0;
while (numViews < 19) {
BOOL goodView = YES;
UIView *candidateView = [[UIView alloc] initWithFrame:CGRectMake(arc4random() % (int)viewWidth, arc4random() % (int)viewHeight, 50, 30)];
candidateView.backgroundColor = [UIColor redColor];
for (UIView *placedView in self.view.subviews) {
if (CGRectIntersectsRect(CGRectInset(candidateView.frame, -10, -10), placedView.frame)) {
goodView = NO;
break;
}
}
if (goodView) {
[self.view addSubview:candidateView];
numViews += 1;
}
}
}
Related
i am creating an application, where i am using UIScrollView for displaying the number of available colors of each product. I am getting number of available colors at run time, so i have used for loop and displaying on my scroll view. Its working fine, but the problem if i am getting only one available color then my output is coming as below screen :
But the output should be as below screen :
It seems like i need to do kind of center alignment for my UIScrollView, so every available color will suppose to display from center. here is my code :
UIScrollView *availableColorScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 80)];
availableColorScrollView.backgroundColor = [UIColor clearColor];
availableColorScrollView.showsHorizontalScrollIndicator = YES;
availableColorScrollView.showsVerticalScrollIndicator=NO;
availableColorScrollView.pagingEnabled = YES;
for (int i = 0; i < arrayAvlbleColors.count; i++) {
CGRect frame;
frame.origin.x = 23 * i;
frame.origin.y = 0;
frame.size = availableColorScrollView.frame.size;
UIView *subview = [[UIView alloc] initWithFrame:frame];
UILabel *label = [[UILabel alloc] init];
[label setFrame:CGRectMake(15, 14, 16, 16)];
[label.layer setCornerRadius:8];
NSString *strColorCode = [arrayAvlbleColors objectAtIndex:i];
strColorCode = [strColorCode substringFromIndex:1];
[label setBackgroundColor:[self colorWithHexString:strColorCode]];
[subview addSubview:label];
[availableColorScrollView addSubview:subview];
}
[self.view addSubview:availableColorScrollView];
availableColorScrollView.contentSize = CGSizeMake(24 * arrayAvlbleColors.count, availableColorScrollView.frame.size.height);
Please suggest me to achieve my output, Thanks!
this is the simple answer but working fine if u taken any Mainview or subview or else,
set the frame size/2 for height and width it automatically set it into center of the subview.
here i used static color , customize urself
just change your line this
NSString *strColorCode = [arrayAvlbleColors objectAtIndex:i];
strColorCode = [strColorCode substringFromIndex:1];
[label setBackgroundColor:[self colorWithHexString:strColorCode]];
[subview addSubview:label];
[availableColorScrollView addSubview:subview];
into
NSString *strColorCode = [arrayAvlbleColors objectAtIndex:i];
strColorCode = [strColorCode substringFromIndex:1];
[label setBackgroundColor:[self colorWithHexString:strColorCode]];
//use any one
//option no 1:
//[label setCenter:subview.center];
//option no 2:
[ label setCenter:CGPointMake(subview.frame.size.width / 2, subview.frame.size.height / 2)];
[subview addSubview:label];
[availableColorScrollView addSubview:subview];
final out put is
You can calculate your scrollview content to be placed in centre like this:
float contentWidth = 23 * arrayAvlbleColors.count;
Now you have content width to subtract from scrollView's width
float centerPadding = 0.0f;
float width = availableColorScrollView.frame.size.width;
centerPadding = width - contentWidth;
if(centerPadding < 0)
{
//content cannot be placed in center as content is bigger than width
centerPadding = 0.0f;
}
We have padding to center our content in scrollView, so use it in for loop like this :
frame.origin.x = (23 * i) + centerPadding;
I would like to add buttons to an UIView. The number of buttons varies from view to view.
I want to achieve the following:
I tried to add the Buttons (in a foreach construct) like this:
UIButton *but=[UIButton buttonWithType:UIButtonTypeRoundedRect];
but.frame= CGRectMake(200, 15, 15, 15);
[but setTitle:#"Ok" forState:UIControlStateNormal];
[but addTarget:self action:#selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:but];
But I don't know how to calculate the CGRectMake when it comes to an new line. How can I check the end of the line (UIView)? Or is it kinda stupid to add Buttons like this?
Thanks
Florian
You need to add calculate buttons size after you set the title. Then keep track of the current X and Y of the previous buttons and figure out if the newly created button can fit on the current "line". Otherwise go to the next one.
I suggest you to look at existing components and see how they do it, below are a couple links.
https://github.com/domness/DWTagList
https://github.com/andreamazz/AMTagListView
With the following code , you can place multiple buttons in one row as long as their total width and the gap is smaller then the view's width.
UIView *view = nil;
NSArray *allBtns = nil;
float viewWidth;
float currentY = 0;
float currentX = 0;
float btnGapWidth = 10.0;
float btnGapHeight = 2.0;
for (UIButton *btn in allBtns) {
CGRect rc = btn.frame;
BOOL shouldAddToNewLine = viewWidth - currentX - btnGapWidth < rc.size.width ? YES : NO;
if (shouldAddToNewLine) {
rc.origin = CGPointMake(0, currentY + rc.size.height + btnGapHeight);
currentX = 0;
currentY += rc.size.height + btnGapHeight;
} else {
//another row
rc.origin = CGPointMake(currentX + rc.size.width + btnGapWidth, currentY);
currentX += rc.size.width + btnGapWidth;
}
btn.frame = rc;
[view addSubview:btn];
}
I've got a UITableView and I want to add a button just underneath the table. The table is bigger than the screen so to get to the button, I need to scroll down to it. The problem is, the screen will scroll to just above where the button is. So I can drag the screen slightly and the button is visible but when I let go, the screen springs back and I can't get to the button.
The button is set up as follows
for(int i = 0; i < [buttonArray count]; i++)
{
UIButton *but = [buttonArray objectAtIndex:i];
float xPosition = but.frame.origin.x;
float xGap = (self.view.frame.size.width - (but.frame.size.width)*2)/3;
if ((i % 2 == 0) && (i < [buttonArray count] - 1))
{
xPosition = xGap;
}
else if ((i % 2 == 1) && (i < [buttonArray count] - 1))
{
xPosition = (xGap * 2) + but.frame.size.width;
}
else
{
xPosition = (self.view.frame.size.width - but.frame.size.width)/2;
}
//Add space between row of buttons
if(i > 0)
{
if(i % 2 == 0)
{
yPosition+=but.frame.size.height;
CGRect screenRect = [[tableView superview] bounds];
//Add extra space between row of buttons
float fGap = (screenRect.size.height / 100.0) * 4.5;
yPosition+=fGap;
}
}
CGRect rect = CGRectMake(xPosition, yPosition, but.frame.size.width, but.frame.size.height);
but.frame = rect;
[but addTarget:self action:#selector(genericMethod:) forControlEvents:UIControlEventTouchUpInside];
CGRect screenRect = [self.view bounds];
CGFloat fHeight = screenRect.size.height;
float fMargin = (fHeight / 100.0) * 0.8;
but.titleEdgeInsets = UIEdgeInsetsMake(0, 0, fMargin, 0);
[tableView addSubview:but];
}
}
So I go through an array of buttons (only one button in the array in my current case) and set up the frames and position them into columns and add it as a subview to the tableView. Things I've tried are:
Increase the table footer size. This just makes the gap between the table and button increase and I still can't scroll down as far as the button.
Add the button to the footer. This kind of worked. I could get to the button, but the button was always on screen, not just static below the table.
Add the button to a separate view below the table and add that view to the viewController.view. This didn't work at all and the button wasn't displayed.
Set the tableView.tableFooterView equal to the button. This also kind of worked and I could reach the button but it wouldn't work when there is more than one button in the array above.
You should create a custom view. Inside that view you should add all the buttons created using buttonArray. Now, assign this custom view to tableFooterView.
UIView *customView = [[UIView alloc] initWithFrame:properFrame];
for(int i = 0; i < [buttonArray count]; i++)
{
//...calculation of frame and other stuff
[customView addSubview:but];
}
tableView.tableFooterView = customView;
This should solve your scrolling issue.
If you want to make bottom view as stable,Take a UIView at the bottom
of UITableView.
If you will use TableFooterView,It will be at the end of cell .
I'm working on an iPad app and part of the UI is a scrollview that has buttons for its contents. I'm working on adding images to these buttons, but when I do so, I only ever get the image in one spot, when I should be seeing it on all the buttons. This is what I'm doing:
float scrollCurrTop = 0;
CGRect currProcedureButtonFrame = CGRectMake(0,
scrollCurrTop,
self.fProceduresView.frame.size.width,
self.fLabelAndButtonHeight);
PatientIDButton* currProcedureButton = [PatientIDButton buttonWithType:UIButtonTypeCustom];
[currProcedureButton setFrame:currProcedureButtonFrame];
[currProcedureButton.layer setBorderColor: [self.fPanelViewBorderColor CGColor]];
[currProcedureButton.layer setBorderWidth: self.fBorderWidth];
currProcedureButton.titleLabel.font = self.fLabelFont;
NSString* displayName = [grabbing name];
if (displayName == nil)
{
displayName = currPlanName;
}
[currProcedureButton setTitle:displayName
forState:UIControlStateNormal];
[currProcedureButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
currProcedureButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
currProcedureButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
// is the plan approved?
if ([self isPlanApproved:currPlanName])
{
// add the checkmark to this plan button
CGRect currPlanButtonFrame = currProcedureButton.frame;
float originX = currPlanButtonFrame.size.width - (currPlanButtonFrame.size.width/3.0f);
float originY = currPlanButtonFrame.origin.y;
float width = currPlanButtonFrame.size.width - originX;
float height = currPlanButtonFrame.size.height;
CGRect currPlanApprovalImageFrame = CGRectMake(originX, originY, width, height);
UIImageView* currPlanApprovalImage = [[UIImageView alloc] initWithFrame:currPlanApprovalImageFrame];
[currPlanApprovalImage setBackgroundColor:[UIColor colorWithRed:(63.0f/255.0f)
green:(179.0f/255.0f)
blue:(79.0f/255.0f)
alpha:1.0f]];
[currPlanApprovalImage setImage:self.fCheckMarkIcon];
[currProcedureButton addSubview:currPlanApprovalImage];
}
[self.fProceduresView addSubview:currProcedureButton];
scrollCurrTop += self.fLabelAndButtonHeight;
Where 'fProceduresView' is the scrollview that houses the buttons. What am I doing wrong?
It seems that you're misunderstanding the logic behing setting the frame of the imageview's those you're trying to add
CGRect currPlanButtonFrame = currProcedureButton.frame;
float originX = currPlanButtonFrame.size.width - (currPlanButtonFrame.size.width/3.0f);
float originY = currPlanButtonFrame.origin.y;
float width = currPlanButtonFrame.size.width - originX;
float height = currPlanButtonFrame.size.height;
CGRect currPlanApprovalImageFrame = CGRectMake(originX, originY, width, height);
UIImageView* currPlanApprovalImage = [[UIImageView alloc] initWithFrame:currPlanApprovalImageFrame];
You don't need to set originY to currPlanButtonFrame.origin.y;
All subviews have relative coordinates to their's superviews.
So in your case originY should be 0
For example:
// Image is visible
Button frame [0, 0, 100, 100]
image in button [0, 0, 100, 100]
// Button is visible, but image is not because it will be clipped by bounds of the button.
Button frame [100, 100, 100, 100]
image in button [100, 100, 100, 100]
Also you will be able to "see" your images, if you set
currProcedureButton.clipsToBounds = NO
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.