How to change search icon inside UISearchBar? - objective-c

I am trying to change the search icon inside an UISearchBar in iOS7 and ok, I got it. But is this the best way?
[self.searchBar setImage:[UIImage imageNamed: #"searchIcon.png"]
forSearchBarIcon:UISearchBarIconSearch
state:UIControlStateNormal];
And the problem is that the image size is not great as the original, I would like to know the correct size to replace the image. I am using an image = 64x64 and an image#2x = 128x128, is it correctly? If so, why my search bar is like this:

You can achieve this by setting the leftView of the searchField
if let textFieldInsideSearchBar = self.searchBar.valueForKey("searchField") as? UITextField {
textFieldInsideSearchBar.leftView = imageView
}

to Replace the magnifying glass icon in an iPhone UISearchBar with a custom image use this code
#import <UIKit/UIKit.h>
#interface SearchBoxExperimentsViewController : UIViewController {
IBOutlet UISearchBar *searchBar;
}
#end
#import "SearchBoxExperimentsViewController.h"
#interface SearchBoxExperimentsViewController (Private)
- (void)setSearchIconToFavicon;
#end
#implementation SearchBoxExperimentsViewController
- (void)viewDidLoad {
[self setSearchIconToFavicon];
[super viewDidLoad];
}
#pragma mark Private
- (void)setSearchIconToFavicon {
// Really a UISearchBarTextField, but the header is private.
UITextField *searchField = nil;
for (UIView *subview in searchBar.subviews) {
if ([subview isKindOfClass:[UITextField class]]) {
searchField = (UITextField *)subview;
break;
}
}
if (searchField) {
UIImage *image = [UIImage imageNamed: #"favicon.png"];
UIImageView *iView = [[UIImageView alloc] initWithImage:image];
searchField.leftView = iView;
[iView release];
}
}
#end

Related

Custom view for NSPopupButton NSMenu

I'm having some problems setting a custom NSView for my NSPopupButton menu items. Here is what I've got so far:
#interface ViewController ()
#property (weak) IBOutlet NSPopUpButton *popupButton;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
for(int i = 0; i < 25; i++) {
NSMenuItem *menuItem = [[NSMenuItem alloc ] initWithTitle:[NSString stringWithFormat:#"%d", i] action:#selector(itemClicked:) keyEquivalent:#""];
MenuView *menuView = [[MenuView alloc] initWithFrame:CGRectMake(0, 0, 184, 50)];
menuView.displayText.stringValue = #"This is a test";
[menuItem setView:menuView];
[self.popupButton.menu addItem:menuItem];
}
}
- (void)itemClicked:(id)sender {
}
#end
//My custom view
#implementation MenuView
- (id)initWithFrame:(NSRect)frameRect {
NSString* nibName = NSStringFromClass([self class]);
self = [super initWithFrame:frameRect];
if (self) {
if ([[NSBundle mainBundle] loadNibNamed:nibName
owner:self
topLevelObjects:nil]) {
[self configureView];
}
}
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self configureView];
}
- (void)configureView {
[self setWantsLayer:YES];
self.layer.backgroundColor = [NSColor blueColor].CGColor;
}
#end
//Here is what my xib MenuView looks like
And here is the problem:
This seems like it should be a fairly straight forward task but I'm not sure what is happening to my view and why my label on the view seems to disappear and is not showing any text for each of the views. I was poking around in the documentation and stumbled across this for the NSPopupButton Menu :
// Overrides behavior of NSView. This is the menu for the popup, not a context menu. PopUpButtons do not have context menus.
#property (nullable, strong) NSMenu *menu;
I'm not sure if there is something that I'm doing wrong that is causing this problem or if what I'm trying to do in this context is not achievable off of an NSPopupButton NSMenu. If anyone has any experience with this and could offer advice I'd really appreciate it.

iOS: Styling multiple textfields

I have multiple UITextFields with the same/similar styling but I'm styling them individually. How would I style them all in on go?
example of what I'm doing now:
textfield1.layer.borderWith = 2;
textfield2.layer.borderWith = 2;
textfield3.layer.borderWith = 2;
Here's something I've used in the past:
UITextField * textField1;
UITextField * textField2;
UITextField * textField3;
for (UITextField * textField in #[textField1, textField2, textField3]) {
textField.layer.borderWidth = 2;
}
If you're doing extensive edits to create a highly customized textField, it might be better to use a subclass. If you've just got a few additions you want applied to each textfield, this should be fine.
As per your request, because I'm feeling generous. Here's an example of a UITextField subclass.
MyTextField.h
#import <UIKit/UIKit.h>
#interface MyTextField : UITextField
#end
MyTextField.m
#import "MyTextField.h"
#implementation MyTextField
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.layer.borderWidth = 2;
// Blue For Demonstration
self.layer.borderColor = [UIColor blueColor].CGColor;
// add whatever else you want to customize here ....
}
return self;
}
////////
////// ** Include Custom Methods You Might Need **
////////
#end
Then, in whatever ViewController or View you want to use it, add this:
#import "MyTextField.h"
Then, you can launch MyTextField class Textfields like this:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
MyTextField * textField1 = [MyTextField new];
textField1.frame = CGRectMake(10, 30, 100, 30);
[self.view addSubview:textField1];
MyTextField * textField2 = [MyTextField new];
textField2.frame = CGRectMake(10, 70, 100, 30);
[self.view addSubview:textField2];
MyTextField * textField3 = [MyTextField new];
textField3.frame = CGRectMake(10, 110, 100, 30);
[self.view addSubview:textField3];
}
And you'll get this:
How about --
for (UIView *view in [self.view subviews]) {
if ([view isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *)view;
textField.layer.borderWidth = 2.0;
}
}
That way you will not even have to have outlets of textFields in the view. But this is, of course, only applicable if you want to apply same styles to every textField in the view.
If the textfields have outlets, create an IBOutletCollection like so in your .h:
#property (strong, nonatomic) IBOutletCollection(UITextField) NSArray *textFields;
Then, in your .m:
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
for(UITextField *textField in self.textFields) {
textfield.layer.borderWith = 2;
// add more here as needed
}
}

My animation won't start

I've done this code to start animation when i click a button, when I click the button is should change what the button says and start the animation, but it only changes what the button says ? Is there anything wrong with my code?
#synthesize SwishImage;
#synthesize SwishButton;
- (IBAction) Swish {
if (SwishImage.isAnimating) {
[SwishImage stopAnimating];
[SwishButton setTitle:#"Swish" forState:UIControlStateNormal];
} else {
[SwishImage startAnimating];
[SwishButton setTitle:#"Searching" forState:UIControlStateNormal];
}
}
- (void)viewdidload
{
NSArray * SwishArray;
SwishArray = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"Orange_dot.png"],
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"2.png"],
[UIImage imageNamed:#"3.png"],
[UIImage imageNamed:#"4.png"],
nil];
SwishImage.animationImages=SwishArray;
SwishImage.animationDuration = 1;
SwishImage.animationRepeatCount = 0;
[super viewDidLoad];
}
When I copied this into an empty Xcode project and linked everything correctly in Interface Builder the image view started animating. I assume something isn't correctly linked in Interface Builder.
That being said, your code is a bit awkward from a standards perspective. Variable names should begin with a lower case letter (and that includes properties). You don't need #synthesize anymore and there is a new shortcut for NSArray. Here is how your classes should look:
ViewController.h
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIImageView *swishImage;
#property (strong, nonatomic) IBOutlet UIButton *swishButton;
#end
ViewController.m
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *swishArray = #[
[UIImage imageNamed:#"Orange_dot.png"],
[UIImage imageNamed:#"1.png"],
[UIImage imageNamed:#"2.png"],
[UIImage imageNamed:#"3.png"],
[UIImage imageNamed:#"4.png"],
];
self.swishImage.animationImages=swishArray;
self.swishImage.animationDuration = 1;
self.swishImage.animationRepeatCount = 0;
}
- (IBAction)swish:(id)sender {
if (self.swishImage.isAnimating) {
[self.swishImage stopAnimating];
[self.swishButton setTitle:#"Swish" forState:UIControlStateNormal];
} else {
[self.swishImage startAnimating];
[self.swishButton setTitle:#"Searching" forState:UIControlStateNormal];
}
}
#end
Then just select your image view and go to the Connections Inspector. You should see a section titled Referencing Outlets, make sure that swishImage is connected to your view controller.

custom UIView using objective-c

I want to write a custom UIView that does the following:
It takes an image and adds it to a view.
It has a method to flip that image.
I want to pass this Custom UIView to the iCarousel class:
https://github.com/nicklockwood/iCarousel
How can I create a custom UIView using Objective C and Cocoa?
I started by doing the following:
CItem.h
#import <UIKit/UIKit.h>
#interface CItem : UIView
{
UIImageView *box;
}
#property (nonatomic, retain) UIImageView * box;
#end
CItem.m
#import "CItem.h"
#implementation CItem
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
box = [[UIImageView alloc] initWithFrame:CGRectMake(0,0, 240, 240)];
[box setImage:[UIImage imageNamed:# "cleaning.png"]];
[self addSubview:box];
}
#end
You should not add your addSubview: in drawRect:. See this method's disscussion:
Discussion
The default implementation of this method does nothing.
Subclasses that use native drawing technologies (such as Core Graphics
and UIKit) to draw their view’s content should override this method
and implement their drawing code there. You do not need to override
this method if your view sets its content in other ways. For example,
you do not need to override this method if your view just displays a
background color or if your view sets its content directly using the
underlying layer object. Similarly, you should not override this
method if your view uses OpenGL ES to do its drawing.
If you don't use a xib file for your CItem you can add your code to initWithFrame:.
//CItem.h
#import <UIKit/UIKit.h>
#interface CItem : UIView
- (void)flip;
#end
// CItem.m
#import "CItem.h"
#interface CItem()
#property (assign, nonatomic) BOOL displayingPrimary;
#property (strong, nonatomic) UIImageView *primaryView;
#property (strong, nonatomic) UIImageView *secondaryView;
#end
#implementation CItem
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_primaryView = [[UIImageView alloc] initWithFrame:frame];
[_primaryView setImage:[UIImage imageNamed:# "cleaning.jpg"]];
[self addSubview:_primaryView];
_secondaryView = [[UIImageView alloc] initWithFrame:frame];
[_secondaryView setImage:[UIImage imageNamed:# "adding.jpg"]];
[self addSubview:_secondaryView];
}
return self;
}
- (void)flip
{
[UIView transitionFromView:(self.displayingPrimary ? self.primaryView : self.secondaryView)
toView:(self.displayingPrimary ? self.secondaryView : self.primaryView)
duration:1.0
options:(self.displayingPrimary ? UIViewAnimationOptionTransitionFlipFromRight :
UIViewAnimationOptionTransitionFlipFromLeft) | UIViewAnimationOptionShowHideTransitionViews
completion:^(BOOL finished) {
if (finished) {
self.displayingPrimary = !self.displayingPrimary;
}
}];
}
#end
Then you can use CItem like this:
CItem *subView = [[CItem alloc] initWithFrame:CGRectMake(0, 0, 320, 400)];
[self.view addSubview:subView];
You should only implement drawRect if you intend to do custom drawing. If you want to use subviews you can just move your code into the initWithFrame:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
box = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 240.0f, 240.0f)];
[box setImage:[UIImage imageNamed:#"cleaning"]];
[self addSubview:box];
}
return self;
}
You can safely remove the drawRect method. Not sure what you mean by "flipping" the image, but you should be able to manipulate the imageView object using the "box" property of your custom class.

Infinite UIScrollView not working on iOS 4.3

I try to build a endless scrolling UIScrollView. So far I took the apple sample "StreetScroller". So all I do is setting the contentOffset back when it reaches the end of the scroll view.
Override -layoutSubviews of the UIScrollView:
- (void)layoutSubviews
{
CGFloat contentWidth = [self contentSize].width;
CGPoint contentOffset = [self contentOffset];
CGFloat centerOffsetX = (contentWidth - [self bounds].size.width) / 2.0;
CGFloat distanceFromCenter = contentOffset.x - centerOffsetX;
if (ABS(distanceFromCenter) > (contentWidth / 4.0)) {
contentOffset = CGPointMake(centerOffsetX, contentOffset.y);
[super setContentOffset:contentOffset];
}
}
Now on iOS 5 this works like a charm. But on iOS 4.3 it's not working. As soon as I call [super setContentOffset:contentOffset] it stoops scrolling because next time -layoutSubviews get's called the [self contentOffset] does not return the contentOffset that was set.
I know there are a lot a questions about infinite UIScrollViews, but one of these has fixed this problem!
Try this One. This Code is Working Properly for me on iOS 4.3
RootViewController.h
#class ViewControllerForDuplicateEndCaps;
#interface RootViewController : UIViewController {
ViewControllerForDuplicateEndCaps *viewControllerForDuplicateEndCaps;
}
#property (nonatomic, retain) ViewControllerForDuplicateEndCaps *viewControllerForDuplicateEndCaps;
- (IBAction)loadScrollViewWithDuplicateEndCaps:(id)sender;
#end
RootViewController.m
#import "RootViewController.h"
#import "ViewControllerForDuplicateEndCaps.h"
#import "InfiniteScrollViewAppDelegate.h"
#implementation RootViewController
#synthesize viewControllerForDuplicateEndCaps;
- (IBAction)loadScrollViewWithDuplicateEndCaps:(id)sender {
InfiniteScrollViewAppDelegate *delegate = (InfiniteScrollViewAppDelegate*)[[UIApplication sharedApplication] delegate];
if(self.viewControllerForDuplicateEndCaps == nil) {
ViewControllerForDuplicateEndCaps *temp = [[ViewControllerForDuplicateEndCaps alloc] initWithNibName:#"ViewControllerForDuplicateEndCaps" bundle:nil];
self.viewControllerForDuplicateEndCaps = temp;
[temp release];
}
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:nil action:nil];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
[delegate.navigationController pushViewController:self.viewControllerForDuplicateEndCaps animated:YES];
}
- (void)dealloc {
[scrollView release];
[super dealloc];
}
#end
ViewControllerForDuplicateEndCaps.h
#import <UIKit/UIKit.h>
#interface ViewControllerForDuplicateEndCaps : UIViewController <UIScrollViewDelegate> {
IBOutlet UIScrollView *scrollView;
}
#property (nonatomic, retain) UIScrollView *scrollView;
- (void)addImageWithName:(NSString*)imageString atPosition:(int)position;
#end
ViewControllerForDuplicateEndCaps.m
#import "ViewControllerForDuplicateEndCaps.h"
#implementation ViewControllerForDuplicateEndCaps
#synthesize scrollView;
- (void)viewDidLoad {
[super viewDidLoad];
// add the last image (image4) into the first position
[self addImageWithName:#"image4.jpg" atPosition:0];
// add all of the images to the scroll view
for (int i = 1; i < 5; i++) {
[self addImageWithName:[NSString stringWithFormat:#"image%i.jpg",i] atPosition:i];
}
// add the first image (image1) into the last position
[self addImageWithName:#"image1.jpg" atPosition:5];
scrollView.contentSize = CGSizeMake(1920, 416);
[scrollView scrollRectToVisible:CGRectMake(320,0,320,416) animated:NO];
}
- (void)addImageWithName:(NSString*)imageString atPosition:(int)position {
// add image to scroll view
UIImage *image = [UIImage imageNamed:imageString];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
imageView.frame = CGRectMake(position*320, 0, 320, 416);
[scrollView addSubview:imageView];
[imageView release];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender {
NSLog(#"%f",scrollView.contentOffset.x);
// The key is repositioning without animation
if (scrollView.contentOffset.x == 0) {
// user is scrolling to the left from image 1 to image 4
// reposition offset to show image 4 that is on the right in the scroll view
[scrollView scrollRectToVisible:CGRectMake(1280,0,320,416) animated:NO];
}
else if (scrollView.contentOffset.x == 1600) {
// user is scrolling to the right from image 4 to image 1
// reposition offset to show image 1 that is on the left in the scroll view
[scrollView scrollRectToVisible:CGRectMake(320,0,320,416) animated:NO];
}
}
- (void)dealloc {
[scrollView release];
[super dealloc];
}
#end