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.
Related
I have array of images here i am doing check and uncheck the images finally i have delete button which are the images i check i need to remove the images from array based on the button selection
here is my code
- (IBAction)delete_btn_touch:(id)sender {
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
for(int i=0; i<_GalleryimageArry.count;i++){
_imageV = [[UIImageView alloc]initWithFrame:CGRectMake(CGRectGetWidth(self.view.frame) * i/2*0.6, 0, 100, 100)];
self.Crossbtn =[[UIButton alloc]initWithFrame:CGRectMake(_imageV.image.size.width/2+80,0,20,20)];
UIImage *btnImage = [UIImage imageNamed:#"unselectimag"];
[self.Crossbtn setImage:btnImage forState:UIControlStateNormal];
_imageV.contentMode = UIViewContentModeScaleAspectFill;
_imageV.image = [_GalleryimageArry objectAtIndex:i];
[_imageV setUserInteractionEnabled:YES];
_imageV.tag = i;
self.Crossbtn.tag =i;
[self.Crossbtn addTarget:self action:#selector(deleteImage:) forControlEvents:UIControlEventTouchUpInside];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imageTapMethod:)];
[_imageV addGestureRecognizer:tap];
[self.imageV addSubview:self.Crossbtn];
[self.imageGalleryscroll addSubview:_imageV];
[MBProgressHUD hideAllHUDsForView:self.view animated:YES];
}
self.imageGalleryscroll.delegate = self;
index=0;
self.imageGalleryscroll.contentSize = CGSizeMake(CGRectGetWidth(self.view.frame) * _GalleryimageArry.count/2*0.7, CGRectGetHeight(self.imageGalleryscroll.frame));
[self.imageGalleryscroll setPagingEnabled:YES];
[self.imageGalleryscroll setShowsHorizontalScrollIndicator:NO];
self.imageGalleryscroll.alwaysBounceVertical = NO;
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
-(void)deleteImage:(UIButton *)sender{
btn = (UIButton *)sender;
self.add_delete_view.hidden =YES;
self.deleteview.hidden=NO;
if( [[btn imageForState:UIControlStateNormal] isEqual:[UIImage imageNamed:#"unselectimag"]])
{
[btn setImage:[UIImage imageNamed:#"Crossimg"] forState:UIControlStateNormal];
[btn setSelected:YES];
[btn setTag:index];
}
else
{
[btn setImage:[UIImage imageNamed:#"unselectimag"] forState:UIControlStateNormal];
// other statements
self.selectedimages =#"No";
image = [self.GalleryimageArry objectAtIndex:index];
[self.GalleryimageArry addObject:image];
}
NSLog(#"%#", self.GalleryimageArry);
}
- (IBAction)delete_all_img_btn_touch:(id)sender {
// self.view (change it with your button superview)
if (btn.selected) {
[self.GalleryimageArry removeObjectAtIndex:index];
}
//here i need to removeObjectAtIndex:index based on the how many button are selected
}
any one help me to solve this issues
thanks in advance
Use the following code, where you want to clear the back stack of controllers.
-(void)clearStack
{
NSMutableArray *navigationArray = [[NSMutableArray alloc] initWithArray: self.navigationController.viewControllers];
[navigationArray removeAllObjects];
//[navigationArray removeObjectAtIndex: 2];
self.navigationController.viewControllers = navigationArray;
}
I have created buttons dynamically based on array count ,if i pressed it will move to next page .i want to change the background color of the button if it is pressed .i pressed 1st button its background color should changed ,and den if i pressed anyother buttons the first pressed button should get into default color of the button , and the new pressed button's background color should changed ,
please help me to do this ,On button clicked method i have tried like this ,
- (IBAction)btn1Tapped:(id)sender {
UIButton *btn = (UIButton *) sender;
selected = YES;
if (selected) {
[btn setBackgroundColor:[UIColor redColor]];
}
}
and this my button creation code ,
int buttonheight = 30;
int horizontalPadding = 20;
int verticalPadding = 20;
int totalwidth = self.view.frame.size.width;
int x = 10;
int y = 150;
for (int i=0; i<array.count; i++)
{
NSString* titre = [array objectAtIndex:i];
CGSize contstrainedSize = CGSizeMake(200, 40);//The maximum width and height
NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont systemFontOfSize:20.0], NSFontAttributeName,
nil];
CGRect frame = [titre boundingRectWithSize:contstrainedSize options:NSStringDrawingUsesLineFragmentOrigin attributes:attributesDictionary context:nil];
int xpos = x + CGRectGetWidth(frame);
if (xpos > totalwidth) {
y =y +buttonheight+ verticalPadding;
x = 10;
}
UIButton *word= [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.word = word;
NSLog(#"%#", NSStringFromCGRect(frame));
word = [UIButton buttonWithType:UIButtonTypeRoundedRect];
word.frame = CGRectMake(x, y, CGRectGetWidth(frame)+5, CGRectGetHeight(frame));
[word setTitle:titre forState:UIControlStateNormal];
[word setTitle:titre forState:UIControlStateSelected];
word.backgroundColor = [UIColor colorWithRed:30.0/255.0 green:134.0/255.0 blue:255.0/255.0 alpha:1.0];
[word setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[word setTag:i];
[word addTarget:self action:#selector(btn1Tapped:) forControlEvents:UIControlEventTouchUpInside];
word.layer.borderColor = [UIColor blackColor].CGColor;
word.layer.borderWidth = 1.0f;
word.layer.cornerRadius = 5;
[self.view addSubview:word];
x =x+horizontalPadding+CGRectGetWidth(frame);
}
- (IBAction)allBtnSharedTappedevent:(id)sender {
UIButton *btn = (UIButton *) sender;
[btn setBackgroundColor:[UIColor redColor]];
//loop through all your buttons
for(UIView *view in [self.view subviews]){
if([view isKindOfClass:[UIButton class]]){
if(view != btn){
UIButton* btn1 = (UIButton*) view;
[btn1 setBackgroundColor:[UIColor grayColor]];
}
}
}
}
Keep the buttons in an array.
#property (nonatomic, copy, readonly) NSArray<UIButton *> *buttons;
Then in your method that handles the tap, do something like this.
- (IBAction)buttonTapped:(UIButton *)sender {
// Loop through all buttons, clearing the background color
for (UIButton *button in self.buttons) {
button.backgroundColor = [UIColor clearColor];
}
// Set the background color for the selected button
sender.backgroundColor = [UIColor redColor];
}
You should avoid using the tag property of UIView, it will just cause you headaches down the road.
give your button tag number like 1,2,3,4 ... etc
then
- (IBAction)btn1Tapped:(id)sender {
UIButton *btn = (UIButton *) sender;
[btn setBackgroundColor:[UIColor redColor]];
loop through all your buttons
for(int i = 1;i <= total numbers of button; i++){
if(btn.tag != i){
UIButton* btn1 = [myView viewWithTag:i];
[btn1 setBackgroundColor:[UIColor graycolor]];
}
}
}
I want to make an "add" button to add as many textfields as i want in my scroll view.
I did this already
UITextField *text=[[UITextField alloc]initWithFrame:CGRectMake(50,50,200,200)];
[self.scrollView addSubview:text];
But is not working.
Thanks!
If this is your complete button code:
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
// add this
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
// continue
[self.mainScroll addSubview:button];
Then add this somewhere:
- (void) buttonPressed:(UIButton *)button {
UITextField *text=[[UITextField alloc]initWithFrame:CGRectMake(50,50,200,200)];
text.backgroundColor = [UIColor greenColor]; // just to make sure it's showing up.
[self.scrollView addSubview:text];
}
First create common function like this,
-(void)setTextfieldStyle:(UITextField *)pTmpTextField
{
pTmpTextField.borderStyle = UITextBorderStyleRoundedRect;
pTmpTextField.font = [UIFont systemFontOfSize:15];
pTmpTextField.placeholder = #"First Name";
pTmpTextField.autocorrectionType = UITextAutocorrectionTypeNo;
pTmpTextField.keyboardType = UIKeyboardTypeDefault;
pTmpTextField.returnKeyType = UIReturnKeyDone;
pTmpTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
pTmpTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
pTmpTextField.delegate = self;
}
and use this for creating UITextFiled,
int y = 0;
for(int i=0;i < 5;i++)
{
UITextField *txtTemp=[[UITextField alloc]initWithFrame:CGRectMake(0, y, 300, 31)];
txtTemp.tag = i;
[self setTextfieldStyle:txtTemp];
[self.view addSubview:txtTemp];
[txtTemp release];
y+=36;
}
This is UITextField's delegate method,
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
NSLog(#"%#",textField.text);
}
Hope this works for you as this works for me. only keep this in mind that add the text fields to your scroll view.
In the example am adding them to my view!
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.
I have a class which is predefining some labels and binding their values in a UIScrollView.
I've managed to show those labels, but now I'm stuck at putting a label at the 2nd part of the ScrollView.
I've pushed my project to gitHub.
I can change the label's place on the already visible part, but I must be overlooking something.
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.title = _detail.name;
UIColor *bgColor = [UIColor blackColor];
UIColor *txtColor = [UIColor grayColor];
CGRect frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size.width = _scrollView.frame.size.width *2;
NSString *phoneNr = (_detail.phoneNr == nil) ? #"Not specified" : _detail.phoneNr;
_telLabel = [self prepareLabel:phoneNr textColor:txtColor bgColor:bgColor page:0 y:telNrYAxis];
_webLabel = [self prepareLabel:#"Visit website" textColor:txtColor bgColor:bgColor page:0 y:websiteYAxis];
_detail.address = [_detail.address stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"\n\t "]];
NSArray *addressArrComponents = [_detail.address componentsSeparatedByString:#","] ;
_addressLabel = [self prepareLabel:[addressArrComponents componentsJoinedByString:#"\n"] textColor:txtColor bgColor:bgColor page:0 y:addressYAxis];
UILabel *lbl = [self prepareLabel:#"Derp" textColor:txtColor bgColor:bgColor page:1 y:0];
_detailView = [[UIView alloc] initWithFrame:frame];
_detailView.backgroundColor = [UIColor blackColor];
[_detailView addSubview:_webLabel];
[_detailView addSubview:_addressLabel];
[_detailView addSubview:_telLabel];
[_detailView addSubview:lbl];
[_scrollView addSubview:_detailView];
NSLog(#"%f",self.view.frame.size.height - (_scrollView.frame.origin.y + _scrollView.frame.size.height) );
_pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height - 250 , self.view.frame.size.width/4, 120)];
_pageControl.numberOfPages=2;
_pageControl.currentPage=0;
[_pageControl addTarget:self action:#selector(pageChange:) forControlEvents:UIControlEventTouchDown];
_scrollView.contentSize = CGSizeMake(800,800);
_scrollView.delegate=self;
_scrollView.backgroundColor = [UIColor blackColor];
_scrollView.pagingEnabled=YES;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.scrollsToTop = NO;
[self pageChange:0];
[self.view addSubview:_pageControl];
// Do any additional setup after loading the view.
}
-(UILabel*)prepareLabel:(NSString*) text textColor:(UIColor*)textColor bgColor:(UIColor*)backgroundColor page:(int)page y:(int) yPos{
int lines = [[text componentsSeparatedByString:#"\n"] count];
CGRect labelFrame = CGRectMake(_detailView.frame.size.width * page +20,yPos,self.view.frame.size.width, [UIFont systemFontSize]*lines);
UILabel *returnLabel = [[UILabel alloc] initWithFrame:labelFrame];
returnLabel.text = text;
returnLabel.backgroundColor = backgroundColor;
returnLabel.textColor = textColor;
[returnLabel setNumberOfLines:lines];
[returnLabel sizeToFit];
return returnLabel;
}
- (void)loadScrollViewWithPage:(int)page {
NSLog(#"Derped");
}
-(IBAction)pageChange:(id)sender{
int page=_pageControl.currentPage;
CGRect frame = _scrollView.frame;
frame.origin.x = _scrollView.frame.size.width * page;
frame.origin.y = 0;
//CGRect frame= (page == 0) ? _detailFrame : _reviewFrame;
NSLog(#"%f",frame.origin.x);
[_scrollView scrollRectToVisible:frame animated:YES];
}
The delegate -(IBAction)pageChange:(id)sender gets fired, but I must be doing something wrong with the frames somewhere :s
Please take a look!
Try to implement this method may help you :
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat pageWidth = self.scrollView.frame.size.width;
float fractionalPage = self.scrollView.contentOffset.x / pageWidth;
NSInteger page = lround(fractionalPage);
self.pageControl.currentPage = page;
}