I am new to iOS Development.
I have a navigation based Application, In my application I created dynamic buttons by using a for loop.
I have two UITextFields (row and column) in FirstViewController. When user enters a value of row and column then click on OK Button the values of row and column passes to anOtherViewController. In anOtherViewController I have to put a logic to create All Buttons based on row and column value.
MyLogical Code:
for (int i = 1 ; i <= rows; i++)
{
for (int j = 1 ; j <= columns ; j++)
{
NSString *btnTitle = [NSString stringWithFormat:#"%d",buttonCount];
self.btnCount = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.btnCount.tag = [btnTitle intValue];
[self.btnCount setTitle: btnTitle forState: UIControlStateNormal];
[self.btnCount addTarget:self action:#selector(btnCountPressed:) forControlEvents:UIControlEventTouchUpInside];
self.btnCount.frame = CGRectMake(162+changedX, 60+changedY, 43, 43);
[self.scrollView addSubview:self.btnCount];
[self.listOfbtnCount addObject:btnTitle];
changedY = changedY + 50;
buttonCount = buttonCount + 1;
}
changedX = changedX + 55;
if (i == rows)
widthScView = changedX;
if (heightScView == 0)
heightScView = changedY;
changedY = 5;
}
My ScreenShot:
It works fine, but my problem is that if I enter values of row and column more then 40 (about) then my app takes more time to create the dynamic button. The issue is only related to the time required to create the button.
Is there any way to create a button faster? and I also need to know is if my code is bad for memory management? please help me on this issues.
For Information : I Have no errors generated, I have issue of only time consuming process of creation of Buttons.
Thank in Advance.
You should use UICollectionView for this.
UICollectionView works a lot like UITableView in that it'll manage the cells that are displayed on screen, including scrolling, and it'll ask its data source for new cells as it needs them. You can also recycle cells, so you'll only need to create about enough to display, plus a few extra. This should really improve performance, especially when scrolling.
Apple has some sample code using UICollectionView here, and watching Introducing Collection Views in the 2012 WWDC Videos will get you off to a good start.
my problem is that If i enter values of row and column more then 40
Forty rows of forty columns would give you 1600 buttons, most of which don't need to exist most of the time. By managing which cells are needed on screen for you, UICollectionView will reduce that to around eighty (judging by your screen shot). You should see much, much better performance this way.
UICollectionView will also simplify positioning the buttons once you've configured the collection view (which you can do in code or in Interface Builder), you won't need any code of your own for calculating the positions of the buttons.
just implement you logic here with your requirement..
int imageIndex = 0;
int yOffset = 4;//set offset which you want...
while (imageIndex < rows)
{
int yPos = 7 + yOffset * 30; // set distance in height between two raws
for(int i = 0; i < columns; ++i)
{
CGRect rect = CGRectMake((0 + i * 80), yPos, 80, 31);**// here set frame of every button with different x and y postion// here width of button is 80 and height is 31**
if (imageIndex < rows) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = rect;
button.tag = imageIndex;
[button addTarget:self
action:#selector(btnTemp_Clicked:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:[NSString stringWithFormat:#"%d",imageIndex] forState:UIControlStateNormal];
[button.titleLabel setFont:[UIFont fontWithName:#"Helvetica-Bold" size:12]];
// [button.titleLabel setTextColor:[UIColor blueColor]];
[button setTitleColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"circle03.jpg"]] forState:UIControlStateNormal ];
[button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted ];
[button setNeedsDisplay];
[yourScrollView addSubview:button];
}
++imageIndex;
}
++yOffset;
}
See the screen which i got output..
Try this method
-(void)ScrollViewSetting {
scrollview.scrollEnabled=YES;
scrollview.userInteractionEnabled=YES;
TotalStyleX=25;
TotalStyleY=18;
int count=0;
int px=0;
int py=0;
for (int i=1; i<=TotalStyleX; i++) {
px=0;
for (int j=1; j<=TotalStyleY; j++) {
count++;
UIButton *btn1=[[UIButton alloc] init];
btn1.tag = count;
btn1.frame=CGRectMake(px+10, py+10, 300, 380); //you can set your height and width your x and y position
[scrollview addSubview:btn1];
px=px+320;
}
py=py+400;
}
[scrollview setContentSize:CGSizeMake(px, py)];
}
Related
I have a UIScrollView that will expand depending on how many buttons it is due to display. It will always round up to the nearest 320 multiple.
So, if the UIScrollView will receive 3 buttons it will be 320px horizontal, if it received 6 then 640px, 9 is 960.
What I need to do is distribute the UIButtons across this UIScrollView evenly.. However I can't seem to figure out how to do this.
My UIButtons measure 80 pixels horizontally.
Could somebody help me get my head round this?
Update/Clarification: I have no problem setting the UIScrollView's width. This has been done. I am looking for info on how to distribute the 'UIButtons' within the 'UIScrollView'..
[theScrollView setContentSize:CGSizeMake(320/640/960, theScrollView.frame.size.height)];
//considering a margin of 10 pts on either edges and a additional 10 pts on each side of button
Add the buttons like below:
for(int i=0; i< buttonCount;i++){
CGRect buttonFrame = CGRectMake( 10 + i*(80+10+10) +10 , buttonY, 80, buttonHeight );
UIButton *button = [UIButton buttonWithType:<type>];
button.frame = buttonFrame;
}
//To set the scrollable area
[scrollView setContentSize:CGSizeMake( 10 + buttonCount*(80+10+10) +10, 0 )];
//left margin + buttonCount x (buttonWidth + leftButtonMargin+rightButtonMargin) + right margin
This should give you an almost evenly distributed buttons according to the number of buttons.
First take all the buttons in an array..lets say buttonsArray
int spacing = 10; // Adjust according to you requirement
int buttonWidth = 100; // Adjust according to you requirement
int buttonHeight = 100; // Adjust according to you requirement
int count = 0;
for (UIButton *thisButton in buttonsArray) {
[thisButton setFrame:CGRectMake(spacing*(count+1)+count*buttonWidth, 20, buttonWidth, buttonHeight)];
count++;
}
[theScrollView setContentSize:CGSizeMake([[buttonsArray lastObject]frame].origin.x+[[buttonsArray lastObject]frame].size.width+spacing, 0)];
Hope this will help you. I have tested it..working fine...
You can use like this:Use MyScrollView.pagingEnabled=YES.
int PageNum=0;
if(TotalButtons%3 >0)
{
pageNum=TotalButtons/3;
pageNum++;
}
else{
PageNum=TotalButtons/3;
}
[MyScrollView setContentSize:CGSizeMake(320*pageNum, MyScrollView.frame.size.height)];
Add Buttons according to the width and spacing you want on the scrollview.
Edit:
int x=56;
int y=60;
for(int i=1;i<= 60;i++)
{
UIButton *button=[UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame=CGRectMake(x, y, 200, 120);
button.tag=i;
// [button setTitle:[NSString stringWithFormat:#"Video-%d",i+1] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:#"220x200.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(ButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[VideoStoreScroll addSubview:button];
if(i%6==0)
{
count++;
x=(count-1)*VideoStoreScroll.frame.size.width+56;
y=50;
}
else
{
if(i%3==0)
{
x=(count-1)*VideoStoreScroll.frame.size.width+56;
y=y+190;
}
else
{
x=x+256;
}
}
}
VideoStoreScroll.contentSize=CGSizeMake(x-56, 480);
VideoStoreScroll.contentOffset=CGPointMake(0, 0);
Here I am using six buttons horizontally on scroll per page.You can work for three following this.
I have a UIScrollView which scrolls only horizontally. I have a situation where I have views filled by array in UIScrollView. There are three views which altogether make one single component in UIScrollView (there are many such components). Component contains :
UILabel
UIButton
UIView (for underlying text)
I have placed two arrow keys(left and right) at the ends of UIScrollView. On touching left arrow I am shifting one position left (with complete string to display) in UIScrollView and one position right (with complete string to display) in case of right arrow button.
Till now I am able to perform left arrow action. But I have no idea how to perform right arrow touch and how to display complete string to touching arrow keys if only part of that string is being displayed.
I know it is weird that I have a UIScrollView and still want to add arrow keys to move it. But can't help it. This is client's requirement. The following is how I implemented left arrow action:
-(IBAction) onClickLeftArrow
{
NSLog(#"BUTTON VALUE : %i",iButtonValue);
if(iButtonValue <= [m_BCListArray count]) {
NSArray *arr = [scrollDemo subviews];
for(int j = 0; j < [arr count]; j++) {
UIView *view1 = [arr objectAtIndex:j];
[view1 removeFromSuperview];
}
XX = 5.0;
int tagcount = [m_BCListArray count]-iButtonValue;
NSLog(#"%#",m_BCListArray);
for(int i = iButtonValue; i >= 1; i--)
{
UILabel *blabel = [[UILabel alloc] initWithFrame:CGRectMake(XX, 6, 120, 26)];
blabel.text = [m_BCListArray objectAtIndex:[m_BCListArray count]-i];
blabel.backgroundColor = [UIColor clearColor];
blabel.textColor = [UIColor whiteColor];
blabel.font = [UIFont systemFontOfSize:14];
[scrollDemo addSubview:blabel];
//underline code
CGSize expectedLabelSize = [[m_BCListArray objectAtIndex:[m_BCListArray count]-1] sizeWithFont:blabel.font constrainedToSize:blabel.frame.size lineBreakMode:UILineBreakModeWordWrap];
CGRect newFrame = blabel.frame;
newFrame.size.height = expectedLabelSize.height;
blabel.frame = CGRectMake(blabel.frame.origin.x, blabel.frame.origin.y, expectedLabelSize.width+10, expectedLabelSize.height);
blabel.numberOfLines = 1;
[blabel sizeToFit];
int width=blabel.bounds.size.width;
int height=blabel.bounds.size.height;
UIButton *btnContent = [UIButton buttonWithType:UIButtonTypeCustom];
[btnContent addTarget:self action:#selector(SelectButton:)forControlEvents:UIControlEventTouchDown];
btnContent.tag = tagcount+1;
btnContent.frame=CGRectMake(XX, 2.0, width+10, height);
[scrollDemo addSubview:btnContent];
scrollDemo.contentSize = CGSizeMake(XX+50, 32);
//scrollDemo.contentSize = CGSizeMake(expectedLabelSize.width,expectedLabelSize.height);
UIView *viewUnderline=[[UIView alloc] init];
viewUnderline.frame=CGRectMake(XX, 26, width, 1);
viewUnderline.backgroundColor=[UIColor whiteColor];
[scrollDemo addSubview:viewUnderline];
[viewUnderline release];
scrollDemo.contentSize = CGSizeMake(XX+width+10, 32);
XX = XX + width+10;
iRight = iRight + 1;
tagcount ++;
// iRight --;
}
}
iButtonValue = iButtonValue+1;
}
Set the contentOffset of UIScrollView on the Button click action and u'll get your desired effect.
I need to space UIButtons out on a UIScrollView. The code I have works, however depending on the amount of dataItems I have, the spacing is not even.
Snippet in Question
CGRectMake(10, ((120 / (count + 1)) * (i + 1) * 3) ,300,50)
Specifically
((120 / (count + 1)) * (i + 1) * 3)
Working code
int count = [dataItems count]; /* not a specific value, can grow */
for (int i = 0; i < count; i++) {
UIButton* aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTag:i];
[aButton setFrame: CGRectMake(10,((120 / (count + 1)) * (i + 1) * 3) ,300,50) ];
[aButton setTitle:[[dataItems objectAtIndex:i] objectForKey:#"Feed"] forState:UIControlStateNormal];
[aButton addTarget:self action:#selector(viewCategories:) forControlEvents:UIControlEventTouchUpInside];
[scroller addSubview:aButton];
}
Screenshot
The example on the right should look like the example on the left as far as spacing goes. The UIButtons are sitting on a UIScrollView, so the UIScrollView's contentSize should also grow if there are more dataItems so the buttons can scroll offscreen if there are say, 30+ dataItems.
sounds like you need a set size and padding...
int count = [dataItems count];
CGFloat staticX = 10; // Static X for all buttons.
CGFloat staticWidth = 300; // Static Width for all Buttons.
CGFloat staticHeight = 50; // Static Height for all buttons.
CGFloat staticPadding = 10; // Padding to add between each button.
for (int i = 0; i < count; i++) {
UIButton* aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setTag:i];
//Calculate with the Static values.
//I added one set of padding for the top. then multiplied padding plus height for the count.
// 10 + 0 for the first
// 10 + 60 for the second.
// 10 + 120 for the third. and so on.
[aButton setFrame: CGRectMake(10,(staticPadding + (i * (staticHeight + staticPadding)) ,staticWidth,staticHeight) ];
[aButton setTitle:[[dataItems objectAtIndex:i] objectForKey:#"Feed"] forState:UIControlStateNormal];
[aButton addTarget:self action:#selector(viewCategories:) forControlEvents:UIControlEventTouchUpInside];
[scroller addSubview:aButton];
}
however if you are trying to get buttons to do this sort of behavior. I am inclined to agree with the rest.. You can make a custom cell with a button in it.
Then you can load that button cell when the table asks for a button.
And you have the table tie to your [dataItems count] for the total of the items.
then your only calculation is to set the cell height when you initially set the dataItems count. making sure not to make them too short. and the table will handle the rest.
I agree with Gurpartap, but if your dead set on this, I'd do it a bit differently. Even if you understand the math in that setFrame statement now, will you or someone else understand it later. I sure don't looking at it quick. Why not do something like:
CGRect frm = CGRectMake(10,10,300,50);
for (int i = 0; i < count; i++) {
UIButton* aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setFrame: frm];
frm.origin.y = frm.origin.y + aButton.frame.size.height + 10;
etc, etc
You should really use a UITableView instead. It does the scroll view, cell laying out, etc. all by itself. You just specify the cell contents.
This is a beginner's question about the fundamentals of objective programming (at least I think so..):
I have an UIView and would like to add several buttons to this UIView programatically. How many buttons there are depends on the user input.
Every button has four characteristics:
Its number (e.g. button number one, two, three etc.)
Its title (e.g. click this, click here, click me etc.)
Its position and size (i.e. a CGRect - size stays the same, only y-position needs to change)
Its colour (e.g. red, green, blue etc.)
Now I thought I can create a button by creating a method, but I am not entirely sure if this is a very sound method. I have the feeling that I should have created an object. Any help of how I should go about this would be very much appreciated. Here is my attempt - which is full of mistakes (for instance, I wasn't sure of how to create button1, button2 etc. -- hence the button[bNumber] thing):
-(void) createIndexButtonWithNumber:(NSString *)bNumber withTitle:(NSString *)bTitle atPosition:(NSInteger *)bPosition withColour:(NSInteger *)bColour {
CGRect buttonFrame = CGRectMake(0,bPosition,25,25);
UIButton* button[bNumber] = [[[UIButton alloc] initWithFrame:buttonFrame] autorelease];
UIButton.text = bTitle;
if (bColour == 1) {UIButton.color = [UIColor colorWithRed:0.751 green:0.742 blue:0.715 alpha:1.000];};
[indexView addSubview:button[bNumber]];
// to do: if button[bNumber] pressed {do something};
}
Then, I would like to 'multiply' the object three times by calling:
for (temp = 0; temp < 2; temp++) {
[self createIndexButtonWithNumber:temp withTitle:[#"Test%i", temp] atPosition:10 withColour:1];}
I'm sure this is all a bit problematic, wrong and clumsy, so I'd be very grateful for any suggestions of how to tackle this.
Here's a simple example that I wrote that creates 5 buttons vertically in a row. The only thing extra in there is the tag, which is used to later reference the button if you need to.
I would suggest reading some more object orientated program examples as well.
float buttonPadding = 20;
float buttonWidth = 80;
float buttonHeight = 40;
for (int k=0;k<5;k++)
{
UIButton* btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btn.tag = 1000 + k;
btn.frame = CGRectMake(0, k*(buttonPadding+buttonHeight), buttonWidth, buttonHeight);
[btn setTitle:[NSString stringWithFormat:#"Button %i", k+1] forState:UIControlStateNormal];
[self.view addSubview:btn];
}
I'd like to reference to UIButton Class Reference
You should create buttons only with buttonWithType: method.
Second, there is no button color. You can set a color for title with setTitleColor:forState: method.
There are just syntax mistakes in your code (UIButton.text, etc). You cant do such a call. UIButton is a class.
Your calling createIndexButtonWithNumber... within for will place buttons in the same place — atPosition input parameter has no change.
NSInteger variable is not a pointer — * is not needed.
...
In the end of struggling we have smth like that:
-(void)createIndexButtonWithNumber:(NSInteger)bNumber //(sorry for that, some troubles with code formatting)
withTitle:(NSString *)bTitle
atPosition:(NSInteger)bPosition
withColour:(NSInteger)bColour {
CGRect buttonFrame = CGRectMake(0,bPosition,25,25);
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = buttonFrame;
button.tag = bNumber;
[button setTitle: [NSString stringWithFormat:#"Button %i", bNumber]
forState:UIControlStateNormal];
if (bColour == 1) {
[button setTitleColor:[UIColor colorWithRed:0.751 green:0.742 blue:0.715 alpha:1.000]
forState:UIControlStateNormal];
};
// you should pass to #selector a description like 'indexAction:' but NOT any calls like '[self indexAction:button]'
[button addTarget:self
action:#selector(indexAction:)
forControlEvents:UIControlEventTouchUpInside];
[indexView addSubview:button];
}
And for call:
for (int temp = 0; temp < 2; temp++) {
[self createIndexButtonWithNumber:temp withTitle:[#"Test%i", temp] atPosition:30 * temp withColour:1];
}
UPDATE: Selector method
-(void)indexAction:(id)sender {
NSLog(#"Button with tag %d is pressed", ((UIButton *)sender).tag);
}
I have ScrollView and UIView created in interface builder (but can as well be code). I want to add random amount of thumbnails (subviews) to UIView and be able to scroll it up-down if there are more than the screen can take. Hovewer, I can't get ScrollView to scroll.
Where and how do I resize UIView and add it as a subview of ScrollView?
When do I set contentSize of scrollView to make it expand along with uiview? I tried creating fixed large contentSize but didn't work as well.
What properties in IB I might need to change to make it work?
I'd like to make the images in uiview clickable in next step.
I guess I could also make both view in code without IB. Just somehow can't get it to work.
Thanks in advance !
//declare base view
UIViewController *viewForLoadForm =[[UIViewController alloc] init];
viewForLoadForm.view.frame=CGRectMake(0, 0,screenSize.size.width,screenSize.size.height);
viewForLoadForm.view.backgroundColor=[UIColor blackColor];
[Manview.view addSubview:viewForLoadForm];
//declare scrollview and add to base view
UIScrollView *scrollview=[[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, screenSize.size.width,screenSize.size.height)];
scrollview.indicatorStyle=UIScrollViewIndicatorStyleBlack;
[scrollview setContentSize:CGSizeMake(screenSize.size.width,screenSize.size.height)];
scrollview.clipsToBounds = NO;
scrollview.scrollEnabled = YES;
scrollview.pagingEnabled = NO; scrollview.showsVerticalScrollIndicator =NO;
scrollview.alwaysBounceVertical= YES;
[viewForLoadForm.view addSubview:scrollview];
//Add your controls to scrollview that s image view or something which is needed to display
.........your control's code (textbox,imageview etc)
//took last control's y postion and set your K
float k=Last control's y position +100;(some thing which ll be decide scroll size)
// reassign the scrollview height
[scrollview setContentSize:CGSizeMake(screenSize.size.width,k)];
use above line for scroll view size adjustment at run time.
screenSize.size.width is 320 here
code snippet,
- (void) createThumbView
{
float y_axis = Set y axis;
int x = 0;
int totalImgs = total images;
int tempCnt = 0;
for (int i = 0; i < totalImgs;)
{
float x_axis = set x axis;
int loopCount = 0;
if (totalImgs - tempCnt >= (no of images in row))
{
loopCount = (no of images in row);
}
else
{
loopCount = totalImgs % (no of images in row);
}
for (int j = 0; j < loopCount; j++)
{
MasksData *mData = [masksList objectAtIndex:x];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(x_axis, y_axis, width, height);
[btn setImage:[UIImage imageNamed:[NSString stringWithFormat:#"%#.png",mData.bgImage]] forState:UIControlStateNormal];
btn.backgroundColor = [UIColor clearColor];
btn.tag = x;
[scroll View addSubview:btn];
//photoCount++;
x_axis += width + some space;
tempCnt++;
i++;
x++;
}
y_axis += height + some space;
scroll View.contentSize = CGSizeMake(320.0, y_axis);
}
}