A simple drop down list for iPhone

It is often the case that the controls provided by iOS for the iPhone or iPad don’t quite meet our needs. In this blog we’ll learn how to mimic a simple Drop – Down list using a label, some custom buttons, and a hidden view. So let’s get started!

Open Xcode, choose “Create a new Xcode project,” select the Single View Application template, and click Next. Name the project “DropDownDemo,” and choose options as shown here:

Click Next, choose a location to save the project, and click Create.

When the app template has been created, open the ViewController.zib file, and drag controls to the view as shown below:

The properties for these controls should be set in the following way:

 View: no properties set
◦ Label – Select A Color: Change the text to “Select A Color,” change the background to a light yellow color.
◦ Button: Change the text to “▼” by navigating to Edit | Special Characters in the menu, then selecting the down arrow character. Change the font to System Bold 10.0. Change the background to a light yellow color. The button type is set to Custom.
◦ View: align the left and right sides of the view to the left side of the label and the right side of the button above it. We will also hide this button by checking the “Hidden” checkbox, but not just yet.
▪ Button – Red: set the button type to Custom, the text to “Red,” align the top of the button with the top of its containing view, and the left and right sides of the button with the left and right sides of the view. Set the tag value to 1, and the height of the button to 36.
▪ Button – Blue: as above, but the text is “Blue”, and the tag value is 2
▪ Button – Green: as above, but the text is “Green”, and the tag value is 3

After making these changes, select the view that contains the three buttons (Red, Blue, and Green), and put a check mark in the Hidden property.

Open the ViewController.h file, and add the following properties and methods:

</div>
<div class="objc codesnip"></div>
<div class="objc codesnip"><span class="co1">#import <UIKit/UIKit.h></span><span class="kw1">@interface</span> ViewController <span class="sy0">:</span> UIViewController<span class="kw1">@property</span> <span class="br0">(</span>nonatomic, strong<span class="br0">)</span> IBOutlet UILabel <span class="sy0">*</span>ddText;
<span class="kw1">@property</span> <span class="br0">(</span>nonatomic, strong<span class="br0">)</span> IBOutlet UIView <span class="sy0">*</span>ddMenu;
<span class="kw1">@property</span> <span class="br0">(</span>nonatomic, strong<span class="br0">)</span> IBOutlet UIButton <span class="sy0">*</span>ddMenuShowButton;

<span class="sy0">-</span> <span class="br0">(</span>IBAction<span class="br0">)</span>ddMenuShow<span class="sy0">:</span><span class="br0">(</span>UIButton <span class="sy0">*</span><span class="br0">)</span>sender;
<span class="sy0">-</span> <span class="br0">(</span>IBAction<span class="br0">)</span>ddMenuSelectionMade<span class="sy0">:</span><span class="br0">(</span>UIButton <span class="sy0">*</span><span class="br0">)</span>sender;

<span class="kw1">@end</span>

</source>

&nbsp;

</div>
</div>
In the ViewController.zib file, wire up ddText to the UILabel, ddMenu to the hidden view, and ddMenuShowButton to the small custom button containing the “▼” character. The ddMenuShow method is also wired to this small custom button (Touch Up Inside), and each of the other custom buttons (Red, Blue, and Green) are wired to the ddMenuSelectionMade method, also on TouchUpInside.

Next, open the ViewController.h file, and make changes as shown below:
<div class="codesnip-container">
<div class="objc codesnip"></div>
<div class="objc codesnip"></div>
<div class="objc codesnip"><span class="co1">#import "ViewController.h"</span><span class="kw1">@interface</span> ViewController <span class="br0">(</span><span class="br0">)</span><span class="kw1">@end</span>

<span class="kw1">@implementation</span> ViewController

<span class="kw1">@synthesize</span> ddMenu, ddText;
<span class="kw1">@synthesize</span> ddMenuShowButton;

<span class="sy0">-</span> <span class="br0">(</span>IBAction<span class="br0">)</span>ddMenuShow<span class="sy0">:</span><span class="br0">(</span>UIButton <span class="sy0">*</span><span class="br0">)</span>sender
<span class="br0">{</span>
<span class="kw1">if</span> <span class="br0">(</span>sender.tag <span class="sy0">==</span> 0<span class="br0">)</span> <span class="br0">{</span>
sender.tag <span class="sy0">=</span> <span class="nu0">1</span>;
self.ddMenu.hidden <span class="sy0">=</span> <span class="kw2">NO</span>;
<span class="br0">[</span>sender setTitle<span class="sy0">:</span><span class="co3">@</span><span class="st0">"▲"</span> forState<span class="sy0">:</span>UIControlStateNormal<span class="br0">]</span>;
<span class="br0">}</span> <span class="kw1">else</span> <span class="br0">{</span>
sender.tag <span class="sy0">=</span> <span class="nu0">0</span>;
self.ddMenu.hidden <span class="sy0">=</span> <span class="kw2">YES</span>;
<span class="br0">[</span>sender setTitle<span class="sy0">:</span><span class="co3">@</span><span class="st0">"▼"</span> forState<span class="sy0">:</span>UIControlStateNormal<span class="br0">]</span>;
<span class="br0">}</span>
<span class="br0">}</span>

<span class="sy0">-</span> <span class="br0">(</span>IBAction<span class="br0">)</span>ddMenuSelectionMade<span class="sy0">:</span><span class="br0">(</span>UIButton <span class="sy0">*</span><span class="br0">)</span>sender
<span class="br0">{</span>
self.ddText.text <span class="sy0">=</span> sender.titleLabel.text;
<span class="br0">[</span>self.ddMenuShowButton setTitle<span class="sy0">:</span><span class="co3">@</span><span class="st0">"▼"</span>forState<span class="sy0">:</span>UIControlStateNormal<span class="br0">]</span>;
self.ddMenuShowButton.tag <span class="sy0">=</span> <span class="nu0">0</span>;
self.ddMenu.hidden <span class="sy0">=</span> <span class="kw2">YES</span>;
<span class="kw1">switch</span> <span class="br0">(</span>sender.tag<span class="br0">)</span> <span class="br0">{</span>
<span class="kw1">case</span> 1<span class="sy0">:</span>
self.view.backgroundColor <span class="sy0">=</span> <span class="br0">[</span>UIColor redColor<span class="br0">]</span>;
<span class="kw2">break</span>;
<span class="kw1">case</span> 2<span class="sy0">:</span>
self.view.backgroundColor <span class="sy0">=</span> <span class="br0">[</span>UIColor blueColor<span class="br0">]</span>;
<span class="kw2">break</span>;
<span class="kw1">case</span> 3<span class="sy0">:</span>
self.view.backgroundColor <span class="sy0">=</span> <span class="br0">[</span>UIColor greenColor<span class="br0">]</span>;
<span class="kw2">break</span>;

<span class="kw1">default</span><span class="sy0">:</span>
<span class="kw2">break</span>;
<span class="br0">}</span>
<span class="br0">}</span>
…

</div>
</div>

As always, we begin by synthesizing the properties. After this, we implement our two action methods. The ddMenuShow method shows or hides the menu depending on the current state of its tag. It also changes the direction of the arrow character using the setTitle: forState: method. NSStrings are Unicode strings, so it’s legal to use special characters directly in the string as we’ve done here.

The ddMenuSelectionMade method changes the color of the main view’s background depending on the tag value of the button pushed. It also makes changes to the ddMenuShowButton, and hides the ddMenu view.

Save and run the application.

In a production application, we would certainly want to create a custom UIControl and make the appearance of our drop down box conform to the Human Interface Guidelines. But this technique is a simple way to obtain functionality quickly for testing purposes during the development process.

Have Fun!

 

http://www.edumobile.org/iphone/iphone-programming-tutorials/a-simple-drop-down-list-for-iphone/

Using UIPageControl as a container UIViewController

Setting up the interface

To setup the user interface in Interface Builder, you’ll need to create a UIPageControl and a UIScrollView within a UIViewController, and as many other UIViewControllers as to need.

Setting up the PageViewController class

The PageViewController will contain 2 subview a UIScrollView and a UIPageControl. The UIScrollView will contain the views while the UIPageControl will navigate and control which part of the UIScrollView is visible.
You’ll also need some mechanism for calling addChildViewController: on the view controller, I’m my example I did this by sub-classing PagerViewController, but you could also do this before the view controller is push into view.

So, the public interface should look like this:

@interface PagerViewController : UIViewController 
 
@property (nonatomic, strong) IBOutlet UIScrollView *scrollView;
@property (nonatomic, strong) IBOutlet UIPageControl *pageControl;
 
- (IBAction)changePage:(id)sender;
 
@end

On to the implementation file. First of all, I want to handle all the view appearence at rotation calls myself so, we need to over-ride automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers and return NO indicating we don’t want the UIViewController super class doing this.
When the PagerViewController view comes into view, we will need to signal to the currently active child view controller that it has become visible. So we will forward on the view appeared/disappeared messages.

- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
	return NO;
}
 
- (void)viewDidAppear:(BOOL)animated {
	[super viewDidAppear:animated];
	UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
	if (viewController.view.superview != nil) {
		[viewController viewDidAppear:animated];
	}
}
 
- (void)viewWillDisappear:(BOOL)animated {
	UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
	if (viewController.view.superview != nil) {
		[viewController viewWillDisappear:animated];
	}
	[super viewWillDisappear:animated];
}
 
- (void)viewDidDisappear:(BOOL)animated {
	UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
	if (viewController.view.superview != nil) {
		[viewController viewDidDisappear:animated];
	}
	[super viewDidDisappear:animated];
}

viewWillAppear is a little more complex since we also want to load all the child view controllers into the scroll view (we’ll cover loadScrollViewWithPage next), and also make sure the scroll view’s content size is large enough to handle all the child views.

- (void)viewWillAppear:(BOOL)animated {
	[super viewWillAppear:animated];
 
	for (NSUInteger i =0; i < [self.childViewControllers count]; i++) {
		[self loadScrollViewWithPage:i];
	}
 
	self.pageControl.currentPage = 0;
	_page = 0;
	[self.pageControl setNumberOfPages:[self.childViewControllers count]];
 
	UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
	if (viewController.view.superview != nil) {
		[viewController viewWillAppear:animated];
	}
 
	self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [self.childViewControllers count], scrollView.frame.size.height);
}

To load the content of the UIViewController into the UIScrolView contentView we go though each child and add its view as a subview of the UIScrollView off-setting the origin by a screen width each time.

- (void)loadScrollViewWithPage:(int)page {
    if (page < 0)
        return;
    if (page >= [self.childViewControllers count])
        return;
 
	// replace the placeholder if necessary
    UIViewController *controller = [self.childViewControllers objectAtIndex:page];
    if (controller == nil) {
		return;
    }
 
	// add the controller's view to the scroll view
    if (controller.view.superview == nil) {
        CGRect frame = self.scrollView.frame;
        frame.origin.x = frame.size.width * page;
        frame.origin.y = 0;
        controller.view.frame = frame;
        [self.scrollView addSubview:controller.view];
    }
}

Handling scrolling

To handle scrolling we need to implement a few UIScrollViewDelegate methods and also the - (IBAction)changePage:(id)sender method we declared earlier.
We need to know how the scrolling occurred, i.e. was it initiated from a gesture swipe across the screen, or by tapping either side of the UIPageControl.

To work this out we update an ivar when the various delegate callback are called..
This code is largely taken from this Cocoa with Love post
I also call the child UIViewController’s viewillAppear etc. methods.

// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
         _pageControlUsed = NO;
}
 
// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
         _pageControlUsed = NO;
}
 
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
        UIViewController *oldViewController = [self.childViewControllers objectAtIndex:_page];
        UIViewController *newViewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
        [oldViewController viewDidDisappear:YES];
        [newViewController viewDidAppear:YES];
 
        _page = self.pageControl.currentPage;
}

Now, to update the display after the page change we just need implement the scrollViewDidScroll delegate method and the changePage IBAction method.
changing the viewable UIViewController is done by simply scrolling the UIScrollView to the appropriate location.

- (IBAction)changePage:(id)sender {
        int page = ((UIPageControl *)sender).currentPage;
 
        // update the scroll view to the appropriate page
        CGRect frame = self.scrollView.frame;
        frame.origin.x = frame.size.width * page;
        frame.origin.y = 0;
 
        UIViewController *oldViewController = [self.childViewControllers objectAtIndex:_page];
        UIViewController *newViewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
        [oldViewController viewWillDisappear:YES];
        [newViewController viewWillAppear:YES];
 
        [self.scrollView scrollRectToVisible:frame animated:YES];
 
        // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above.
        _pageControlUsed = YES;
}
 
- (void)scrollViewDidScroll:(UIScrollView *)sender {
    // We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
    // which a scroll event generated from the user hitting the page control triggers updates from
    // the delegate method. We use a boolean to disable the delegate logic when the page control is used.
    if (_pageControlUsed || _rotating) {
        // do nothing - the scroll was initiated from the page control, not the user dragging
        return;
    }
 
    // Switch the indicator when more than 50% of the previous/next page is visible
        CGFloat pageWidth = self.scrollView.frame.size.width;
        int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
        if (self.pageControl.currentPage != page) {
                UIViewController *oldViewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
                UIViewController *newViewController = [self.childViewControllers objectAtIndex:page];
                [oldViewController viewWillDisappear:YES];
                [newViewController viewWillAppear:YES];
                self.pageControl.currentPage = page;
                [oldViewController viewDidDisappear:YES];
                [newViewController viewDidAppear:YES];
                _page = page;
        }
}

Finally, Rotation

To handle device rotation, we need to return YES from shouldAutorotateToInterfaceOrientation.
We also need to pass on the following messages to the currently active child UIViewController.

  • willAnimateRotationToInterfaceOrientation:duration:
  • willRotateToInterfaceOrientation:duration:
  • didRotateFromInterfaceOrientation:

But, we also need to handle our own rotation, i.e. resizing the scrollviews contentView, and adjusting the frame of the child subviews, otherwise everything is miss-aligned. This is done inwillAnimateRotationToInterfaceOrientation:duration:, so that the resizing is also animated.

When the frame of UIScrollView adjusts scrollViewDidScroll: also gets called, so to prevent that from flipping us to a different page we set and unset the _rotating flag in the following methods:

  • willRotateToInterfaceOrientation:duration:
  • didRotateFromInterfaceOrientation:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
	return YES;
}
 
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
	UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
	[viewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
	_rotating = YES;
}
 
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
 
	UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
	[viewController willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
 
	self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [self.childViewControllers count], scrollView.frame.size.height);
	NSUInteger page = 0;
	for (viewController in self.childViewControllers) {
		CGRect frame = self.scrollView.frame;
		frame.origin.x = frame.size.width * page;
		frame.origin.y = 0;
		viewController.view.frame = frame;
		page++;
	}
 
	CGRect frame = self.scrollView.frame;
	frame.origin.x = frame.size.width * _page;
	frame.origin.y = 0;
	[self.scrollView scrollRectToVisible:frame animated:NO];
 
}
 
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
	_rotating = NO;
	UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
	[viewController didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}

Conclusion

 

For fully working example project see this repository on GitHub

Change RGB color of the picture


- (UIImage *) changeColor: (UIImage *)image {
     UIGraphicsBeginImageContext(image.size);
     
     CGRect contextRect;
     contextRect.origin.x = 0.0f;
     contextRect.origin.y = 0.0f;
     contextRect.size = [image size];
     // Retrieve source image and begin image context
     CGSize itemImageSize = [image size];
     CGPoint itemImagePosition; 
     itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width) / 2);
     itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height) );
     
     UIGraphicsBeginImageContext(contextRect.size);
     
     CGContextRef c = UIGraphicsGetCurrentContext();
     // Setup shadow
     // Setup transparency layer and clip to mask
     CGContextBeginTransparencyLayer(c, NULL);
     CGContextScaleCTM(c, 1.0, -1.0);
     CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [image CGImage]);
     
     
     switch (colorSelected) {
          case 0:
               CGContextSetRGBFillColor(c, 0, 0, 1, 1);
               break;

          default:
               CGContextSetRGBFillColor(c, 1, 0, 0., 1);
               break;
     }
     
     contextRect.size.height = -contextRect.size.height;
     contextRect.size.height -= 15;
     // Fill and end the transparency layer
     CGContextFillRect(c, contextRect);
     CGContextEndTransparencyLayer(c);

     UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
     return img;
}

How to Pass Data Between UIViewControllers: The Global Variable & The Singleton Class

GLOBAL VARIABLES

The simple, but crude way is to use Global Variables. Global Variables can get messy because once you use a certain name as global variable, you can not use it again at ANY OTHER PLACES. And this can get confusing when you have many lines of codes and more than one class.

A quick example of Global Variable Declaration is as follows:

In your header (.h) file, input the “allocation” of the variable.

  1.  
  2. #import <UIKit/UIKit.h>;
  3. extern BOOL MYGlobalVariable;
  4. @interface BattleGameViewController : UIViewController
  5. @end;

“extern” does not declare it. What it does is just “allocate” a memory for that particular variable. Therefore to declare it, one need to declare in the implementation file (*.m) as follows:

  1. #import “MyAppHeader.h”
  2. @implementation BattleGameViewController
  3. BOOL MYGlobalVariable = NO;

So to use this variable in another class, all you need to do is import “MyAppHeader.h” and MYGlobalVariable should be ready to be used.

It works well, in fact, I also used it in some of my early apps. That is until I learn about Singleton.

SINGLETON

Believe it or not, MOST of us NOOBIES already used Singleton. The most common Singleton we use is…. *drumroll*… NSUserDefaults!

Do you like NSUserDefaults? I do. It is so easy and simple. And that is why you also should use Singleton in variable aspects of your app. It will make your coding very nice and easy to maintain.

How to implement a Singleton? I am no ObjC Guru, that much I can tell you, but hey, why reinvent the wheel, when some gurus have created the Singleton class for you? There are loadsssss of ways to write a Singleton Class, and you can find them here:

StackOverflow: Samples of Singletons

Anyway, here is MY singleton class. I used this Singleton class in one of my latest app – Clock Stand for iPad. I stripped off all the other variables and leave just 1 for example so that it is clear for you to see how to implement it.

  1. //
  2. //  MySingletonCenter.h
  3. //  ClockForiPad
  4. //
  5. //  Created by Emir Fithri Samsuddin on 6/20/12.
  6. //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
  7. //
  8. #import <Foundation/Foundation.h>
  9. @interface MySingletonCenter : NSObject {
  10. // Your variables go here
  11. // here’s one example:
  12.   BOOL is24Hour;
  13. }
  14. // Your property settings for your variables go here
  15. // here’s one example:
  16. @property (nonatomic, assign) BOOL is24Hour;
  17. // This is the method to access this Singleton class
  18. + (MySingletonCenter *)sharedSingleton;
  19. @end

And the implementation file (*.m)

  1. //
  2. //  MySingletonCenter.m
  3. //  ClockForiPad
  4. //
  5. //  Created by Emir Fithri Samsuddin on 6/20/12.
  6. //  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
  7. //
  8. #import “MySingletonCenter.h”
  9. @implementation MySingletonCenter
  10. static MySingletonCenter *shared = NULL;
  11. @synthesize is24Hour;
  12. – (id)init
  13. {
  14.     if ( self = [super init] )
  15.     {
  16.        // init values 
  17.        // here you assign initial values to your variable.
  18.        // in my case, I save all these values into NSUserDefaults as users preference.
  19.        // so i do the necessary things to ensure that happens.
  20.         NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
  21.         if ([def objectForKey:@“is24Hour”]==nil) {
  22.             is24Hour = NO;
  23.             [def setBool:self.is24Hour forKey:@“is24Hour”];
  24.             [def synchronize];
  25.         } else {
  26.             // read from NSUserDefaults
  27.             self.is24Hour = [def boolForKey:@“is24Hour”];
  28.         }
  29.     }
  30.     return self;
  31. }
  32. + (MySingletonCenter *)sharedSingleton
  33. {
  34.     @synchronized(shared)
  35.     {
  36.         if ( !shared || shared == NULL )
  37.         {
  38.             // allocate the shared instance, because it hasn’t been done yet
  39.             shared = [[MySingletonCenter alloc] init];
  40.         }
  41.         return shared;
  42.     }
  43. }
  44. – (void)dealloc
  45. {
  46.     NSLog(@“Deallocating singleton…”);
  47.     [super dealloc];
  48. }
  49. @end

Now, to create the Singleton Class, all you need to do is Right Click on the left panel of XCode and Choose Add File… and Choose Objective-C Class. Give a proper name (for eg, MySingletonCenter.h and MySingletonCenter.m) to it and add to project. After that just copy and paste the above Singleton code into the corresponding .h and .m. And you’re set to go.

To use Singleton in another class is easy.. in fact super easy just like NSUserDefaults.

1. #import “MySingletonCenter.h”

2. Everytime you want to read or write to it:

  1. MySingletonCenter *tmp = [MySingletonCenter sharedSingleton];
  2. // write
  3. tmp.is24Hour = YES;
  4. // read
  5. BOOL new = tmp.is24Hour;

 

 

Reference: http://xcodenoobies.blogspot.com/2012/08/how-to-pass-data-between.html