I cannot find a way to set the height of a NSProgressIndicator programmatically.
My try so far:
NSProgressIndicator *ind = [[NSProgressIndicator alloc] init];
[ind setStyle: NSProgressIndicatorBarStyle];
// Height does not change height of the actual indicator
[ind setFrame: NSMakeRect(0, 0, 100, 50)];
[ind setBounds: NSMakeRect(0, 0, 100, 50)];
//[ind setControlSize: 0]; does only make it smaller, not bigger
[view addSubview: ind];
I found NSProgressIndicatorBarStyle enumeration in the documentation, but I couldn't find a method to specify the thickness.
Here a screenshot describing my problem: (layer has a background of red for better understanding):
This also occurs when using the NSButton class. Is there a workaround for this?
in iOS You can't change the progress indicator height just changing its frame, due to framework restrictions. However you should be able to achieve the same result, playing with transform
_indicator.transform = CGAffineTransformMakeScale(1.0f, 0.6f);
EDIT: I just tried on Mac OS X
_indicator.layer.transform = CATransform3DMakeScale(1.0f, 0.6f, 0.0f);
and it doesn't work, so it is not like iOS, likely because of how it is implemented on Cocoa (like Ken suggested).
The only way I managed to change the height is using controlSize, but I don't think it will suit your needs (since it doesn't allow you to specify points).
[_indicator setControlSize:NSMiniControlSize]; // or NSSmallControlSize
You should be able to use an arbitrary frame by subclassing NSProgressIndicator, and overriding drawRect, at this point my recommendation would be to look around to find something that can be extended for your use, like this one
https://www.cocoacontrols.com/controls/lbprogressbar
in IB you can
select your NSProgressIndicator control
in the utilities view select the View Effects inspector
press + in Content Filters
select Lanczos Scale Transform filter
set the appropriate scale value in the Scale row
set the Aspect Ratio too if you need to change the height only
this can be added programmatically also, just google for it how to add Content Filters to NSView
Related
I'm trying to implement a custom slider in Cocoa with 5 values. See my demo project, which can be downloaded here: http://s000.tinyupload.com/index.php?file_id=07311576247413689572.
I've subclassed the NSSliderCell and implemented methods like drawKnob:(NSRect)knobRect and drawBarInside:(NSRect)cellFrame flipped:(BOOL)flipped etc.
I'm facing some issues:
I'm not able to position the knob correctly regarding to the background image. I know that I'm able to change the knob's frame, and I've tried doing some calculation to position the knob correctly, but I'm not able to make it work for my custom slider. Could someone please help me with this?
The height of my custom slider background is 41px. In the drawBarInside:(NSRect)cellFrame flipped:(BOOL)flipped I change the height of the frame to 41px as well, but the entire background is not visible. Why?
I've noticed that the included images (the background and knob) are flipped vertically. Why? Note that the border top is darker in the background compared to the bottom, but this is reversed when I draw the background.
I found a mistake in your calculation of the x position of the knob rectangle: You used the height of the image where you should have used the width.
The cell drawing is being clipped to the frame of the control. Maybe you could expand the control frame when your cell awakes.
You need to use the NSImage method drawInRect:fromRect:operation:fraction:respectFlipped:hints:, and pass YES for the respectFlipped: parameter. Apple's controls generally do use flipped coordinates.
Added: Expanding the frame in awakeFromNib doesn't seem to work, the frame gets set back. Here's something that does work. Instead of overriding drawBarInside:flipped:, add this override:
- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
NSRect controlFrame = [controlView frame];
float bgHeight = self.backgroundImage.size.height;
if (controlFrame.size.height < bgHeight)
{
controlFrame.size.height = bgHeight;
[controlView setFrame: controlFrame];
}
[self.backgroundImage
drawInRect: [controlView bounds]
fromRect: NSZeroRect
operation: NSCompositeSourceOver
fraction: 1.0
respectFlipped: YES
hints: NULL];
[self drawKnob];
}
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 having this odd issue with UIProgressView. This video will explain better than I can with words...
https://vimeo.com/45399884 password: stackoverflow
But basically, I have a UIProgressView that uses iOS5's new setProgress:animated method. I'm animating it but when it animates, the slider part of the control is being scaled from the view's bounds 0,0 to bounds.size.max,bounds.size.max. It animates from left to right properly (with one exception), but scales at the same time. So basically it looks like a diagonal slide.
This is every bit of my progress view code.
progressView = [[UIProgressView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 11)];
[self.view addSubview:progressView];
[progressView setProgressViewStyle:UIProgressViewStyleBar];
[progressView setProgress:refreshInterval animated:YES];
Any tips or advice is appreciated. Thanks.
The designated initializer for UIProgressView is -initWithProgressViewStyle:. You're not supposed to modify the height of a progress bar, and while the height of the bar-style progress bar is 11, there are probably some effects being initialized in -initWithProgressViewStyle: that you're missing since the default height for the control is 9.
The designated initializer for a UIProgressView appears to be -initWithProgressBarStyle:. Try creating it using that method.
I'm working on some drawing code. I have that portion working great.
I want to draw over an image, but I want to still be able to see the detail of the image, the black lines, etc.
What I am working on is making a transparent UIImageView that holds the image.
I'm not sure how to get this set up properly though.
Should this be added above the other UIImageView that I color on or below it?
Here's what I have so far:
- (void)viewDidLoad
{
[super viewDidLoad];
topImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 46, 320, 370)];
[topImageView setImage:[UIImage imageNamed:#"imagesmall.png"]];
topImageView.alpha = 1.0;
topImageView.layer.opacity = 1.0;
topImageView.layer.opaque = NO;
[self.view addSubview:topImageView];
[topImageView release];
}
Thoughts anyone?
Yes, you can draw views over other views. They are drawn in the order that they're added as subviews, unless you reorder them after that.
You may need to set the opaque property for some views (this is distinct from and overrides their layer opacity), and set their backgroundColor to nil. UIImageView seems to be transparent by default, as long as its image is; some other UIView subclasses are not.
So, just what is your overlay going to be? If you just need to display one image over another, what you have here seems to work already. If you need to draw some lines programmatically, you'll need to do this:
Create a subclass of UIView.
Implement its drawRect method to display the content you need.
When you add your custom view on top of the background image, make sure it is not opaque and has no backgroundColor.
A common problem here is to find that your foreground is working, but the background isn't being loaded properly. To make sure the background is there, set the alpha of the foreground view to 0.5. You won't want to do that in production, but it will allow you to verify that both views exist.
I create some buttons dynamically on my view and i decide their frames according to some of my JSON respone parameters. But i want to autoresize them when the device(dsimulator) rotates. I can easily do this on interface builder but can't do anything on dynamic ones. Can someone help?
EDIT
Here is a snipped of my code
if (button.tag==1) {
button.frame = CGRectMake(30.0f, yPosition, 200.0f, buttonHeight);
}
if (button.tag==2) {
button.frame = CGRectMake(280.0f, yPosition, 200.0f, buttonHeight);
}
if (button.tag==3) {
button.frame = CGRectMake(530.0f, yPosition, 200.0f, buttonHeight);
}
There is no problem when using Portraid mode but when it rotates to Landscape a big empty area stays on the right side of the screen. How can i fix this?(I mean, when i rotate, i want the buttons got to the center of the scren's width)
EDIT:
I played with autoresizing on Size Inspector(Xcode 4.3) with my xib file and it works great, but whatever i did i couldn't resize the dynamically created buttons after rotation. I tried almost all of AutoresizingMask enums of UIView but nothing changes. Can someone please help
You can define by code what was the expected behavior when the device is rotated.
You can take a look at: http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/uiview/uiview.html
and
http://developer.apple.com/library/ios/#documentation/uikit/reference/uiview_class/uiview/uiview.html#//apple_ref/c/tdef/UIViewAutoresizing
You need to set the button behavior when you add it like:
[button setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin];
The attributes you've set up in your interface builder file are the UIViewAutoresizing attributes.
Take a look at this documentation from Apple on the UIView class (which your button is a subclass of); look for the UIViewAutoresizing attribute. That's the one you'll want.
Update: Here's a snippet of code for an MKMapView that uses this ability:
mainMapView = [[MKMapView alloc] initWithFrame:CGRectMake(20, 239, 280, 122)];
[mainMapView setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin];
With UIViewAutoresizingFlexibleTopMargin, the map view moves down when the user answers the phone --- it fixes the map's position relative to the top of the screen.
Dig around in the documentation and you'll find the autoresizing mask that works best for your situation.