Xcode storyboard with dynamic views - ios

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.

Related

Change height of view programmatically in uistackview

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

UIView animated changes with auto layout constraints

Say that I have a project which looks like the following:
There are two UIViews - one called yellowBox and the other called redBox. The auto layout constraints dictate that the yellowBox is 60 points from the top of the superview with 350 points leading and trailing spaces (i.e. to left and right of the view). The redBox has the same leading and trailing space constraints. There is a vertical space constraint between the two boxes of 0 to indicate that the bottom of the yellowBox should always be directly on top of the redBox.
When the user taps the Expand Yellow Box button, I would like the height of the yellowBox to increase and, as a result, the redBox moves down to continue satisfying the vertical space constraint (that the yellowBox is always on top of the redBox). Here is the animation code:
- (IBAction)expandYellowBox:(id)sender {
[UIView animateWithDuration:0.5
animations:^{
CGRect newFrame = self.yellowBox.frame;
newFrame.size.height += 50;
self.yellowBox.frame = newFrame;
}];
}
However, I have been unable to get this working properly. As you can see by the red icon, there is a problem with the constraints at the moment:
which is fair enough, as there's no way for auto layout to know the height of the boxes. However, I don't know how to resolve this issue in such a way that it will allow for the boxes to be resized and moved. For example, if I specify a height constraint on the yellowBox then that will prevent it from being resized. If I set the height constraint to be greater than or equal (to allow the yellowBox height to increase) then I get a different constraint error:
All constraints have been established using Xcode in the storyboard - none have been written in code.
Any help greatly appreciated.
EDIT: As it turns out, the yellowBox is growing when the button is clicked - it's just I couldn't tell because it appears behind the redBox. I only noticed after clicking it around four times and it started appearing out the bottom of the redBox. However, the same question still remains - how to get the redBox to always stick to the bottom of the yellowBox.
Try it as mentioned by shwet-solanki, but add the following line after changing the constraint:
[self.view layoutIfNeeded];
the IBAction would look like:
- (IBAction)expandYellowBox:(id)sender {
[UIView animateWithDuration:0.5
animations:^{
self.yellowBoxHeightConstraint.constant += 50;
[self.view layoutIfNeeded];
}];
}
Where yellowBoxHeightConstraint is the IBOutlet for height constraint of yellowBox.
Hope this helps.
Add Height constraint to both the views
Create an IBOutlet for height constraint of yellowbox
Now instead of changing the height of yellowbox in the button pressed event, rather change the value of the height constraint. i.e suppose your IBOutlet constraint name is yellowBoxHeightConstraint, then yellowBoxHeightConstraint.constant += 50;
Hope this works for you.
//
// WPViewController.h
// AutoLayoutTEst
//
// Created by VASANTH K on 09/01/14.
//
//
#import <UIKit/UIKit.h>
#interface WPViewController : UIViewController
#property (strong, nonatomic) IBOutlet UIButton *button1;
- (IBAction)buttClicked:(id)sender;
#property (strong, nonatomic) IBOutlet NSLayoutConstraint *heightConstrain;
#property (strong, nonatomic) IBOutlet UIButton *button2;
#end
click Event
- (IBAction)buttClicked:(id)sender {
self.heightConstrain.constant=100;
}
here u need to set the heightConstrain for the Yellow button then create reference outlet for that button then update the heightConstrain to update the size of that button it will automatically move your Red button down.
https://github.com/vasanth3008/AutoLayoutHeighDemo
refer my sample demo project

Xcode 5, how to use autolayout with orientation, in the shown scenario?

I'm struggling with AutoLayout, to arrange two buttons as shown below.
I've watched the initial 2012 WWDC video and the Xcode-5 WWDC update video.
Also various other videos and tutorials.
I'm having trouble describing the issue so I've produced an image to show the problem.
I can align simple layouts, like two buttons at the bottom of the screen and I've tried adding a container then adding the buttons to that.
I'm beginning to think this might not be possible.
Can someone advise?
The following seem like common behaviors that we might ask Auto Layout to perform:
move the top half of a layout in portrait to the left half in landscape
and, move the bottom half of a layout in portrait to the right half in landscape
Here's how I would do it. I would create two content views for the two halves of the layout. Although the content views would be created in IB, all of their constraints would merely be placeholders and removed at runtime (by checking a box in each constraint's Attributes inspector). In order to create placeholder constraints, however, you need to create constraints explicitly in IB. In code, the constraints for the content views are created dynamically in response to device rotation.
The advantage to this approach is that you can layout the subviews for the content views in IB and not have to worry about orientation. The configuration of the content views' constraints could be abstracted out into a UIViewController base class.
Here's a screenshot of the content views without any subviews. The root view is white and can be seen peaking behind the status bar.
Here's the code for configuring the content views' constraints:
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UIView *topContentView; // moves to the left half in landscape
#property (weak, nonatomic) IBOutlet UIView *bottomContentView; // moves to the right half in landscape
#property (nonatomic, strong) NSArray *constraintsForContentViews;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.constraintsForContentViews = #[];
[self configureConstraintsForContentViewsForInterfaceOrientation:UIInterfaceOrientationPortrait];
}
// instead of creating this helper method, this code could be placed in the view controller's updateViewConstraints method
- (void)configureConstraintsForContentViewsForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
UIView *topView = self.topContentView;
UIView *bottomView = self.bottomContentView;
UIView *leftView = self.topContentView; // unnecessary but improves readibility of visual format
UIView *rightView = self.bottomContentView; // unnecessary but improves readibility of visual format
id topGuide = self.topLayoutGuide;
id bottomGuide = self.bottomLayoutGuide;
NSArray *visualFormats = nil;
// remove prior constraints
[self.view removeConstraints:self.constraintsForContentViews];
self.constraintsForContentViews = #[];
// build visual formats for orientation
if (UIInterfaceOrientationIsPortrait(orientation)) {
// portrait
visualFormats = #[#"H:|[topView]|", #"H:|[bottomView]|", #"V:[topGuide][topView(bottomView)][bottomView(topView)][bottomGuide]"];
} else {
// landscape: topView becomes leftView by name only, bottomView becomes rightView by name only
visualFormats = #[#"H:|[leftView(rightView)][rightView(leftView)]|", #"V:[topGuide][leftView][bottomGuide]", #"V:[topGuide][rightView][bottomGuide]"];
}
// install new constraints
for (NSString *format in visualFormats) {
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:0 views:NSDictionaryOfVariableBindings(topView, bottomView, leftView, rightView, topGuide, bottomGuide)];
[self.view addConstraints:constraints];
self.constraintsForContentViews = [self.constraintsForContentViews arrayByAddingObjectsFromArray:constraints];
}
}
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
[self configureConstraintsForContentViewsForInterfaceOrientation:toInterfaceOrientation];
}
#end
One thing I've been doing is, on your "left pane", add top and left constraints, then height and width. On the "right pane", add bottom and right constraints, height and width.
Then on - willRotateToInterfaceOrientation:duration: you can adjust each constraint's constant to make the sizes exactly what you want.

UIScrollView in Interface Builder not working

I originally had a normal view with a bunch of stuff in it, and I want that view to be an UIScrollView, so I created a new ScrollView and dragged everything over. The view is not scrolling.
After looking around - I unchecked use autolayout, but that didn't work. I also realize that this could be solved by setting contentSize, but I have access to this view through a variable that is of type UIView, and not UIScrollView. In other words I would be doing -
self.someController.view.contentSize = //something
where self.someController.view is only an UIView and contentSize is not a property of UIView(or at least that's what I'm seeing- I get compiler warnings).
Why is this scroll view not scrolling?
EDIT -
So I stupidly forgot I can cast - I did that, but it's still not working -
UIScrollView* basicCardView = ((UIScrollView *)self.detailController.view);
basicCardView.contentSize = CGSizeMake(basicCardView.frame.size.width * 12,
basicCardView.frame.size.height);
You need to connect your scrollview to Iboutlet var in .m .
Create var in your interface:
IBOutlet UIScrollView *scrollview;
And connect to your scrollview in storyboard, then you can set contentsize.
[scrollview setContentSize:CGSizeMake(2000,200)];
Elto has it correct. To elaborate: In your view controller .m say it's called MyViewController:
#interface MyViewController ()
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
#end
Go back to storyboard, select your view controller and select the connections tab (last one on the upper right). You should now see an outlet called scrollView. Drag a connection from that outlet to the scroll view that you added to the scene.
Now the content size code can be written. Just to get it working, use large constants in content size, like:
self.scrollView.contentSize = CGSizeMake(1000, 1000);
The size you're setting in the post (on the wrong view) looks like it's just the size of one of the subviews. You want the content size of the scroll view to be more like a multiple of the scrollView's size. You want the rectangle it can scroll within to at least encompass the frame (not the bounds) of every subview it contains.

UISearchBar covered by section header

I have a searchBar showing as part of the tableViewHeader as created in the storyboard. However I would like to hide it under some circumstances. To accomplish this, I set the tableHeaderView.frame to a height of 0. To show it again, I set the tableHeaderView.frame to its original height. When it does show it is covered by the first section header(s). Pulling down moves the search bar along with the section header.
I tried [self.searchBar sizeToFit] after it is shown without any success. I also tried [self.view layoutSubviews].
How do I keep the section title from covering the search bar? (iOS 6 and iOS 7)
Instead of hiding it by setting its height to zero, you can set the table's content offset to the search bar height. This makes it basically scroll up out of view.
Something like this:
#property (nonatomic, weak) IBOutlet UISearchBar* searchBar;
#property (nonatomic, weak) IBOutlet UITableView* table;
...
- (void) hideSearchBar
{
self.table.contentOffset = CGPointMake( 0, self.searchBar.frame.size.height );
}

Resources