Dynamic generate buttons - ios

I want to dynamic generate a few buttons, the number will be given by background. When I get it, I must use it to create the corresponding number buttons,each button will be the same size and the space between them are the same, if the button can not contain in a row, it will line feed. The minimum width will be a constant,but the actual length will be according title text of the button.
My code is below, but it can't line feed, also I don't know how to use the text to determine the length of the button, grateful for any guidance.
- (void)viewDidLoad {
[super viewDidLoad];
CGFloat testHeight = 50;
CGFloat testWidth = 100;
CGFloat spaceing = 10;
int number = 5;
for (int i = 0; i < number; i++) {
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(spaceing + testWidth * i + spaceing * i , 100 , testWidth, testHeight )];
[button setBackgroundColor:[UIColor redColor]];
[self.view addSubview:button];
}
}

You could use a UICollectionView to do this, but it is not difficult to implement just using an array of UIButtons. You can use sizeToFit to have the button size itself based on its title. To get your buttons to wrap you should just check if it will extend past the max x of the view you are adding them to, in your case self.view.
For example you could say something like:
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *buttonStrings = #[#"how", #"now", #"brown", #"cow", #"the", #"quick", #"brown", #"fox"];
NSMutableArray *buttons = [[NSMutableArray alloc]initWithCapacity:[buttonStrings count]];
for (NSString *string in buttonStrings)
{
UIButton *button = [self buttonForString:string];
[buttons addObject:button];
}
[self layoutButtonArray:buttons inView: self.view];
}
// takes an array of buttons and adds them as subviews of view
- (void)layoutButtonArray:(NSArray<UIButton *> *)buttons inView:(UIView *)view
{
CGFloat spacing = 10.0;
CGFloat xOffset = spacing;
CGFloat yOffset = spacing;
for (UIButton *button in buttons)
{
if((xOffset + button.bounds.size.width + spacing) > CGRectGetMaxX(view.bounds))
{
xOffset = spacing;
yOffset += (button.bounds.size.height + spacing);
}
button.frame = CGRectMake(xOffset, yOffset, button.bounds.size.width, button.bounds.size.height);
[view addSubview:button];
xOffset += (button.bounds.size.width + spacing);
}
}
// Takes a string returns a button sized to fit
- (UIButton *) buttonForString:(NSString *)string
{
UIButton *button = [[UIButton alloc]initWithFrame:CGRectZero];
button.backgroundColor = [UIColor redColor];
[button setTitle:string forState:UIControlStateNormal];
[button sizeToFit];
// if you want to have a minimum width you can add that here
button.frame = CGRectMake(button.frame.origin.x, button.frame.origin.y, MAX(button.frame.size.width, kMinWidth), button.frame.size.height);
return button;
}

Related

Bringing UiScrollView element to center when clicked

What I have is UIScrollView and inside it I have buttons of different different sizes.
- (void)viewDidLoad {
[super viewDidLoad];
myScrollView.frame = CGRectMake(0, 100, 375, 50.0);
int totalButtonsToAdd = 20;
startX = 0;
int buttonWidth = 60;
for (int i=0;i<totalButtonsToAdd;i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:[NSString stringWithFormat:#"Btn-%d", i] forState:UIControlStateNormal];
[button setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
button.accessibilityValue = [NSString stringWithFormat:#"%d", i+1];
button.frame = CGRectMake(startX, 0, buttonWidth, 50.0);
[[button layer] setBorderWidth:2.0f];
[[button layer] setBorderColor:[UIColor greenColor].CGColor];
button.layer.cornerRadius = 5;
startX = startX + buttonWidth + 5;
buttonWidth = buttonWidth + 5;
[myScrollView addSubview:button];
}
NSLog(#"startX===%d", startX);
myScrollView.contentSize = CGSizeMake(startX, 50.0);
}
-(IBAction)aMethod:(id)sender {
UIButton *mButton = (UIButton *)sender;
NSLog(#"clicked button index is %#", mButton.accessibilityValue);
}
What I want to do is when I click any button, I want to bring that button in center. For this I believe I will need to scroll the scrollview to specific position.
For this what I did is as below.
- (void)viewDidLoad {
[super viewDidLoad];
myScrollView.frame = CGRectMake(0, 100, 375, 50.0);
int totalButtonsToAdd = 20;
startX = 0;
int buttonWidth = 60;
for (int i=0;i<totalButtonsToAdd;i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:[NSString stringWithFormat:#"Btn-%d", i] forState:UIControlStateNormal];
[button setTitleColor:[UIColor greenColor] forState:UIControlStateNormal];
button.accessibilityValue = [NSString stringWithFormat:#"%d", i+1];
button.frame = CGRectMake(startX, 0, buttonWidth, 50.0);
[[button layer] setBorderWidth:2.0f];
[[button layer] setBorderColor:[UIColor greenColor].CGColor];
button.layer.cornerRadius = 5;
startX = startX + buttonWidth + 5;
NSLog(#"startX===%d==%d", i, startX);
buttonWidth = buttonWidth + 5;
[myScrollView addSubview:button];
}
NSLog(#"startX final===%d", startX);
myScrollView.contentSize = CGSizeMake(startX, 50.0);
}
-(IBAction)aMethod:(id)sender {
UIButton *mButton = (UIButton *)sender;
NSLog(#"clicked button index is %#", mButton.accessibilityValue);
focusPosition = 0;
int totalButtonsToAdd = 20;
int buttonWidth = 60;
startX = 0;
for (int i=0;i<totalButtonsToAdd;i++) {
startX = startX + buttonWidth + 5;
buttonWidth = buttonWidth + 5;
if (i==[mButton.accessibilityValue intValue]) {
focusPosition = startX;
}
}
NSLog(#"focusPosition===%d", focusPosition);
CGRect frame = CGRectMake(focusPosition, 0, buttonWidth, 50); //wherever you want to scroll
[myScrollView scrollRectToVisible:frame animated:NO];
}
However this don't give me exact what I want. Is there any property for scrollview that will bring that button in center?
Project with above code
Note: This is sample for iPhone 6 only. So please run project on iPhone 6 simulator only
UICollectionView would probably have been a better choice than a UIScrollView, since it adds a method to achieve just what you want (scrollToItemAtIndexPath:atScrollPosition:animated:).
If you're sticking with UIScrollView, you'll need to use setContentOffset:animated: instead, and compute the desired offset, e.g.:
-(IBAction)aMethod:(UIButton *)button {
CGPoint contentOffset = CGPointMake(CGRectGetMidX(button.frame) - (CGRectGetWidth(self.scrollView.frame) / 2.0),0.0);
[myScrollView setContentOffset:contentOffset animated:YES];
}
The UIScrollView function
- (void)scrollRectToVisible:(CGRect)rect
animated:(BOOL)animated
does almost that.
Reference says: "This method scrolls the content view so that the area defined by rect is just visible inside the scroll view. If the area is already visible, the method does nothing."
Sorry, just saw you've already found that function.
Here is the link of a sample project which is doing the same as you want.
This include one class named PagedFlowView.
sample project to center a view in scrollview

How to take button at the center of the UIScrollView?

I am generating multiple buttons in my scrollview, A scroll view that has constrains at main.storyboard so it's width changes on different iphones. and i can't make my buttons to the center. Here is my code.
#synthesize table,scroll;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
img = #[#"Shirley-Stevens.jpg"];
NSUInteger i;
int buttonWidth=50;
int buttonHeight=50;
int space = 50;
// int xCoord= 100;// (scroll.frame.size.width/2) - buttonWidth - space;
// int Xcoord2= 200;//(scroll.frame.size.width/2) + buttonWidth + space;
int xCoord = (scroll.contentSize.width/2) + buttonWidth + space + buttonWidth + space;
int Xcoord2= (scroll.contentSize.width/2) + buttonWidth + space;
int yCoord=0;
int buffer = 10;
for (i = 1; i <= 100; i++)
{
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
[aButton setBackgroundImage:[UIImage imageNamed:[img objectAtIndex:0]]forState:UIControlStateNormal];
aButton.frame = CGRectMake(xCoord, yCoord,buttonWidth,buttonHeight );
[aButton addTarget:self action:#selector(whatever:) forControlEvents:UIControlEventTouchUpInside];
[scroll addSubview:aButton];
UIButton *bButton = [UIButton buttonWithType:UIButtonTypeCustom];
[bButton setBackgroundImage:[UIImage imageNamed:[img objectAtIndex:0]]forState:UIControlStateNormal];
bButton.frame = CGRectMake(Xcoord2, yCoord,buttonWidth,buttonHeight );
[bButton addTarget:self action:#selector(whatever:) forControlEvents:UIControlEventTouchUpInside];
[scroll addSubview:bButton];
yCoord += buttonHeight + buffer;
}
[scroll setContentSize:CGSizeMake(300, yCoord)];
}
- (IBAction)whatever:(UIButton *)sender {
NSLog(#"Button");
}
Here is my Code Now that works fine, Basically the problem is, viewDidLoad called before the parameters of scrollview updates. So the best method to practice scrollview is viewDidAppear.
#synthesize table,scroll;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
img = #[#"Shirley-Stevens.jpg",
#"Shirley-Stevens.jpg"];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSUInteger i;
int buttonWidth=50;
int buttonHeight=50;
int space = 50;
int xCoord = (scroll.frame.size.width/2) - buttonWidth - space;
int Xcoord2 = (scroll.frame.size.width/2) + space;
int yCoord=0;
int buffer = 10;
for (i = 1; i <= 100; i++)
{
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeCustom];
[aButton setBackgroundImage:[UIImage imageNamed:[img objectAtIndex:0]]forState:UIControlStateNormal];
aButton.frame = CGRectMake(xCoord, yCoord,buttonWidth,buttonHeight );
[aButton addTarget:self action:#selector(whatever:) forControlEvents:UIControlEventTouchUpInside];
[scroll addSubview:aButton];
UIButton *bButton = [UIButton buttonWithType:UIButtonTypeCustom];
[bButton setBackgroundImage:[UIImage imageNamed:[img objectAtIndex:0]]forState:UIControlStateNormal];
bButton.frame = CGRectMake(Xcoord2, yCoord,buttonWidth,buttonHeight );
[bButton addTarget:self action:#selector(whatever:) forControlEvents:UIControlEventTouchUpInside];
[scroll addSubview:bButton];
yCoord += buttonHeight + buffer;
}
[scroll setContentSize:CGSizeMake(300, yCoord)];
}
- (IBAction)whatever:(UIButton *)sender {
NSLog(#"Button");
}
I think you should make changes only below two line -
Assume that you need two button in center with space gap in between.
int xCoord = (scroll.contentSize.width/2) - (space/2) - buttonWidth;
int Xcoord2= (scroll.contentSize.width/2) + (space/2);
Hope this will help you.
Set the center point of UIButton along with frame.
For example: Set the center point at width/2 & height/2 of UIScrollView.

How to scroll a UIScrollView horizontally based on the buttons frame size inside the UIScrollview

Initially I need to add one default button on a scrollView.
Then, if I add one more button on the scrollView, the first default button should move to the left.
I am using this code:
int x = 0;
for (int i = 0; i < pullscount ; i++) {
NSString *myString = [pullsarray objectAtIndex:i];
CGSize stringsize = [myString sizeWithFont:[UIFont systemFontOfSize:16]];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(x, 5, 100, 40)];
[button setTitle:[pullsarray objectAtIndex:i] forState:UIControlStateNormal];
[button setFont:[UIFont fontWithName:#"SegoeWP-Semibold" size:15.0]];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[button addTarget:self
action:#selector(buttonAction:)
forControlEvents:UIControlEventTouchUpInside];
[button setTag:190+i];
[topScrollView addSubview:button];
x += button.frame.size.width+30;
}
NSLog(#"%d",x);
topScrollView.contentSize = CGSizeMake(x+200, topScrollView.frame.size.height);
topScrollView.backgroundColor = [UIColor clearColor];
In scrollViewDidScroll delegate method:
NSLog(#"%f",button.frame.size.width);
CGFloat pageWidth = button.frame.size.width;
NSLog(#"%f",pageWidth);
if (topScrollView.contentSize.width>pageWidth) {
float stopx = 100.0f;
if (topScrollView.contentSize.width >= stopx) {
CGPoint stop = topScrollView.contentOffset;
NSLog(#"Value – %#", NSStringFromCGPoint(stop));
stop.x = stopx;
[topScrollView setContentOffset:stop animated:YES];
}
}
else if (topScrollView.contentOffset.x >= 110.0f && topScrollView.contentOffset.x <= 220.0f) {
float stopx = 210.0f;
CGPoint stop1 = topScrollView.contentOffset;
stop1.x = stopx;
[topScrollView setContentOffset:stop1 animated:YES];
topScrollView.contentOffset = stop1;
}
}
My requirement is that i want to scroll the UIButtons in a tableViews `headerView.
Hence I took the scrollView and placed UIButtons dynamically.
When I scroll the scrollView horizontally, it has to move horizontally as per the button's width.
I also need to be highlight the button title at certain point on scrollview when i am scrolling.
If you simply want to scroll the scrollView by 100px width then check this scenario:
- (void)viewDidLoad {
//...
UIButton *btnGoRight = [UIButton buttonWithType:UIButtonTypeRoundedRect];\
[btnGoRight setTitle:#"Scroll Right" forState:UIControlStateNormal];
[btnGoRight addTarget:self
action:#selector(scrollMyScrollView)
forControlEvents:UIControlEventTouchUpInside];
[btnGoRight setFrame:CGRectMake(0, 0, self.view.frame.size.width, 30)];
[self.view addSubview:btnGoRight];
}
- (void)scrollMyScrollView {
if((topScrollView.contentOffset.x + topScrollView.frame.size.width) <= topScrollView.contentSize.width) {
CGPoint tempContentOffset = topScrollView.contentOffset;
tempContentOffset.x += 100; //to go right
[topScrollView setContentOffset: tempContentOffset animated:YES];
}
}
To go left:
Use another button (say, *btnGoLeft) and this conditional statement:
if((topScrollView.contentOffset.x + topScrollView.frame.size.width) >= 100) {
//...
tempContentOffset.x -= 100; //to go left
//...
}
Basically, we create 2 buttons (outside the scrollView) whose task is to simply scroll the scrollView to the right/left by 100px.
This is the basic concept and you can build on this to get what you're looking for
PS: Your question was vague (atleast to me) and it wasn't clear how you plan to scroll (on swipe or clicking on a button or something) or how many buttons you will have (roughly) in the scrollView so... there seemed to be multiple scenarios with what you're trying to do.
Hence, I wrote this... not as a complete answer to your question but, hopefully, to help you get on the right track.

Why isn't my UIPageControl updating when the ScrollView scrolls?

I'm trying to make a table whose cells have UIPageControls with ScrollViews in them. The ScrollViews work and the PageControls are there, but the PageControl does not update when scrolling happens except for on the bottom cell. Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.contentView.backgroundColor = [UIColor blueColor];
UIColor *color = [colorsArray objectAtIndex:indexPath.row];
scrollView = [[UIScrollView alloc] init];
[scrollView setDelegate:self];
CGRect screen = [[UIScreen mainScreen] bounds];
CGFloat width = CGRectGetWidth(screen);
CGFloat height = tableView.rowHeight;
scrollView.frame = CGRectMake(0, 0, width, height/1.25);
scrollView.contentSize=CGSizeMake(width*3,height/1.25);
scrollView.pagingEnabled = YES;
[scrollView setBackgroundColor:color];
[scrollView setShowsHorizontalScrollIndicator:NO];
scrollView.clipsToBounds = YES;
NSUInteger i;
int xCoord=width/25;
int yCoord=width/25;
int buttonWidth=width/8;
int buttonHeight=width/8;
int buffer = width;
for (i = 1; i <= 4; i++)
{
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
aButton.backgroundColor = [UIColor blackColor];
aButton.frame = CGRectMake(xCoord, yCoord,buttonWidth,buttonHeight );
[aButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
aButton.tag = i;
UIImage *buttonImage = [picsArray objectAtIndex:indexPath.row];
[aButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
[scrollView addSubview:aButton];
xCoord += buttonHeight + buffer;
}
[cell addSubview:scrollView];
pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, height/1.25, width, height/4)];
pageControl.numberOfPages = 3;
pageControl.currentPage = 0;
pageControl.userInteractionEnabled =YES;
[pageControl addTarget:self action:#selector(pageAction:) forControlEvents:UIControlEventValueChanged];
[cell addSubview:pageControl];
return cell;
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// Update the page when more than 50% of the previous/next page is visible
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
}
- (void)pageAction:(UIPageControl *)sender {
// update the scroll view to the appropriate page
CGRect frame;
frame.origin.x = scrollView.frame.size.width * pageControl.currentPage;
frame.origin.y = 0;
frame.size = scrollView.frame.size;
[ scrollView scrollRectToVisible:frame animated:YES];
}
That is because you have reference only to scroll view and page control generated for the last cell:
// this references are redefined every time new cell is generated
scrollView = [[UIScrollView alloc] init];
pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0, height/1.25, width, height/4)];
You could try to use sender in your UIScrollView delegate method:
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// Update the page when more than 50% of the previous/next page is visible
CGFloat pageWidth = sender.frame.size.width;
int page = floor((sender.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
// !!! but here is another problem. You should find reference to appropriate pageControl
pageControl.currentPage = page;
}
But there will be one more problem: you should get reference to the appropriate UIPageControl object. You could use tags, array or anything else for that purpose.

How could I make this work with UIScrollView?

I'm inserting dynamically anywhere from 1 to 300 buttons inside a UIScrollView(as subviews). Currently, the buttons line up nicely but is not scrolling as I'd like them to. It just scrolls horizontally without a paging effect. Ideally, they way I'd like it to work is:
Display a max of 48 buttons per "page"
When scrolling to the right, show next "page" with 48 additional buttons
My code:
-(void)populateScrollView:(NSMutableArray *)colors {
// Properties
NSInteger count = 0;
NSInteger rowsize = 48;
CGFloat pageNum = 6;
CGFloat pageWidth = scrollView.frame.size.width;
CGFloat pageHeight = scrollView.frame.size.height;
CGFloat visibleWidth = 465;
myButtons = [[NSMutableArray alloc]init];
// Clear the subviews if any
for (UIView *subview in scrollView.subviews) {
[subview removeFromSuperview];
}
for (Color *element in colors) {
// Set the button properties
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *image = [UIImage imageNamed:#"color_overlay.png"];
[button setImage:image forState:UIControlStateNormal];
[button setImage:image forState:UIControlStateHighlighted];
div_t temp = div(count, rowsize);
button.frame = CGRectMake(52 * temp.rem , 52*temp.quot, 52, 52);
button.tag = count++;
UIImage *effect = [UIImage imageNamed:element.image_resource];
effectImage = [[UIImageView alloc] initWithImage:effect];
effectImage.frame = CGRectMake(52 * temp.rem , 52*temp.quot, 52, 52);
// Color the graphic if color available. If not, load the image
unsigned result = 0;
if ([element.hex_value length] > 1){
NSScanner *scanner = [NSScanner scannerWithString:element.hex_value];
[scanner scanHexInt:&result];
button.backgroundColor = UIColorFromRGB(result);
}
else {
effectImage.image = effect;
}
// Set actions for the color
[button addTarget:self action:#selector(changeGraphicColor:) forControlEvents:UIControlEventTouchUpInside];
[myButtons addObject:button];
for (UIButton *myButton in myButtons){
[scrollView insertSubview:effectImage atIndex:1];
[scrollView insertSubview:myButton atIndex:2];
}
}
// Set scrollView contentSize and create pages:
CGFloat leftShift=floor(((visibleWidth-pageWidth)/2)/pageWidth)*pageWidth;
CGFloat contentSizeReduction=2*leftShift;
scrollView.contentSize = CGSizeMake(pageNum*pageWidth-contentSizeReduction,pageHeight);
[myButtons removeAllObjects];
[myButtons release];
}
I'm thinking the way I'm adding the buttons won't allow me to implement what I am trying to accomplish. What do you guys think I'm doing wrong here?
Did you set scrollView.pagingEnabled to YES?

Resources