I'm using code to resize a UIImageView by reducing its width to .5 its original value.
The code is
- (void)viewDidLoad
{
[super viewDidLoad];
self.allisonHall.newWidth = .5;
self.allisonHall.frame = CGRectMake(self.allisonHall.frame.origin.x,
self.allisonHall.frame.origin.y,
self.allisonHall.frame.size.width*self.allisonHall.newWidth,
self.allisonHall.frame.size.height);
self.allisonHall.contentMode = UIViewContentModeLeft;
self.allisonHall.clipsToBounds = YES;
NSLog(#"%f",self.allisonHall.frame.size.width);
}
and the result of the NSLog is 140, .5*280 as expected.
However, in the view the UIImageView remains at its original width.
The UIImageView is linked as
#property (weak, nonatomic) IBOutlet XYZdiningHall *allisonHall;
within the view controller's .h file, where XYZdiningHall is a subclass of UIImageView
Should the UIImageView's frame be changing given this code or do I need to call another method to fire the change?
Do you need to use UIViewContentModeLeft? You can use UIViewContentModeScaleAspectFit or UIViewContentModeScaleAspectFill and the image will be redrawn (the aspect modes are related to the image view bounds, Left isn't).
Related
I am trying to make a vertical progress bar in iOS that can be placed as a UIView in interface builder, and given a progress bar view class. Here are my class files:
ProgressBar.h:
#interface ProgressBar : UIView
#property (nonatomic, retain) IBOutlet UIView *barView
-(void)setBarValue:(float)value;
#end
ProgressBar.m:
-(id)initWithCoder:(NSCoder *)aDecoder {
id s = [super initWithCoder:aDecoder];
if (s) {
self.backgroundColor = [UIColor clearColor];
}
return s;
}
-(void)setBarValue:(float)val {
[self.barView setBackgroudnColor:TURQUOISE];
CGRect frame = self.barView.frame;
frame.size.height = self.barview.frame.size.height * val;
[self.barView setFrame:frame];
}
The only constraint I have on the 'barView' inside the ProgressBar element is 'align bottom edges'. The setFrame method never seems to update the bar, and even at full height, the inner self.barView isn't the same height as the ProgressBar view. The properties are all correctly linked in the Storyboard.
Any ideas?
The key issue is that, if using autolayout, you should add your constraints for this subview in IB, too. (I assume you already added constraints for the ProgressView.) And you should not change the frame of barView, but rather change its constraints and then call setNeedsLayout. The easiest way will be to add leading/trailing/top constraints of zero and then create a final height constraint. You can then add an IBOutlet for that height constraint. You can then programmatically set the constant of that constraint (and if you're going to use a multiplicative factor, it should be the product of this factor and the overall progress view, not a factor of the bar, itself), and then call setNeedsLayout.
I have to create an effect like in the images but I don't know how to do it (and also don't know how to call this effect to search). You can see in the pictures, at first we have an image at the top of page. After that, when we scroll up, the image moves up while the content moves with higher speed to cover the image. Can you give me a link or a suggestion?
First of all take imageview and scrollview in your apps with IBOutlet.
In your YourViewController.h file
#property(nonatomic,retain) IBOutlet UIImageView *imagev;
#property(nonatomic,retain) IBOutlet UIScrollView *scr;
In your YourViewController.m file
- (void)viewDidLoad
{
scr.contentSize = CGSizeMake(320,850);
scr.decelerationRate = UIScrollViewDecelerationRateNormal;
[super viewDidLoad];
}
Set imagev frame according to scrolling in scrollview delegate.
pragma mark - ScrollView Delegate
-(void)scrollViewDidScroll:(UIScrollView *)callerScrollView
{
NSLog(#"%f",callerScrollView.contentOffset.y);
[imagev setFrame:CGRectMake(imagev.frame.origin.x, - 0.5 *callerScrollView.contentOffset.y, imagev.frame.size.width, imagev.frame.size.height)];
}
Output :
I have a custom view class which inherits from UIView. This class has an UILabel as its subview. In the init-function of this custom view class I set up everything needed like this:
//h-file
#import <UIKit/UIKit.h>
#interface MyCustomView : UIView
#property (strong, nonatomic) UILabel *myLabel;
#end
//m-file
#implementation MyCustomView
#synthesize myLabel = _myLabel;
- (id)init
{
self = [super init];
if (self) {
_myLabel = [UILabel new];
if(_textView){
_myLabel.highlightedTextColor = [UIColor whiteColor];
_myLabel.translatesAutoresizingMaskIntoConstraints = NO;
_myLabel.lineBreakMode = NSLineBreakByWordWrapping;
_myLabel.numberOfLines = 0;
_myLabel.backgroundColor = [UIColor clearColor];
[self addSubview:_myLabel];
}
}
return self;
}
#end
I also set up a bunch of constraints to manage padding inside my custom view - furthermore there are constraints to layout multiple MyCustomView-instances for both vertical and horizontal axis as well.
To get a multilined label output I have to set the preferredMaxLayoutWidth-property of the UILabel myLabel. The width depends on the free space available. At http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html I read, that I can let Auto Layout calculate the width first and set it as preferredMaxLayoutWidth after the frame of the MyCustomView-instance (the label inside is single lined at this moment) has been set.
If I put the following function into the MyCustomView, the label still has a single line of text:
- (void)layoutSubviews
{
[super layoutSubviews];
float width = _myLabel.frame.size.width;
_myLabel.preferredMaxLayoutWidth = width;
[super layoutSubviews];
}
If I set the preferredMaxLayoutWidth to an explicit value inside the init-function, the label is multilined.
Does anybody know what I am doing wrong here?
Thanks in advance!
Without seeing all the constrains you have setup for your custom view, and the superview that contains it, it's really hard to determine the problem, I suggest you to print out all the view frames of the entire view hierarchy starting from the view controller's view at viewDidLayoutSubviews and determine if the label and its superviews have correct frame set.
I have an encountered similar issues with dynamic label size and scroll view so I created a prototype here, might be useful to you too: https://github.com/briandotnet/AutoLayoutScrollViewExperiment
I am currently trying to program a game with a HP gauge represented by an UIImageView placed on a .xib file. I declared my IBOutlet as follows:
#property (weak, nonatomic) IBOutlet UIImageView *hpGaugeView;
and synthesized accordingly. It is also linked to the UIImageView instance in the xib.
In the xib, I set the length of hpGaugeView to 188 and height to 9.
Now this is what I did in viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[hpGaugeView setFrame:CGRectMake(49, 18, 123, 9)];
NSLog(#"%f, %f", [hpGaugeView frame].size.width, [hpGaugeView frame].size.height);
}
Although NSLog tells me the hpGaugeView's width is 123, when I run it the length appears unchanged compared to the one in xib. All the other setFrame: or setBound: worked fine in other viewControllers, so I'm just wondering what's happening here.
It is a small but crucial problem that is bugging me for a few hours straight...
Edit:
When I turn off AutoLayout, the resizing worked; it creates a bunch of other problems though...
With autolayout on, the subviews have not been laid during the viewDidLoad. The constraints are calculated a bit later and you can override the viewDidLayoutSubviews method to set your frame:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
// Do any additional setup after subviews are laid.
[hpGaugeView setFrame:CGRectMake(49, 18, 123, 9)];
NSLog(#"%f, %f", [hpGaugeView frame].size.width, [hpGaugeView frame].size.height);
}
From the class reference:
viewDidLayoutSubviews
Notifies the view controller that its view just laid out its subviews.
I believe the problem is that you're not changing the frame of the UIImageView. The bounds refer to the position and size of the view in it's own coordinate system whereas the frame refers to the position and size in it's superview coordinate system.
If the clipsToBounds property is set yo YES, then nothing outside the frame of your view will be visible.
It turns out it is some weird weird interaction between the nib and the code...when I created the UIImageView programmatically it worked fine.
AutoLayout property worked only above IOS 6.0 only . Dragging of control to XIB instead of you can create the UIImageView through Code and add to current view. I have given the code for adding UIImageView programmatically.
Source Code:
// .h file
#property (weak, nonatomic) UIImageView *hpGaugeView;
//.m file
- (void)viewDidLoad
{
[super viewDidLoad];
hpGaugeView = [[UIImageView alloc] init];
[hpGaugeView setFrame:CGRectMake(49, 18, 123, 9)];
[self.view addSubview:hpGaugeView];
}
Initialize and add the hpGaugeView to subview inside the viewDidLoad function through programmatically.
I have a ViewController Container that is 400 high on the iphone5. When I use it on a iphone4 it squashes the view like it does to everything. In this case I want the view to appear the same size on all phones.
vc.h
#property (strong, nonatomic) IBOutlet UIView *viewForContainer;
vc.m
#synthesize viewForContainer
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect rect = [viewForContainer frame];
rect.size.height = 400;
[viewForContainer setFrame:rect];
}
Why can't I just force the height like this?
.. am I going to have to make a new storyboard for it?
Short answer:
Select the view and choose Editor > Pin > Height. Now get rid of the unnecessary bottom constraint.
Long answer:
You really should stop everything you're doing and understand what you're doing - in particular, about autolayout. It's everywhere, by default, whether we like it or not, so one may as well know about it.