here is my code but it covering my total slider frame i want to change only the slider icon it is not working
[mySlider setThumbImage: [UIImage imageNamed:#"slider.png"]forState:UIControlStateNormal];
mySlider.minimumValue = 2000;
mySlider.maximumValue = 4000;
mySlider.continuous = NO;
[mySlider addTarget:self action:#selector(sliderChanged:)
forControlEvents:UIControlEventValueChanged];
You need to set the initial thumb image using setThumbImage forState. This works fine for me in iOS 10 and returns the correct width of the image. The slider is setup in a storyboard and connected via an IBOutlet.
Looking at the properties that UISlider provides, you can get a pretty strong sense that while the class is designed to let you customize it's appearance, dynamically changing the appearance of the control as the user adjusts it probably wasn't what the designer had in mind. Otherwise, they'd have included the sort of mechanism you suggest: a means to associate different images with ranges of values.
self.thumbImage = [self imageWithImage:[UIImage imageNamed:#"IconForSlider.png"] scaledToSize:CGSizeMake(frame.size.height, frame.size.height)];
size = self.thumbImage.size.height;
[self setThumbImage:[self imageRotatedByDegrees:0] forState:UIControlStateNormal];
[self addTarget:self action:#selector(changeValue) forControlEvents:UIControlEventValueChanged];
Related
I am experimenting with a block-breaking iOS app to learn more about UI features. Currently, I am having issues trying to make it work for screen rotation.
I am able to get the blocks to re-arrange properly after screen rotation but am having trouble with getting the UIImageView for the paddle re-arrange.
My code is split as follows, VC calls initializes an object of the BlockModel class. This object stores a CGRect property (which is the CGRect corresponding to the paddle's ImageView).
The VC then creates an imageView initialized with the paddle image, sets the autoresinging property on the image view (to have flexible external masks), sets the frame based on the CGRect in the model object and adds the imageView as a sub-view of the main view being handled by the VC.
The code is below.
When I rotate, I am seeing that the ImageView is not being automatically repositioned.
If I do all the image view and CGRect creation in the vC, then it works (code sample 2).
Is this expected behavior? If yes, why is autoresizing not kicking in if the CGRect is obtained from a property in another object?
Full Xcode project code is here (github link)
EDIT
Looks like things don't work if I store the imageView as a property. I was doing this to have quick access to it. Why doesn't it work if imageView is stored as a property?
Code where model is initialized
self.myModel = [[BlockerModel alloc] initWithScreenWidth:self.view.bounds.size.width andHeight:self.view.bounds.size.height];
Model initialization code
-(instancetype) initWithScreenWidth:(CGFloat)width andHeight:(CGFloat)height
{
self = [super init];
if (self)
{
self.screenWidth = width;
self.screenHeight = height;
UIImage* paddleImage = [UIImage imageNamed:#"paddle.png"];
CGSize paddleSize = [paddleImage size];
self.paddleRect = CGRectMake((self.screenWidth-paddleSize.width)/2, (1 - PADDLE_BOTTOM_OFFSET)*self.screenHeight, paddleSize.width, paddleSize.height);
}
return self;
}
Code in VC where imageView is initialized
self.paddleView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"paddle"]];
self.paddleView.backgroundColor = [UIColor clearColor];
self.paddleView.opaque = NO;
self.paddleView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
NSLog(#"Paddle rect is %#",NSStringFromCGRect(self.myModel.paddleRect));
[self.paddleView setFrame:self.myModel.paddleRect];
[self.view addSubview:self.paddleView];
If I instead use this code in the VC to initialize imageView things work
UIImage* paddleImage = [UIImage imageNamed:#"paddle.png"];
CGSize paddleSize = [paddleImage size];
CGRect paddleRect = CGRectMake((self.view.bounds.size.width-paddleSize.width)/2, (1 - PADDLE_BOTTOM_OFFSET)*self.view.bounds.size.height, paddleSize.width, paddleSize.height);
UIImageView *paddleView = [[UIImageView alloc] initWithImage:paddleImage];
paddleView.backgroundColor = [UIColor clearColor];
paddleView.opaque = NO;
paddleView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin|UIViewAutoresizingFlexibleBottomMargin;
[paddleView setFrame:paddleRect];
[self.view addSubview:paddleView];
Found the issue. I was using the model object to handle all my "game object location" logic. E.g VC would calculate the X axis deltas from the touch events & forward them to the model object. Also, CADisplayLink events would be forwarded so that model can update ball location based on velocity and time since last event. It will then use updated location to detect collisions. This split was used because model class also had the methods to detect collisions with sides, paddle/ball etc.
The issue was that the model object was rewriting the CGRect of the paddleView by adding the delta it received from VC to the origin.x of current paddleRect it had stored. This paddleRect did not take into account the automatic adjustment to the CGRect that is done by auto-resizing after a rotation.
The fix was for the VC to set the CGRect of the paddleRect (set to paddleView frame) before calling the method in the model to update all the game properties and detect collisions. This way model only takes care of logic of collusion detection and updating ball movement and velocity based on it. The VC uses current paddleView location and hence automatically accounts for the automatic adjustment to the CGRect that is done by auto-resizing after a rotation.
Source code in github link updated.
On iOS 6 SDK I wrote the following lines of code to display an image inside a button:
NSURL *thumbURL2 = [NSURL URLWithString:#"http://example.com/thumbs/2.jpg"];
NSData *thumbData2 = [NSData dataWithContentsOfURL:thumbURL2];
UIImage *thumb2 = [UIImage imageWithData:thumbData2];
[btn2 setImage:thumb2 forState:UIControlStateNormal];
[self.view addSubview:btn2];
But now with Xcode 5 and iOS 7 this doesn't work. The button doesn't contain the image. The button is filled with blue color.
In iOS7 there is new button type called UIButtonTypeSystem NS_ENUM_AVAILABLE_IOS(7_0), // standard system button
Check your .xib file and change button type to Custom
To do this programmatically, add this line to the viewDidLoad:
[UIButton buttonWithType:UIButtonTypeSystem];
It seems iOS 7 is using the image provided just as an Alpha mask for displaying the button's tint color.
Changing the button type to UIButtonTypeCustom did the trick for me (thanks user716216!).
Setting the image as background doesn't always work if you already have a background image, as was my case.
Swift 3, 4, 5 :
let image = UIImage(named: "my-image")
myButton.setImage(image.withRenderingMode(.alwaysOriginal), for: .normal)
There's a good chance that the image is there and you just can't see it. Try changing the button's type to UIButtonTypeCustom. If that doesn't work, set the button's background color to [UIColor clearColor];
For swift:
let aButton = UIButton.buttonWithType(UIButtonType.Custom) as UIButton
The issue is the TintColor. By default, iOS throws a blue tint color over every button. You can get around it through 3 ways.
Change the tint color. [button setTintColor:[UIColor blackColor]];
This may color your image in ways you don't want it to.
As most other suggested, set the background image. [button setBackgroundImage:[UIImage...]];
Add an UIImageView to your button.
UIImageView * img = [[UIImageView alloc] initWithImage:[UIImage...]];
[button addSubView:img];
I had the same issue.
On my storyboard I had a button without any image.
I would then assign the image in the code.
IOS 7 came and I got a lot of blue images.
The resolution was simple yet confusing. If I assign any image on the storyboard and then change the image at run time it works fine.
You always must specify a starting image on the storyboard even if you are not going to use it.
This worked for me
[myButton1 setBackgroundImage:[UIImage imageNamed:#"phones.png"] forState:UIControlStateNormal];
Note:Remove front image before doing this.
Old thread, but I wanted to chime in because I just had the same problem. The issue was just that you are calling setImage when you should call setBackgroundImage.
In iOS 13 -- just set the Tint property to White, while keeping the type of the UIButton as Custom
None of the given solutions were working for me. If you do not set an initial image in Storyboard, you can still change the image of the button by using setBackgroundImage.
For your example, only a minor change is needed.
NSURL *thumbURL2 = [NSURL URLWithString:#"http://example.com/thumbs/2.jpg"];
NSData *thumbData2 = [NSData dataWithContentsOfURL:thumbURL2];
UIImage *thumb2 = [UIImage imageWithData:thumbData2];
[btn2 setBackgroundImage:thumb2 forState:UIControlStateNormal];
[self.view addSubview:btn2];
This Problem is called blue color problem of the button in xcode.
When we make button by code the button shows the blue tint color by default.This can be solved byt assigning tint color to black or white accordingly to your cell's color.
The code is :
UIImage *closebtnimg = [UIImage imageNamed:#"icon_uncheck.png"];
UIImage *closebtnimg1 = [UIImage imageNamed:#"icon_checked.png"];
Custombutton *button = [Custombutton buttonWithType:UIButtonTypeRoundedRect];
[button setFrame:CGRectMake(52, 66, 25, 24)];
[button setBackgroundImage:closebtnimg forState:UIControlStateNormal];
[button setBackgroundImage:closebtnimg1 forState:UIControlStateSelected];
[button setTintColor:[UIColor whiteColor]];
[cell.contentView addSubview:button];
[button addTarget:self action:#selector(changeImage:) forControlEvents:UIControlEventTouchUpInside];
Using Xcode 9.2 none of the above solutions worked for what I was looking for.
I was looking for a solution that will let me set .normal and .selected UIControlState images inside the storyboard for their original rendering mode, but, inside the Swift file, no string literals should exist regarding the image names.
Basically, inside your code you will get the image you set inside your storyboard for .normal state and re-render it as .alwaysOriginal (Same for .selected state), then, you will set that image (which is now rendered as original and won't be affected by the tint) for the relevant state (.normal and .selected) of your UIButton.
Here it is:
// Get your .normal image (you set via your storyboard) and render it as original
let unselectedImage = yourButton.image(for: .normal)?.withRenderingMode(.alwaysOriginal)
// Set your normal image but this time rendered as original
yourButton.setImage(unselectedImage, for: .normal)
// Same for selected state
let selectedImage = yourButton.image(for: .selected)?.withRenderingMode(.alwaysOriginal)
yourButton.setImage(selectedImage, for: .selected)
This way you can set your button image states and if the image name will change, it won't affect your code.
making the tint color as clearcolor for all the four states(Default,Highlighted,selected,disabled) worked for me.
In Swift 4, initialize your UIButton and assign uyour image Data as follows:
let myButton = UIButton(type: .cutsom)
myButton.setImage(UIImage(data:myImageData), for: .normal)
In app my, if you tap on a certain area a UIPopoverController appears with UIButtons that perform certain tasks when clicked. The UIButtons (called CableDisconnectButton) are a subclassed UIButton so I could add two additional properties to them. I also add UILabels to go over the buttons
However, the background images of the buttons are invisible or don't appear until I tap on the screen somewhere. The UIlabels show up fine, but not the buttons. It can be a tap on the UIPopoverController or anywhere else on the screen. Once I've tapped that first time, the buttons will be there until the app is closed. So, this only happens right after launch and up until I first open that UIPopover. I tap plenty of times before opening the popover.
The functionality of the buttons and everything else works fine, but the background images are hidden on that first launch and I have no idea why.
Here's how I create the buttons and UILabel:
//create custom button
CableDisconnectButton *removeConnectionButton = [CableDisconnectButton buttonWithType:UIButtonTypeCustom];
removeConnectionButton.frame = CGRectMake(x, y, 190, 80);
removeConnectionButton.backgroundColor = [UIColor clearColor];
[removeConnectionButton setBackgroundImage:[UIImage imageNamed:#"images/cable_disconnect_button.png"] forState:UIControlStateNormal];
[removeConnectionButton setBackgroundImage:[UIImage imageNamed:#"images/cable_disconnect_button_over.png"] forState:UIControlStateHighlighted];
//set input and output jacks to button properties
removeConnectionButton.inputJack = inputJack;
removeConnectionButton.outputJack = self.outputJackView;
//add action to button
[removeConnectionButton addTarget:self action:#selector(removeConnectionButtonTarget:) forControlEvents:UIControlEventTouchUpInside];
//create label for output
UILabel *outputConnectionLabel = [[UILabel alloc] initWithFrame:CGRectMake(x+18, y+5, 180, 22)];
outputConnectionLabel.backgroundColor = [UIColor clearColor];
outputConnectionLabel.textColor = [UIColor whiteColor];
outputConnectionLabel.text = self.outputJackView.jackDisplayName;
outputConnectionLabel.font = [UIFont systemFontOfSize:16];
//add subviews
[self addSubview:removeConnectionButton];
[self addSubview:outputConnectionLabel];
I've tried to add a regular, non-custom UIButton and it appears without the tap. I suspect it may have something to do with the subclassed UIButton, but I'm not sure why. The extra properties added to the UIButton are strings that are crucial to the functionality of the and can't be omitted.
After beating my head off the desk for days, I ran into the "Clean Build Folder" option. I've cleaned the project plenty of times, but wasn't aware of "Clean Build Folder". To execute this, simple hold the Option key, click Product from the menu and select Clean Build Folder.
So, if your app isn't behaving the way it should and it makes no sense AT ALL, try this.
I can't seem to change the size of UIStepper:
In IB, the Width and Height boxes are grayed out.
I used initWithFrame:
UIStepper *stepper = [[UIStepper alloc] initWithFrame:CGRectMake(300, 638, 120, 80)];
But it does not change the size. Several posts on SO seemed to implied it is changeable. Any suggestion?
UIStepper* s = [UIStepper alloc] init];
s.transform = CGAffineTransformMakeScale(0.75, 0.75);
You can properly update the UIStepper size without transformation.
Use the following method to set the background image and the stepper will draw itself using the background size:
- (void)setBackgroundImage:(UIImage*)image forState:(UIControlState)state
Example
[self.stepper1 setIncrementImage:[UIImage imageNamed:#"plusIcon1.png"] forState:UIControlStateNormal];
[self.stepper1 setDecrementImage:[UIImage imageNamed:#"minusIcon1.png"] forState:UIControlStateNormal];
[self.stepper1 setBackgroundImage:[UIImage imageNamed:#"stepperBkg1.png"] forState:UIControlStateNormal];
[self.stepper1 setBackgroundImage:[UIImage imageNamed:#"stepperBkgHighlighted1.png"] forState:UIControlStateHighlighted];
[self.stepper1 setBackgroundImage:[UIImage imageNamed:#"stepperBkgDisabled1.png"] forState:UIControlStateDisabled];
This yields the following result on the left, compared to an unmodified stepper on the right:
stepperBkg1#2x.png:
stepperBkgHighlighted1#2x.png:
I tried the transform on my stepper - it did change the appearance and did scale it, however, the images of the + and - were stretched (so you have to scale in proportion to the original stepper.
Also, be careful because the area of touch that actually increments and decrements, does change - so on the stretched image, the button would not decrement along the entire view - so this is probably not a good solution....
from the doc:
The bounding rectangle for a stepper matches that of a UISwitch object.
Doesn't sound, like it is possible upfront.
Also in this blog post:
// Frame defines location, size values are ignored
UIStepper *stepper = [[UIStepper alloc] initWithFrame:CGRectMake(120, 20, 0, 0)];
But you can try to transform it's layer.
You can provably scale it:
stepper.transform = CGAffineTransformMakeScale(1.75, 1.0);
I've made a small custom UIStepper class for it. No images needed, no transformation needed. Images generated automatically.
https://github.com/alelipona/VZCustomSizeStepper
Yes, you can change size of stepper.
first, right click on storyboard --> select (open as)--> Select (Source Code)
then find stepper in the code--> find width=??? and change.
then click on storyboard again and select open as interface builder.
I'm trying to change the background color of a button when it's selected and don't want to use an image.
[mBtn setBackgroundColor:[UIColor grayColor] forState:UIControlStateHighlighted];
Any thoughts?
I'm replying to this old thread because it pops up consistently in searches for a solution to this problem and I have seen no solution elsewhere. It is truly annoying that setTintColor only applies to the highlighted state of a UIButton. Six months ago, it was equally annoying that it applied only to iOS 5, but that will hopefully be less of an issue going forward. With that in mind, I've drawn upon and combined a number of community suggestions to composite a general purpose solution to tinting a group of buttons in their normal state.
The method below accepts an NSArray of UIButtons and a set of color specifications as input. It applies the color specifications to one button using setTintColor, renders the result to a UIImage, and applies that image as the background image of the entire set of buttons. This avoids the need to create discrete image files for button colors. Also, it does so using a stretchable image so that it may work with a collection of buttons of different sizes (though note that it assumes the default corner rounding factors of UIButton). I hope you'll find it useful for iOS 5 targets.
- (void) setColorOfButtons:(NSArray*)buttons red:(float)red green:(float)green blue:(float)blue alpha:(float)alpha {
if (buttons.count == 0) {
return;
}
// get the first button
NSEnumerator* buttonEnum = [buttons objectEnumerator];
UIButton* button = (UIButton*)[buttonEnum nextObject];
// set the button's highlight color
[button setTintColor:[UIColor colorWithRed:red/255.9999f green:green/255.9999f blue:blue/255.9999f alpha:alpha]];
// clear any existing background image
[button setBackgroundImage:nil forState:UIControlStateNormal];
// place the button into highlighted state with no title
BOOL wasHighlighted = button.highlighted;
NSString* savedTitle = [button titleForState:UIControlStateNormal];
[button setTitle:nil forState:UIControlStateNormal];
[button setHighlighted:YES];
// render the highlighted state of the button into an image
UIGraphicsBeginImageContext(button.layer.frame.size);
CGContextRef graphicsContext = UIGraphicsGetCurrentContext();
[button.layer renderInContext:graphicsContext];
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIImage* stretchableImage = [image stretchableImageWithLeftCapWidth:12 topCapHeight:0];
UIGraphicsEndImageContext();
// restore the button's state and title
[button setHighlighted:wasHighlighted];
[button setTitle:savedTitle forState:UIControlStateNormal];
// set background image of all buttons
do {
[button setBackgroundImage:stretchableImage forState:UIControlStateNormal];
} while (button = (UIButton*)[buttonEnum nextObject]);
}
[mBtn setTintColor:[UIColor grayColor]];
This only effects the highlighted state, so I believe that this is what you're looking for.
You can also set it from Interface Builder, from the Highlight Tint drop-down menu.
Just for people that will land here like I did when searching for changing background colors for highlighted state...
I ended up with an UIButton subclass that has a property for backgroundHighlightColor and tracks highlighting through KVO. Here's the link to GitHub: SOHighlightButton
You should be able to adapt it to any other scenario if you need more / other properties ot the UIButton to change if highlighted.
There is no method like this, setBackgroundColor: forState:
Check documentation. you need to use image.