I need to change the view height in the stack view when I press the test button, but it is not working properly.
When I press the test button, I want to set the height of view 3 to 50 and the height of view5 to fill the remaining area. When I press the test button again, i want to reverse to process. How can I do that?
Thank you.
As #SeanLintern88 mentioned, the way you really should be doing this is with auto layout constraints -- you don't want to be mixing setFrame with autolayout.
IBOutlet the height constraints for View 3 and View 5. Set the View 3 height constraint as inactive to start (if you want it to look like your storyboard does currently to start), then whenever the button is pressed, check which constraint is active and flip-flop them.
#import "ViewController.h"
#interface ViewController ()
#property (strong, nullable) IBOutlet NSLayoutConstraint *view3HeightConstraint;
#property (strong, nullable) IBOutlet NSLayoutConstraint *view5HeightConstraint;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// start us out as inactive
self.view3HeightConstraint.active = NO;
}
- (IBAction)btnPressed:(id)sender {
if (self.view5HeightConstraint.active) {
// view 5 height constraint is active
// you can set the height constants directly in storyboard as well
self.view3HeightConstraint.constant = 50.0f;
self.view3HeightConstraint.active = YES;
self.view5HeightConstraint.active = NO;
} else {
// view 3 is height constraint is active
// you can set the height constants directly in storyboard as well
self.view5HeightConstraint.constant = 50.0f;
self.view5HeightConstraint.active = YES;
self.view3HeightConstraint.active = NO;
}
// animate the layoutIfNeeded so we can get a smooth animation transition
[UIView animateWithDuration:1.0f animations:^{
[self.view layoutIfNeeded];
}];
}
#end
Related
I have a problem about Xcode storyboard and dynamically showed views.
I have 3 vertically aligned views in my storyboard and each one is linked with each other with top-bottom relationship with constraints
However during runtime I want to hide the 2nd view and replace its place with the 3'rd view (which is a tableview) and to fill the both 2nd and 3rd places I'm trying to extend the height of tableview.
However I cannot succeed. I have tried lots of things but closest thing I get is to transform the 3rd view to 2nd place but the height remains the same
My latest code is in below
if (status) {
self.filterView.hidden = NO;
self.contentTable.frame = contentTableFrame;
} else {
self.filterView.hidden = YES;
CGFloat predictedHeight = self.contentTable.frame.size.height+(self.contentTableFrame.origin.y-self.filterView.frame.origin.y);
self.contentTable.transform = CGAffineTransformMakeTranslation(0, self.filterView.frame.origin.y-self.contentTable.frame.origin.y);
for (NSLayoutConstraint *constraint in self.contentTable.constraints) {
if (constraint.firstAttribute == NSLayoutAttributeHeight) {
constraint.constant = predictedHeight;
}
}
}
You can also find the screenshot of the 3rd view's constraints. What should I do to fix that? Does anyone have any idea about it?
I also have another solution to this problem . But I've another problem on that too.
When I executed the below line of code my 3rd view move to 2nd view's place but its height remains the same so on the bottom of the page it happens to seems a blank space.
self.contentTable.transform = CGAffineTransformMakeTranslation(0, self.filterView.frame.origin.y-self.contentTable.frame.origin.y);
In order to fix that I've tried to change its height(with .frame = CGRectMake(.....) )
but it didn't work.Then I've tried to scale the 3rd view(which is a tableview) and it succeed but because I've scaled it all the cells inside the tableview scaled too and the visual appearance of the table has broken. So I couldn't able to find a solution to that problem.
It seemed like a challenge.
Thanks
Sorry it is in objective-c.
I get the top contraint from the TableView (Storyboard). When I hide the topView, I get the height of my topView and change the top constraint constant. You can see it in #IBAction. Finally, the tableView is stretched and takes the space left from the topView. Is that what you were looking ?
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UIView *topView;
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *topTableViewConstraint;
- (IBAction)pushTest:(id)sender;
#end
ViewController.m
- (IBAction)pushTest:(id)sender {
if (self.topView.hidden) {
self.topTableViewConstraint.constant = 0;
}else{
self.topTableViewConstraint.constant = -self.topView.bounds.size.height;
}
self.topView.hidden = !self.topView.hidden;
}
you can hide filterview but you can't replace it by tableview.
if you want to replace it by table view.You need to use method BringSubviewToFront for That Tableview.it will bring that tablview to front and set filterview to back which is hidden for ui.
I have two UIViews aligned vertically in Main view, there is business logic like if usertype A is logined need to show both views, If usertype B logined need to show top view only and hide that bottom view but topview should get total frame of bottom view aswell, Can anyone please suggest me how can implement with Autolayout ?.
You should define height constraint for your bottom view.
Main idea is to change that constraint for your purpose. Just create outlet for height in your code and set it constant to 0, when you need to hide it (optionally, set hidden property to YES, if you wish)
Storyboard steps:
Add leading, trailing, top and bottom constraints for top view
Add leading, trailing, height and bottom constraints for bottom view
Your constraints should look like:
Last step - drag outlet for height to your view controller in order to get access to change it's constant
Hope this helps
If your deployment target is iOS 9 or later, the easiest way to do this is to put the views in a UIStackView:
I put the two views (plus the toolbar) in a vertical stack view. I constrained each view's leading and trailing edges to the stack view, and constrained the top and bottom views to have equal heights. Then I set the priority of the equal-height constraint to 249 (a fairly low priority). If you don't want equal heights, you can set whatever height constraints you want for when both views are visible. Just set them to a low priority so the stack view can override them when only one view is showing.
Hiding and showing the views is easy, even with animation. It's this simple:
#interface ViewController ()
#property (strong, nonatomic) IBOutlet UIView *topView;
#property (strong, nonatomic) IBOutlet UIView *bottomView;
#end
#implementation ViewController
- (IBAction)hideTop:(id)sender {
[UIView animateWithDuration:0.3 animations:^{
self.topView.hidden = YES;
self.bottomView.hidden = NO;
}];
}
- (IBAction)hideBottom:(id)sender {
[UIView animateWithDuration:0.3 animations:^{
self.bottomView.hidden = YES;
self.topView.hidden = NO;
}];
}
- (IBAction)showAll:(id)sender {
[UIView animateWithDuration:0.3 animations:^{
self.topView.hidden = NO;
self.bottomView.hidden = NO;
}];
}
#end
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.
The above Image is captured from storyboard.
It is constructed like as follows:
UIView (include UILabel and UIProgressView) <--2px spacing --> UIActivityIndicatorView <---6px spacing ---> UIButton
I want the UIView to increase its width to button when UIActivityIndicatorView hidden as follows:
UIView( include UILabel and UIProgressView) <---6 space---> UIButton
How can I do that?? Let me Know. Please.
https://github.com/bilobatum/ActivityIndicatorDemo
Make the button's intrinsic content size along the horizontal axis required (i.e., priority 1000). This prevents the layout from being ambiguous along the horizontal axis.
#interface ViewController ()
#property (strong, nonatomic) IBOutlet NSLayoutConstraint *activityIndicatorWidthConstraint;
#property (strong, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
// spacerConstraint is the horizontal spacer constraint between the activity indicator and the gray view
#property (strong, nonatomic) IBOutlet NSLayoutConstraint *spacerConstraint;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.activityIndicator startAnimating];
}
- (IBAction)stopButtonTapped:(UIButton *)sender
{
sender.enabled = NO;
self.activityIndicatorWidthConstraint.constant = 0;
self.spacerConstraint.constant = 0;
[UIView animateWithDuration:1.0 animations:^{
self.activityIndicator.alpha = 0.0;
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
[self.activityIndicator stopAnimating];
//[NSLayoutConstraint reportAmbiguity:nil];
}];
}
#end
If you are using Auto-layout, consider setting the width of the UIActivityIndicatorView to 0 when you disable it. This won't be exactly what you need, but it's close.
Let's assume that your UILabel is called _label, UIProgressView is called _progressView and UIActivityIndicator is called _activityIndicator.
When you hide your _activityIndicator, call this block of code:
[_label setFrame:CGRectMake(_label.frame.origin.x, _label.frame.origin.y, _label.frame.size.width + _activityIndicator.frame.size.width + 2, _label.frame.size.height)];
[_progressView setFrame:CGRectMake(_progressView.frame.origin.x, _progressView.frame.origin.y, _progressView.frame.size.width + _activityIndicator.frame.size.width + 2, _progressView.frame.size.height)];
When _activityIndicator shows again:
[_label setFrame:CGRectMake(_label.frame.origin.x, _label.frame.origin.y, _label.frame.size.width - _activityIndicator.frame.size.width - 2, _label.frame.size.height)];
[_progressView setFrame:CGRectMake(_progressView.frame.origin.x, _progressView.frame.origin.y, _progressView.frame.size.width - _activityIndicator.frame.size.width - 2, _progressView.frame.size.height)];
Remember, that Autolayout should be turned off, if you want to manually set the frames! It is very simple: just uncheck the "Use Autolayout" feature in File Inspector:
I have a button set up in IB. I have an IBOutlet set up and the onscreen object linked to it. Is there a way to programmatically change that buttons position and/or size? I know you can change the title and some things but I don't see how to change it's position or size.
Now I would like to change the position of it accordingly. Is it possible? If yes, please let me know how, since I am trying to change the position of my button in the following code, but it does not work in the header file.
#property (nonatomic, strong) IBOutlet UIButton *mybuttonOutlet;
In the implementation file:
-(void)viewDidLoad {
screenSizeHeight=[UIScreen mainScreen].bounds.size.height;
if(screenSizeHeight==568)
mybuttonOutlet.frame= CGRect(38, 464 ,157,25);
if(screenSizeHeight==480)
mybuttonOutlet.frame= CGRect(38, 364 ,157,25);
}
Remove Use Autolayout from the button in IB or storyboard.
If you want to adjust positions with Autolayout enabled, you will have to change your code like this
-(void)viewDidLayoutSubviews {
screenSizeHeight=[UIScreen mainScreen].bounds.size.height;
if(screenSizeHeight==568)
mybuttonOutlet.frame= CGRect(38, 464 ,157,25);
if(screenSizeHeight==480)
mybuttonOutlet.frame= CGRect(38, 364 ,157,25);
}
Basically you need to perform any custom layout adjustments in viewDidLayoutSubviews method if Autolayout is enabled
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
#import "ViewController.h"
#interface ViewController ()
#property(nonatomic, strong) IBOutlet UIButton *theButton;
// -(IBAction)moveTheButton:(id)sender;
#end
#implementation ViewController
#synthesize theButton;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)moveTheButton:(id)sender{
//set default position
CGRect btFrame = theButton.frame;
btFrame.origin.x = 145;
btFrame.origin.y = 285;
theButton.frame = btFrame;
//position changing
btFrame.origin.x += 40;
theButton.frame = btFrame;
//new size of button
CGRect rect=CGRectMake(145, 285, 190, 30);
[self.theButton setBounds:rect];
}
#end
I eventually went for the constraints. Get an outlet of the constraints that determine the position of the button (top, bottom, leading, trailing) and change the constraint(s) value(s).
self.constBtnSubmitTrailing.constraint = 50.0
This so you can keep AutoLayout enabled.
The solution I figured out for this is to create new View object inside the main View, and put my "dynamically changing objects" inside that View (as shown in picture).
Object hierarchy
Then I use Auto-Layout to position the new View in the main View.
But bugButton:UIButton which is inside the new View, changes position as expected with:
bugButton.frame.origin = CGPoint(x: newX, y: newY)
Please perform this check.
-(void)viewDidLoad{
if(self.mybuttonOutlet==nil)NSLog(#"Button is NIL");
}
Now if you get the log "Button is NIL", then probably you forgot to link your IB button to your variable mybuttonOutlet.