Custom UIView with variable UIButtons (programmatically)

Discussion in 'iOS Programming' started by mraheel, Feb 1, 2010.

  1. mraheel macrumors regular

    Apr 18, 2009
    Hi guys,
    I've been workin on a custom "pop up" view. More or less succeeded. But now i've got something very different.

    Uptil now, the popup only shows a single NSString. I divide the strings with @"\n" to get the desired wordwrap effect.

    Hence in the popUpView class, in

    - (void)drawRect:(CGRect)rect {
    //After creating the graphic effect, i jus add the following
    	[dataString drawInRect:textRect
    		withFont:[UIFont systemFontOfSize:15]					   lineBreakMode:UILineBreakModeWordWrap			 alignment:UIBaselineAdjustmentAlignBaselines];
    That gives me the desired results with no problems. Now I wanted to add UIButtons for the capacity to tap.
    However, The number of uibuttons isnt fixed, its dynamic and corresponds to an Array count.

    What i'd like to do is to have this View check the count of an array and add those many buttons on its view with fixed height, one below another.
    But all of them will call one action. "URL Action". with different URLs.

    How do I add those buttons? What do i instantiate in header.

    I kinda ruled out using TableViews. This suits my app perfectly. If done right.

    thanks for the help guys
  2. KoolStar macrumors demi-god


    Oct 16, 2006
    Why not look at the UIActionSheet. I do believe it does what you are trying to do.
  3. mraheel thread starter macrumors regular

    Apr 18, 2009
    That doesnt work for my app, too many buttons, it'll cover the whole screen if used in action sheet.
  4. North Bronson macrumors 6502

    Oct 31, 2007
    San José
    This is going to be fairly non-trivial and would involve a little code, but it could be done.

    I would recommend taking this PopUpView and making your view controller its delegate. Your delegate supplies information about how many buttons there are and what strings are displayed on the buttons. Your delegate also receives the action when a user taps on a button.

    When the PopUpView is about to display, it calls back to the delegate for all the information it needs and it resizes appropriately.
  5. mraheel thread starter macrumors regular

    Apr 18, 2009
    Okay, this is wat i came up with, maybe its just lame, but.. im hoping to go right from here :)

    In my popupView.m [ UIView Class], I added a method to create a setup buttons based on objects in the supplied array.

    -(void) setupfromArray:(NSArray *)btnArray maxWidth:(CGFloat )maxW{
    	if(btnArray.count >0){
    	NSInteger i;
    	UIButton *button;
    	CGRect frame = CGRectInset(self.bounds, kPopupMarginForShadow + kPopupTextXPadding - 2, kPopupMarginForShadow + kPopupTextYPadding);
    		frame.size.height = 19;
    		frame.size.width = maxW;
    	for(i=0; i<btnArray.count; i++)
    			frame.origin.y +=20;
    			//frame.origin.y += 20;
    			button = [UIButton buttonWithType:UIButtonTypeCustom];
    			button.frame = frame;
    			[button setTitle:[btnArray objectAtIndex:i] forState:UIControlStateNormal];
    			button.tag = [btnArray count];
    			//[button setImage:buttonImage forState:UIControlStateNormal];
    			[button addTarget:self action:@selector(SelectMission) forControlEvents:UIControlEventTouchUpInside];
    			[self addSubview:button];
    			//[missionButtons addObject:button];
    			//[button release];
    			button = nil;
    Basically looping through an array and adding buttons that corresponds to required number of buttons and button titles.

    Next likely step is to associate a PopUpViewController with this popUpView. and somehow setup the delegate and do something with the buttons.

    Please let me know if this is the right direction :)
  6. North Bronson macrumors 6502

    Oct 31, 2007
    San José
    Something like this should do the trick. I think you might just want to mimic the functionality of UIActionSheet's initWithTitle: method -- you pass in all the information and let the view figure out how to display itself.

    I see three ways to do it:

    [1] a custom initView: method

    [2] a setupView method

    [3] delegation

    Option [1] would be more for if you display the view and you know that it's not changing until it's dismissed. If the buttons could update while the view is showing, go with [2] or [3].

    Whether or not you prefer [2] or [3] is up to you. I prefer the delegation method because it feels cleaner, but [2] could feel more straightforward. Delegation seems to be keeping more in line with the "Cocoa" feel, so I usually prefer that route.
  7. mraheel thread starter macrumors regular

    Apr 18, 2009
    Yea, delegation keeps things very clean. Theres so much mess when you dont follow the "Cocoa" model.
    I've created the ViewController associated with the PopUpView. THe number of buttons remain the same after loading.

    when you say form a delegate, you mean declaring "id delegate" and assigning it when creating/initialising the PopUpViewController right?
  8. North Bronson macrumors 6502

    Oct 31, 2007
    San José
    When you setup your view class, you can do something like:

    @interface PopUpView: UIView
        id <PopUpViewDelegate> myDelegate;
    - (id)initViewWithDelegate:(id)delegate;
    and then assign your delegate in the init method.

    When you say that you've "created the view controller" what does that mean? Is the PopUpView displaying as a subview of a "main view"? You should let the same view controller manage everything instead of using a different view controller for views on the same page.
  9. mraheel thread starter macrumors regular

    Apr 18, 2009
    I actually made it to a viewController. Well, im a beginner so you mite get a very obnoxious answer! ahem
    using the popup view was fine, until, there was a certain lag after every tap. On tap, a new popupView was being created everytime and perhaps released with it. Hence kind of a new view was initialised.

    I wanted it to be like ViewController, once loaded, remains until app exit. Considering that this popupView will be frequently used and I have only a 2 view controllers. One Main and another DetailViewController, I thought maybe this mite get rid of the lag everytime. I didnt quite make this happen though!.

    I really appreciate your help man. thanks;
  10. North Bronson macrumors 6502

    Oct 31, 2007
    San José
    Don't fight the frameworks. Your screenful of content should be managed by only one view controller. That view controller has one view. Your PopUpView (UIView subclass) is a subview of that one view.

    If you are having problems with lag, you don't have to release the view whenever it's dismissed. There are ways around that.

    If you are a beginner and you are having a hard time figuring out how to manage views and view controllers, have you taken a long look at the iPhone Application Programming Guide?
  11. mraheel thread starter macrumors regular

    Apr 18, 2009
    Yea, your right. Im deleting the ViewController files.
    I'm creating variable number of buttons. And I've if dont release the view, those buttons are probably retained. and will recur every other time.

    But then again, as you said, maybe its best this way.

    Thanks alot man, your great help, I'm reading several tutorials on the net everyday. The thing is, iPhone SDK makes making apps so easy(kudos to Apple for that) that we [beginners] sometimes overlook the basics before adventuring, specially when your not in the Computer world professionally!
  12. North Bronson macrumors 6502

    Oct 31, 2007
    San José
    Have you thought about displaying these buttons in a UITableView? The UITableView would handle things like recycling table cell views (for efficiency) and provides some handy delegate methods for setting up each cell.

    You could create a UITableViewCell subclass that holds a button, and populate the UITableView with these custom cells.

    If you plan on displaying all your buttons vertically, this might save you a little time. Creating your own view from scratch might be a good learning experience, though. Creating your own view should also give you better performance because you're not drawing an extra layer.
  13. mraheel thread starter macrumors regular

    Apr 18, 2009
    Yes, I did think about UITableView and tried it too. The View is the issue here. I didnt know how I would resize the tableView.

    For example, If I have only 3 buttons to show, the tableView height should be the size of those three Cells,
    If the buttons are more, then again increase the Box in size.

    I'm trying to accomplish the effect of the popup like in the screenshot[attached] in a completely unrelated app.

    But as i'm typing this, i'm getting some ideas of how to include the tableView. and I'm giving it a try now!! lol!

    Attached Files:

    • ss1.jpg
      File size:
      32.6 KB
  14. North Bronson macrumors 6502

    Oct 31, 2007
    San José
    If you don't need scrolling, I think different people will give you advice whether or not to go with a table view. Personally, I could see arguments for both ways (working with a table view or subclassing a UIView).

    In the screenshot, what are people tapping to make your action happen? Is it the icon on the left, the text on the right, or the whole "region"?
  15. mraheel thread starter macrumors regular

    Apr 18, 2009
    The tapping goes throughout, the icon and text both get selected till ends. And Yea, I dont need the scrolling. Whats different from the screenshot is that those are FIXED number of buttons, fixed Box width, height, But in my case thats variable.

Share This Page