Center the subview in UIView using constraints in IOS - ios

i have three subview like subview1,subview2,subview3 in a UIViewController inside a UIView.
I'm using constraints on them, the constraints which i'm using to show then in a center when the button is clicked are these,
Horizantally in Container,
Vertically in Container,
width and
height.
Issue :
When I run the app and click the button once it comes in the right position. But when i dismiss it and try again to open it, the subview change its position itself and comes on the top left of the UIViewcontroller ,
As you can see in a screen shot, but i want to show the view every time when i click the button in the center of the UIViewcontroller.
I'm confused that constraints are right but why it always changes its position when we open it again.
My code is ,
- (IBAction)Precord:(id)sender {
_DateView.hidden=NO;
[self.DateView bounceIntoView:self.view direction:DCAnimationDirectionLeft];
}
The contents in story board are like this ,
enter image description here

It depends on the way you are dismissing the View. I just tried below code and it worked for me
- (IBAction)btn_Tapped:(id)sender {
_smallView.hidden = false;
[_smallView bounceIntoView:self.view direction:DCAnimationDirectionLeft];
}
- (IBAction)hide_Tapped:(id)sender {
_smallView.hidden = true;
}
Basically i am just hiding the view. And when btn_Tapped, everytime the view is displaying with bouncing animation in the center. Let me know how you go!

try this
yourSubView.center = CGPointMake(yourMainView.frame.size.width / 2,
yourMainView.frame.size.height / 2);

Simple way to programmatically add constrains. Modify it with your desire size.
Notice 1: toItem: self, where self is just a view where u added the subView.
Notice 2: SubView MUST be added to self or a subView of self.
subView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: subView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: subView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1.0, constant: 0).isActive = true
NSLayoutConstraint(item: subView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 0.5, constant: 0).isActive = true
NSLayoutConstraint(item: subView, attribute: .width, relatedBy: .equal, toItem: self, attribute: .width, multiplier: 0.5, constant: 0).isActive = true
I would recommend adding constrains in Storyboard. Easier to see/read, clear code and error validator.
On your problem i would say it a animation problem. Just before adding your view run again the method that set the view frames/constrains (to reset the animation position modification).
Or just when animation is finish, instead of hiding the view, remove it from super view. And when u need it again, just add it again.

Related

Constraints Overlapping, Swift Xcode

I'm creating a custom keyboard in Xcode with swift. Everything runs great but I am running into a problem with constraints. Ill explain what I've done and what I am looking to do.
what I have done:1)I have created a 'world' button that will switch between the iOS default keyboard and the custom keyboard. It is constrained to the bottom left of the view, no matter what device it is loaded onto (iPhone 5,6,7 iPad etc). 2)I have then created a collection view that is constrained to start at the edge of the world button no matter the device. 3)I have created a delete button that is constrained to the bottom right of the view, no matter the device.
what I want to do: 1)I want the collection view to start at the world button and end at the delete button, no matter the device.
The trouble I am having is that the delete button overlaps the collection view on smaller devices. I want the collection view to stop at the delete button but cannot figure out why my constraints are not working.
These are the relevant constraints for the collection view.
// create the constraints
// leading constraint
let categoriesCollectionViewLeadingConstraint = NSLayoutConstraint(item: categoriesCollectionView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: backButton, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0)
// add the leading constraint
view.addConstraint(categoriesCollectionViewLeadingConstraint)
// bottom constraint
let categoriesCollectionViewBottomConstraint = NSLayoutConstraint(item: categoriesCollectionView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
// add the bottom constraint
view.addConstraint(categoriesCollectionViewBottomConstraint)
// trailing constraint
let categoriesCollectionViewTrailingConstraint = NSLayoutConstraint(item: categoriesCollectionView, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0)
// set the priority to less than 1000 so it works correctly
categoriesCollectionViewTrailingConstraint.priority = 999
// add the trailing constraint
view.addConstraint(categoriesCollectionViewTrailingConstraint)
I think you should constraint your collection view like this:
// trailing constraint
let categoriesCollectionViewTrailingConstraint = NSLayoutConstraint(item: categoriesCollectionView, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: - deleteButtonWidth)

Adding view from xib in front of other views

I'm trying to add a custom view from a xib in front of other views. However, for some reason it's never placed as the front view when theres a UITableView on screen. Here's my code:
noInternetView = NSBundle.mainBundle().loadNibNamed("NoInternetView", owner: self, options: nil)[0] as! NoInternetView
noInternetView.translatesAutoresizingMaskIntoConstraints = false
noInternetView.delegate = self
self.view.addSubview(noInternetView)
self.view.addConstraint(NSLayoutConstraint(item: noInternetView, attribute: .CenterX, relatedBy: .Equal, toItem: self.view, attribute: .CenterX, multiplier: 1, constant: 0))
self.view.addConstraint(NSLayoutConstraint(item: noInternetView, attribute: .CenterY, relatedBy: .Equal, toItem: self.view, attribute: .CenterY, multiplier: 1, constant: 0))
I place this at the bottom of my viewDidLoad() code. Why could this be?
noInternetView.hidden = true
your view is hidden, do it visible
noInternetView.hidden = false
self.view.bringSubviewToFront(noInternetView)
Try this it may help you.
First
Check is there a noInternetView have width and height constraints
Second
Add self.view.layoutIfNeeded() after self.view.addConstraint
this help to adjust autolayout you added
If you want your view to be on the top, add it to the window instead.

UIScrollView dynamic height content (autolayout) not filling whole space

I am creating a small chat app in which I use a custom subclass of UIScrollView to present the messages. This app is just for practicing so I don't want to use a third party library. I am implementing this UIScrollView via autolayout, after reading the technical note 2154 by Apple and several tutorials explaining this, and my implementation is almost working but the content view of my UIScrollView doesn't seem to fill all the space available.
The code which presents the ScrollView is:
public class ChatView: UIScrollView {
private var contentView: UIView
...
// This get called by all the init methods. contentView is already created ( contentView = UIView() )
private func setupViews() {
self.translatesAutoresizingMaskIntoConstraints = false
contentView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(contentView)
let constraint1 = NSLayoutConstraint(item: self, attribute: .Top, relatedBy: .Equal, toItem: contentView, attribute: .Top, multiplier: 1.0, constant: 0.0)
let constraint2 = NSLayoutConstraint(item: self, attribute: .Bottom, relatedBy: .Equal, toItem: contentView, attribute: .Bottom, multiplier: 1.0, constant: 0.0)
let constraint3 = NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, toItem: contentView, attribute: .Width, multiplier: 1.0, constant: 0.0)
let constraint4 = NSLayoutConstraint(item: self, attribute: .CenterX, relatedBy: .Equal, toItem: contentView, attribute: .CenterX, multiplier: 1.0, constant: 0.0)
self.addConstraints([constraint1, constraint2, constraint3, constraint4])
self.layoutIfNeeded()
// Later, the messages are added to the contentView. I don't think is relevant to see the exact code (but I can post it if needed)
// Each message is added using autolayout and the constraints only reference the messages themselves and contentView
}
}
When I add a ChatView to my view controller (using storyboards), with its four sides pinned to views which are not in his hierarchy, the following problem happens:
In the image, the scrollView cannot be scrolled upwards any more. There seem to be a space which should be filled and isn't. If I scroll down, I have the exact same problem but the empty space is below the content. In the following images you can see that the contentView is smallest than the ChatView itself:
And the same view hierarchy but with the constraints shown:
In both images the view in the background is the ChatView and the selected one is the contentView. I haven't been able to figure why the content view doesn't cover the full ChatView space.
Thanks in advance!
I finally stumbled upon the answer while searching a different problem, in another stackoverflow question. The key is to open the storyboard and set in the container view controller "AdjustsScrollViewInsets" to "NO".
In code it's simply (inside the view controller):
self.automaticallyAdjustsScrollViewInsets = NO;

Programmatic Autolayout changes behaviour of a UIView

I have a controller where I add a subview programmatically. With the configuration of the subview I add autolayout constraints programmatically. Everthing is working except that the view doesn't react on touches if I add the constraints and even the set backgroundcolor is not displayed.
The buttonView should be displayed in the lower right corner of my parent view.
Any ideas what could be wrong?
Here is how I add my constraints:
private func configureAutolayoutConstraints(buttonView: UIView, parentView: UIView){
buttonView.translatesAutoresizingMaskIntoConstraints = false
let bottomConstraint = NSLayoutConstraint(item: buttonView, attribute:
.Bottom, relatedBy: .Equal, toItem: parentView, attribute: .Bottom, multiplier: 1.0, constant: -130)
parentView.addConstraint(bottomConstraint)
let trailingConstraint = NSLayoutConstraint(item: buttonView, attribute:
.Trailing, relatedBy: .Equal, toItem: parentView, attribute: .Trailing, multiplier: 1.0, constant: -90)
parentView.addConstraint(trailingConstraint)
}
Autolayout engine needs at least 4 constraints to determine the frame of view. You have applied bottom and trailing constraints only. You need either width+height OR leading+top constraint to make it work.

How to set UIImageView in the center of screen horizontally or vertically with Swift, but no more StoryBoard

I am trying to put an UIImageView on the upper center of screen horizontally which is coding in the viewDidLoad( ). And I have two pre-plans, which means I do not know the specify functions or APIs.
1). I want to set a variable which equal to the half of screen's width. And I know it gonna work with something about 'bounds' or 'frame'. Pathetically, I do not know those specify function or parameters.
2). In order to make sure the resolution, I want to figure out the currentDevice. After that, I can set UIImageView with CGRectMake((resolution.x)/2, y, length, width). Is there any function can confirm the currentDevice?
And I think the first one is more efficient than the second one.
A big appreciate for your help and guidance.
Ethan Joe
I would suggest to use autolayout:
var imageView = UIImageView()
imageView.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(imageView)
// Create the constraints and add them to a Array
var constraints = [AnyObject]()
// This constraint centers the imageView Horizontally in the screen
constraints.append(NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterX, multiplier: 1.0, constant: 0.0))
// Now we need to put the imageView at the top margin of the view
constraints.append(NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.TopMargin, multiplier: 1.0, constant: 0.0))
// You should also set some constraint about the height of the imageView
// or attach it to some item placed right under it in the view such as the
// BottomMargin of the parent view or another object's Top attribute.
// As example, I set the height to 500.
constraints.append(NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1.0, constant: 500.0))
// The next line is to activate the constraints saved in the array
NSLayoutConstraint.activateConstraints(constraints)
This code horizontally centers the imageView in every device. I suggest you investigating AutoLayout, it's a nice feature.
Here's a nice link where you can start with it:
Learning to love Auto Layout... Programmatically
So, the best solution to this would be to utilize auto layout.
Say your UIImageVew is defined as var imageView = UIImageView!.
Then you would do the following.
var centerXConst = NSLayoutConstraint(item: imageView, attribute: .CenterX, relatedBy: .Equal, toItem: self.view, attribute: .CenterX, multiplier: 1, constant: 1)
var centerYConst = NSLayoutConstraint(item: imageView, attribute: .CenterY, relatedBy: .Equal, toItem: self.view, attribute: .CenterY, multiplier: 1, constant: 1)
self.view.addLayoutConstraints([centerXConst, centerYConst])
What you are doing is setting the center of the imageView on the x and y axis respectively to the same as the center of the view on the x and y axis respectively.
To find the width of the view as you proposed in 1), do the following:
var screenWidth = self.view.bounds.width

Resources