I am using a UIRefreshControl in my UITableViewController to refresh the content. I use the following code in my -viewDidLoad method to add it to my table.
UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
//[refresh setAttributedTitle:[[NSAttributedString alloc] initWithString:#"Reloading" attributes:#{NSForegroundColorAttributeName : [UIColor lightGrayColor]}]];
[refresh setTintAdjustmentMode:UIViewTintAdjustmentModeNormal];
[refresh setTintColor:[UIColor colorFromHex:0xff8900]];
[refresh addTarget:self action:#selector(refresh) forControlEvents:UIControlEventValueChanged];
[[refresh layer] setZPosition:-1.0f];
//if (iOS_AT_LEAST(10)) {
// [self setRefreshControl:refresh];
//} else {
[self setRefresher:refresh];
[[self tableView] insertSubview:[self refresher] atIndex:0];
//}
I created a category for UIColor so it can accept hex values. I use this in the complete application and on another location I get #ff8900 back which is correct. But setting the tint color on the UIRefreshControl gives me #fb6a2e which is odd. The same happens when I try a default color, for example [UIColor lightGrayColor] gives me another tint than giving the same color to another view.
I have found the following post: UIRefreshControl tint color doesn't match given color. I tried to put it into an animation block and the hack given in the answer, but with no luck.
What do I do wrong here?
Another side question. When setting the attributed title, the spinner has a greater space from the top. If this happens, the title will be below the cell if only one is available. Is there a way to move the string up?
Related
So in my app I have a popover control with an embedded navigation control. In different parts of the navigation stack, I want the popover to be different colors depending on where the user is. The weird thing is sometimes setting the popover background color makes this terrible looking box around it, sometimes it doesn't. It looks like this:
This is the look I am trying to get:
It seems if I change the background color before displaying the popover it seems to work and transition correctly, but if I don't set the popover color before showing it, then change it after it has been shown it has the box effect. I've also noticed other cases where it seems to happen randomly, but I can't really explain what is causing it (my real app is much more complex than this demo). Here is the relevant code:
- (IBAction)buttonPressed:(id)sender {
UIViewController *vc = [[UIViewController alloc] init];
UIButton *b = [[UIButton alloc] init];
[b addTarget:self action:#selector(innerButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[b setTitle:#"Button" forState:UIControlStateNormal];
[b setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[b setFrame:CGRectMake(0,0,100,100)];
[vc.view addSubview:b];
_innerNav = [[UINavigationController alloc] initWithRootViewController:vc];
_popOver = [[UIPopoverController alloc] initWithContentViewController:_innerNav];
//If this line is here, everything works fine
_popOver.backgroundColor = [UIColor yellowColor];
[_popOver presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
//If this line is here (and the above line is commented out), the transition will look wrong
//_popOver.backgroundColor = [UIColor yellowColor];
}
-(void)innerButtonPressed {
_controller = [[UIViewController alloc] init];
UIButton *b = [[UIButton alloc] init];
[b addTarget:self action:#selector(test) forControlEvents:UIControlEventTouchUpInside];
[b setTitle:#"Make Purple" forState:UIControlStateNormal];
[b setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[b setFrame:CGRectMake(0,0,200,200)];
[_controller.view addSubview:b];
[_popOver setBackgroundColor:[UIColor orangeColor]];
[_innerNav pushViewController:_controller animated:YES];
}
-(void)test{
_popOver.backgroundColor = [UIColor purpleColor];
}
Any idea what is causing this issue? And what steps to safely update the background color of a popover without ever getting into this state? I have a full project demonstrating the problem, I thought you could attach projects to questions but apparently you cannot. If someone wants it I can probably host it somewhere.
After looking at your sample project, Apple's "Popover Controllers in iOS" sample project, perusing Apple's Documentation, and trying a few different things I have come to the following observations:
The UIPopoverController only exhibits this odd behavior when it is presented without a valid value for the backgroundColor property. From this I am guessing that since UIPopoverController's backgroundColor property is nil by default it must use different drawing code than when the backgroundColor property is valid.
Triggering some sort of redraw (e.x. Setting popoverContentSize) will get the colored box overlay to go away (it looks like it clips a color layer).
Conclusion: For the time being I would set a backgroundColor prior to the UIPopoverController being presented and then update it as needed. If this is not an option try updating the UIPopoverController such that it redraws (As a note: I was not able to get this to look good and it seems hacky). Lastly, I would report it as a bug to apple.
I hope this helps.
UIPopoverController is now deprecated. I found a similar issue when updating it to use the new popoverPresentationController. In the past I was able to set the backgroundColor of UIPopoverController before presenting. The popover presentation controller also has a backgroundColor property but didn't work like it did before where I could assign it before presentation. To get it to work I had to assign it after it starts presenting for some reason:
contentViewController.modalPresentationStyle = UIModalPresentationPopover;
[[self presentViewController:contentViewController animated:YES completion:^{
// completion code
}];
contentViewController.popoverPresentationController.backgroundColor = [UIColor orangeColor];
For your particular scenario where you are changing the background color after presentation is finished I don't think you'd be able to do that by just changing the popoverPresentationController's backgroundColor. The only solution I can think of is to dismiss and re-present the popover without animating:
[self dismissViewControllerAnimated:NO completion:^{
contentViewController.modalPresentationStyle = UIModalPresentationPopover;
[[self presentViewController:contentViewController animated:NO completion:^{
// completion code
}];
contentViewController.popoverPresentationController.backgroundColor = [UIColor purpleColor];
}];
i'm trying to add a back button using a custom png file for the background, but every time i add the background using the storyboard it just become blue like this:
How can i add a background image on a UIbarbutton?
the back button look like this:
This is the standard behavior in iOS 7 for an image in a button. The image is rendered as a template image, with opaque areas colored the current tint color, and transparent areas, transparent. If you want to see the image, you need to create the image with imageWithRenderingMode: and pass UIImageRenderingModeAlwaysOriginal as the argument.
You will need to do it grammatically.
I have tried doing it in storyboard, and it looks like there is a really strange bug, that causes the developer to decide - either use text or use an image, not both....
- (void)viewDidLoad
{
[super viewDidLoad];
[self addButtonsToNavigationBar];
}
- (void)addButtonsToNavigationBar
{
UIButton *regularButton = [[UIButton alloc] initWithFrame: CGRectMake(0, 0, 100.0f, 30.0f)];
UIImage *historyButtonImage = [UIImage imageNamed:#"image_name.png"];
// can set the background color instead of setting an image.
[regularButton setBackgroundImage:historyButtonImage forState:UIControlStateNormal];
[regularButton setTitle:#"Some button name" forState:UIControlStateNormal];
[regularButton addTarget:self action:#selector(historyButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *navigationBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:regularButton];
self.navigationItem.leftBarButtonItem = navigationBarButtonItem;
}
Currently, I am trying to set the next/previous buttons on my keyboard toolbar to the new, sleek iOS 7 back button/forward buttons that get put in navigation controllers to go back. Here is what I am trying. How can I use the system bar button item instead of the boring static text?
[self setToolbar:[[UIToolbar alloc] initWithFrame:self.frame]];
[self.toolbar setBarStyle:UIBarStyleDefault];
[self.toolbar setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth)];
[self addSubview:self.toolbar];
[self setSegmentedControl:[[UISegmentedControl alloc] initWithItems:#[ NSLocalizedStringFromTable(#"Previous", #"BSKeyboardControls", #"Previous button title."),
NSLocalizedStringFromTable(#"Next", #"BSKeyboardControls", #"Next button title.") ]]];
Here is what it looks like now:
Here is what I want it to look like:
Any ideas on how to access those system items without actually using images? I know its the exact iOS 7 back bar button item, I just don't know how to access it in a tool bar. I've searched everywhere. If it helps, i'm using BSKeyboardControls.
EDIT: To make it look exactly like the second image, use the images provided by Joshua, and save them as back#2x.png, and forward#2x.png into your xcode proj. Use Chun's code, but make sure to call the method for getting the images like this: imageNamed:#"back", and not #"back#2x". You now have iOS 7 back and forward buttons :)
EDIT2: To get it to look exactly like the next/previous arrow buttons use the following customizations in the correct implementation methods:
[self.segmentedControl setWidth:50 forSegmentAtIndex:0];
[self.segmentedControl setWidth:38 forSegmentAtIndex:1];
negativeSeparator.width = -19;
EDIT3: The toolbar with the < > arrows comes by default with all UIWebViews, and it appears when you tap a textfield.
If anyone is interested in a sample project, let me know, and i'll upload a link!
EDIT4: As of May 24, 2014, BSKeyboardControls now has this functionality by default.
These are the images used in toolbar, e.g. the back and forward button images:
Use the icons shared by Joshua and then try with below piece of code and you will be good to go. I have not added the done button here.
UIImage *backImage = [[UIImage imageNamed:#"backImage"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *forwardImage = [[UIImage imageNamed:#"forward"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:#[backImage, forwardImage]];
[self.segmentedControl addTarget:self action:#selector(segmentedControlChangedState:) forControlEvents:UIControlEventValueChanged];
self.segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
self.segmentedControl.tintColor = [UIColor clearColor];
UIBarButtonItem *aSegmentedControlBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.segmentedControl];
[self setItems:#[aSegmentedControlBarButtonItem, self.flexibleSpace]];
1) Download latest files from: https://github.com/simonbs/BSKeyboardControls
2) Import the images for back/next buttons. These can be whatever you want and you can set the appropriate sizes so that they look good. Joshua has a good set. I have mine saved as "keyboardBack.png" and "keyboardForward.png"
3) In BSKeyboardControls.m, update initWithFields:fields. Here you can do some customization like setting the width of your back/next buttons. I removed the Done button here too to follow your screenshot but you can add it back.
- (id)initWithFields:(NSArray *)fields
{
if (self = [super initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)])
{
// Creates toolbar
[self setToolbar:[[UIToolbar alloc] initWithFrame:self.frame]];
[self.toolbar setBarStyle:UIBarStyleDefault];
[self.toolbar setAutoresizingMask:(UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth)];
[self addSubview:self.toolbar];
// Import images
UIImage *backImage = [[UIImage imageNamed:#"keyboardBack"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIImage *forwardImage = [[UIImage imageNamed:#"keyboardForward"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
// Create segmentedcontrol
self.segmentedControl = [[UISegmentedControl alloc] initWithItems:#[backImage, forwardImage]];
self.segmentedControl.tintColor = [UIColor clearColor];
// Set button widths
[self.segmentedControl setWidth:50 forSegmentAtIndex:0];
[self.segmentedControl setWidth:50 forSegmentAtIndex:1];
// Other BSKeyboardControls stuff
[self.segmentedControl addTarget:self action:#selector(segmentedControlValueChanged:) forControlEvents:UIControlEventValueChanged];
[self.segmentedControl setMomentary:YES];
[self.segmentedControl setEnabled:NO forSegmentAtIndex:BSKeyboardControlsDirectionPrevious];
[self.segmentedControl setEnabled:NO forSegmentAtIndex:BSKeyboardControlsDirectionNext];
[self setSegmentedControlItem:[[UIBarButtonItem alloc] initWithCustomView:self.segmentedControl]];
[self setVisibleControls:(BSKeyboardControlPreviousNext)];
[self setFields:fields];
}
return self;
}
4) The left padding on the toolbar is a bit too much, so you can fix it by adding a negative separator in toolbarItems: in BSKeyboardControls.m:
- (NSArray *)toolbarItems
{
NSMutableArray *items = [NSMutableArray arrayWithCapacity:3];
if (self.visibleControls & BSKeyboardControlPreviousNext)
{
UIBarButtonItem *negativeSeperator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil
action:nil];
negativeSeperator.width = -12;
[items addObject:negativeSeperator];
[items addObject:self.segmentedControlItem];
}
if (self.visibleControls & BSKeyboardControlDone)
{
[items addObject:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]];
[items addObject:self.doneButton];
}
return items;
}
Note: I probably don't have the button widths and paddings to the exact specs, but you can tweak it to your liking!
If you don't mind living on the edge you could use Apple's undocumented system items to achieve the iOS 7 look. Here are left and right bar button items.
[self setDoneButton:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:105 target:nil action:nil]];
[self setDoneButton:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:106 target:nil action:nil]];
Source: http://iphonedevwiki.net/index.php/UIBarButtonItem
You can use this great tool by #iftekhar and customise IQSegmentedNextPrevious according to your need for giving images instead of next previous button.
Using Xcode 7.3, you can also just enter a symbol as the title for the Bar Item. This works both in code and in Interface Builder:
Place your cursor where you want the symbol to appear (eg, title box in IB or within quotes in code).
In Xcode's menu, click Edit, then Emoji & Symbols. (Alternatively, press control-command-space to bring up the list of characters.)
In the search box, type less or greater.
Then, select the symbol you want.
The less-than and greater-than symbols are colored blue in the toolbar by default.
In code:
backButton.title = "<"
In IB:
Use this: https://github.com/simonbs/BSKeyboardControls
But it uses the segmented control which got flattened in iOS 7.
Edit:
Just change the text of the segments:
[self setSegmentedControl:[[UISegmentedControl alloc] initWithItems:#[#"<",#">") ]]];
This may not be the most elegant. (Not even sure this exact code compiles, but you see the point)
How can I change the (background) color of the signup button in ParsesPFLoginViewController`?
I have tried:
PFLogInViewController *logInViewController = [[PFLogInViewController alloc] init];
logInViewController.fields = PFLogInFieldsUsernameAndPassword | PFLogInFieldsLogInButton | PFLogInFieldsPasswordForgotten | PFLogInFieldsSignUpButton ;
logInViewController.logInView.signUpButton.backgroundColor = [UIColor redColor];
This is my result:
How can the color be set correctly?
Change the background image to nil, and then set the button's background color:
[logInViewController.logInView.signUpButton setBackgroundImage:nil
forState:UIControlStateNormal];
logInViewController.logInView.logInButton.backgroundColor = [UIColor redColor];
I've not been able to change the color of the button directly. Normally, I'd accomplish via setTintColor:. I was able to achieve the changed background color by actually changing the background image using the completion block, like this:
PFLogInViewController *login = [[PFLogInViewController alloc]init];
login.delegate = self;
[self presentViewController:login animated:YES completion:^{
[login.logInView.signUpButton setBackgroundImage:[UIImage imageNamed:#"restBtn#2x"] forState:UIControlStateNormal];
[login.logInView.signUpButton setBackgroundImage:[UIImage imageNamed:#"restBtn#2x"] forState:UIControlStateHighlighted];
}];
Just make sure you have included your desired red button image in your project somewhere so the name resolution works.
EDIT: As stated by Dmitry, it may be wise to configure the desired image for each UIButton control state that matters to you. Additionally, I had hoped I could pass a collection of UIControlStates, such as
[login.logInView.signUpButton setBackgroundImage:[UIImage imageNamed:#"restBtn#2x"] forState:UIControlStateHighlighted|UIControlStateNormal];
for a single button and image combo, but it didn't appear to work.
.
Hi,
I am wanting to clean up my viewDidLoad method as I it is growing in number of lines of code and it is getting messy.
Now my UI is build programmatically, because I want to learn that way of doing things.
So I read on this SO Post that I can set the UI items in a seperate -9void) method and then link to that void by using [self method]
Now when I use that way, it does not seem to work for me.
like, if I want to set the back ground color this will work:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor colorWithRed:0.0 green:0.2 blue:0.38 alpha:1.0];
}
but this does not:
- (void)viewDidLoad
{
[super viewDidLoad];
[self backgroundColor];
// Do any additional setup after loading the view.
}
-(void)backgroundColor
{
UIView *backgroundView = [[UIView alloc] init];
backgroundView.backgroundColor = [UIColor colorWithRed:0.0 green:0.2 blue:0.38 alpha:1.0];
}
Am I misunderstanding this??
Thanks in Advance:-)
I think you're misunderstanding the nature of views/view controllers.
In this line:
self.view.backgroundColor = [UIColor colorWithRed:0.0 green:0.2 blue:0.38 alpha:1.0];
self refers to the view controller you are loading, and view refers to the view that is owned by that view controller. So when you set self.view.backgroundColor, you are setting the background color for the view that will be presented by the view controller you are displaying. Therefore that works.
Your other method, on the other hand, doesn't do that:
UIView *backgroundView = [[UIView alloc] init];
That line creates an entirely new UIView instance, and sets its background color. This is a brand new view, and is NOT the same view which is referenced earlier by self.view.
If you really want to have a separate function that changes the background color for you, write it like this:
-(void) setBackgroundColor
{
self.view.backgroundColor = [UIColor colorWithRed:0.0 green:0.2 blue:0.38 alpha:1.0];
}
Then you're actually modifying the view that belongs to the view controller, and the change should actually display.
I would also suggest that this function isn't very useful; you're creating a function that encapsulates a single line of code that will never change. There's really not much point in making a function for that. A more useful implementation might be:
-(void) setBackgroundColor:(UIColor)newColor
{
self.view.backgroundColor = newColor;
}
To use this method, you would write the following line in your viewDidLoad method:
[self setBackgroundColor:[UIColor colorWithRed:0.0 green:0.2 blue:0.38 alpha:1.0]];
And then you could call setBackgroundColor again whenever you wanted, to change the background color to different values.
Your backgroundColor method in the second instance is just setting the background colour on some different UIView object that gets created and then leaked. (The method name is also not great -- its suggests a property getter, but doesn't actually get a property or return anything.)
The problem here is you method backgroundColour isn't declared before it's used. So there are 3 ways to get around this
Move your backgroundColor method above viewDidLoad
Declare the backgroundColour as a public method in the #interface
Create a private interface and declare backgroundColour
No.3 Example:
#interace MyViewController (private)
- (void)backgroundColor;
#end
Note if your interface is inherits from anything still write the private interface as above.
Also don't create a new view just perform [self.view setBackgroundColor:[UIColor redColor]];