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.
Related
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;
}
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
I've got some buttons where I left align and line wrap the title text.
When I run the app, there is a delay from where the text is unformatted:
pre-format text http://imageshack.us/a/img28/1958/preformat.jpg
To when the alignment and wrapping take effect:
post-format text http://imageshack.us/a/img821/6118/postformat.jpg
On the simulator the delay is quite noticeable (~ 1 second), on my mate's iPhone 5 the delay is much smaller but still noticeable.
What causes this delay? Can I get around this delay?
Thanks in advance!
EDIT
In my viewDidLoad method I create 10 buttons:
for (int i = 1; i <= STEP_NUMBER; ++i)
[self createStepButtion:i isIphone:isIphone isRetina:isRetina];
In createStepButton, the relevant code is below:
UIButton * b = [UIButton buttonWithType:UIButtonTypeCustom];
// Listener
[b addTarget:self action:#selector(goToStep:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollView addSubview:b];
// Set button size.
CGFloat width = self.scrollView.frame.size.width;
// CGRectMake(x, y, width, height)
int y = stepNum * margin + (stepNum - 1) * buttonHeight;
int buttonWidth = width - margin * 2;
b.frame = CGRectMake(margin, y, buttonWidth, buttonHeight);
b.layer.cornerRadius = cornerRadius;
b.clipsToBounds = YES;
b.showsTouchWhenHighlighted = YES;
// Image
[b setImage:img forState:UIControlStateNormal];
b.imageEdgeInsets = [self makeImageInsets:buttonWidth];
// Text
[b setTitleEdgeInsets:UIEdgeInsetsMake(0, titleLeftMargin, 0, titleRightMargin)];
b.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
b.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
[b setTitle:[NSString stringWithFormat:#"%i - %s", stepNum, STEP_NAMES[stepNum - 1]]forState:UIControlStateNormal];
[b setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
b.titleLabel.font = [UIFont systemFontOfSize:fontSize];
// Background
[b setBackgroundColor:[UIColor whiteColor]];
// The step number this button represents.
b.tag = stepNum;
I'm trying to add 16 UIButton in code to a subview of my main view:
internView = [[UIView alloc] initWithFrame:CGRectMake(16, 16, (self.view.frame.size.width - 16), (self.view.frame.size.height - 16) - 60)];
internView.backgroundColor = [UIColor whiteColor];
for (int rij = 0; rij < 4; rij++) //4 rows
{
for (int kolom = 0; kolom < 4; kolom++) //4 colomns
{
CGFloat x = (((width + spacing) * kolom) + spacing);
CGFloat y = (((height + spacing) * rij) + spacing);
int tag = ((4 * rij) + kolom);
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(x, y, width, height)];
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.backgroundColor = [UIColor blackColor];
[button setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[[projects objectAtIndex:tag]thumbnailImage]]]] forState:UIControlStateNormal];
[button addTarget:self action:#selector(getDetail:) forControlEvents:UIControlStateNormal];
button.tag = tag;
NSLog(#"%i",button.tag);
[internView addSubview:button];
}
}
[self.view addSubview:internView];
The subview 'internview' is visible (as i made it white background) on the main view but the buttons aren't visible.
Also my log shows the tag of the button which goes from 0..15, so I know they are being made but simple aren't added to the subview 'internview'
Can't really see what I'm missing or doing wrong here..
Change your code to :
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(x, y, width, height);
In your version you have:
Memory leak because you have created buttons two times
[UIButton buttonWithType:UIButtonTypeCustom]; returns new button
with CGRectZero frame
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?