How to Put UIView subview In Places - ios

For Example lets say I have a UIView I would like to display
view.addSubview(line)
Now I want t to be able to display that UIView in the top right corner. Let say inside the right side of the navigation bar. How would I do this? Or even in a specific place.

You will need to calculate the frame or need to give constraints to that view.
let screenSize = UIScreen.main.bounds
let screenWidth = screenSize.width
let screenHeight = screenSize.height
From above you can get screenwidth and you can set your y to 0. Let say width height of your view is 20. So, frame would be like below.
yourView.frame = CGRect(x:screenwidth - 20 , y: 20, width:20 , height: 20)
You can change the frame as per your requirements.
For navigation bar there is a better way to do it by adding right bar item. Look below code how to do it.
self.navigationItem.rightBarButtonItem = rightButtonItem

You can use
self.navigationController?.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: lineMat)
to set up a view on navigationBar right side.
Also you can add the lineMat view on UIApplication.shared.keyWindow
Just use UIApplication.shared.keyWindow?.addSubview(lineMat) and set up to lineMat view's frame.

Add a frame for your subview, as :
Objective-C:
line.frame = CGRectMake(0, 0, 50, 50);
Swift 3:
CGRect(x:0,y:0,width: 50,height: 50)
This will add your line subview on top left corner with height 50 and width 50.

Related

How do I get my label to stick to the top right of my landscape screen with CGPOINT in swift?

Firstly I'm new to swift and I'm trying to create a label that will show a value from my player class on the top right of the screen. How do I make a sticky label on the top right that will stay there as the user pans around the screen?
My end goal is to create something like this clash clans example:
I've created this so far and don't want it to be positioned in middle, Instead what I'm interested in is changing it's position to the side and stay there as the user scrolls.
func layoutScene() {
scoreLabel.fontName = "AvenirNext-Bold"
scoreLabel.fontSize = 60.0
scoreLabel.fontColor = UIColor.white
scoreLabel.position = CGPoint(x: frame.midX, y: frame.midY)
scoreLabel.zPosition = 1;
addChild(scoreLabel)
}
To stick your lable on the top of the view:
1) You need to add transparent UIView on the top of your view.Set this view with leading and top constraint with supperView, give height, width & set UIColor as clear.
2)set your button into your transparent UIView & give appropriate constraint to it.
Note: If you are using scrollView or any other view and trying to stick your button on it. Give the constraint to your transparent view with main view(self.view) so another subviews underneath your transparent view will stay free from it.
Just use this:
scoreLabel.position = CGPoint(x: frame.maxX - scoreLabel.frame.width - 16, y: frame.maxY - 16)

How to properly resize textview with exclusionPaths inside of table header view

I have added a view to my tableView header consisting of an imageView and a textView. The image view is left aligned in the top corner and the textview extends over the imageview to the right side of the screen like as follows.
The textView can have dynamic content and has an exclusion path set as follows:
let imagePath = UIBezierPath(rect: imageView.frame)
self.textView.textContainer.exclusionPaths = [imagePath]
I have disabled scrolling for the textview and have set the following constraints inside of the header view:
TextView: left - 8px, right - 8px, top - 0px, bottom - 8px
ImageView: left - 8px, width - 100px, height 100px, top - 8px, bottom - greater than or equal to 8px
I have added this code after my textView is populated with the dynamic text:
if let headerView = self.tableView.tableHeaderView {
let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height
var headerFrame = headerView.frame
if height != headerFrame.size.height {
headerFrame.size.height = height
headerView.frame = headerFrame
self.tableView.tableHeaderView = headerView
}
}
Which adjusts the size of the header. However, when the textView has less text than the height of the image, the size of the view grows.
Example of three lines of text:
Example of six lines of text:
Example of enough text to pass imageview:
Does anyone know why this is happening?
I have a fix for this, because I just encountered this issue myself :)
You see, I was trying to do something very similar, where a UITextView's text should avoid a UIImageView to its left. My code was the following:
let ticketProfileExclusionPath = UIBezierPath(roundedRect: ticketProfilePicture.frame, cornerRadius: Constants.ProfilePictureExclusionRadius)
ticketContent.textContainer.exclusionPaths.append(ticketProfileExclusionPath)
And my results were not very good:
As you can see, the problem relies on the CGRect given to the ticketContent UITextView as its exclusion path, since the latter assumes the given CGRect is corrected to its own frame, not its superview's.
The fix is very simple and requires the use of an API present since the dawn of time (iOS 2.0):
let exclusionPathFrame = convert(ticketProfilePicture.frame, to: ticketContent).offsetBy(dx: Constants.SystemMargin, dy: Constants.Zero)
What we're doing here is converting the UIImageView's frame to the UITextView's coordinate system, therefore providing the correct exclusion path from the perspective of the UITextView. The added offset is simply to align all three of my UITableViewCell's text UIViews.
convert() is a UIView method.
As you can see, the text now wraps around the ticketProfilePicture UIImageView quite nicely.
Hope this helps.
For anyone using Auto Layout, make sure to add the exclusionPathFrame in viewDidLayoutSubviews().
You can calculate textview text height with content size.
let tempTextview = UITextView(frame: CGRect(x: 50, y: 50, width: 120, height: 250))
tempTextview.text = "Dynamic Text"
let height = tempTextview.contentSize.height
Add you extra top and bottom padding to this height.
height = height + padding
if imageview.frame.size.height > height
{
return imageview.frame.size.height
}
else
{
return height
}

Swift programmatically place UIImageView on top of another and resize

On my storyboard I have 2 image views.
One holds the main image, the second is an overlay which will be used to specify the crop area of the main image.
In my viewDidLoad I've done this.
let screen_width = UIScreen.mainScreen().bounds.width
let screen_height = UIScreen.mainScreen().bounds.height
self.overlayImage.frame = CGRect(x: self.imageView.frame.origin.x, y: self.imageView.frame.origin.y, width: screen_width, height: (screen_height * 0.1919))
The goal is to have the overlayImage's top left corner lined up properly with the imageView's top left corner. Also the height of the overlay should be about 1/5th of the screens size. However when I run the code the overlayImage is exactly the same size and in the same location it was originally on the storyboard.
How can I programmatically line it up on top of the imageView after the image has been set to it, and also resize the overlayImage dynamically in the viewDidload?
I'd just do it manually in storyboard editor but everyone will have different screen sizes so I thought it best to use the mainscreen().bounds.height variable to determine the amount of height to use dynamically at runtime.
All you have to do is to write your above code in viewDidAppear instead of viewDidLoad as below:-
override func viewDidAppear(animated: Bool) {
let screen_width = UIScreen.mainScreen().bounds.size.width
let screen_height = UIScreen.mainScreen().bounds.size.height
self.overlayImage.frame = CGRect(x: 0, y: 0, width: screen_width, height:screen_height/5)
}
And your frame will set itself as desired.
Since you're working with Storyboard, I would rather use Autolayout and Constraints to solve this problem for me... For instance you set the constraints for your first image view, then set the constraints of your overlay based and related to the former one. Example:
Lower UIImageView: set leading, trailing, top and bottom constraints
Overlay: set center X and Y constraints to be equal to the lower Image
Overlay: set height and width to be proportional to the lower image
Thus, when ever the screen size changes, the two images will always resize equally...
Interface builder:
Set overlay top, leading, width to your image view.
give your overlay a constant height constraint; the constraint cosntant value is arbitrary because you will replace it at run time
ctrl + drag an IBOutlet from this height constraint to your viewcontroller
in your viewWillLayoutSubViews set the .constant of your height constraint to UIScreen.main.bounds.size.height / 5

Contain items with dynamic height in VC with scrollable functionality

Here is an image of what I'm envisioning.
Two bottoms at the bottom will always stay there. And height of textview and container view is dynamic. I will container another viewcontroller in container view. When sum of height of textview and container view is bigger than current viewcontroller's height, I want them to be scrollable.
I've been looking into 2 things: UICollectionView, UIScrollView.
However, I could not figure out how to make what I'm envisioning with those two components.
I also tried with stackview but that was not suitable for my purposes.
My gut tells me that UIScrollView is way to go but I cannot figure out. My current attempt was putting a scroll view and set the constraints to Nav bar and 2 buttons. Then, put textview and container view inside scroll view using storyboard.
If somebody can guide me a bit, that would be super helpful to me. Sorry for not containing any code, btw. I just couldn't even start :/
let margin = CGFloat(10)
let scrollView = UIScrollView(frame: view.frame)
let textView = UITextView(frame: CGRectMake())//Set textViewFrame
let containerView = UIView(frame: CGRectMake(x:margin, y: textView.height + margin, width: view.frame.width - 2 * margin, height: view.frame.height)
let button1 = UIButton(frame: CGRectMake(x:margin, y: textView.height + contentView.height + 2 * margin, width: (view.frame.width - 2 * margin) /2, height: 30)
scrollView.contentSize = CGSize(width: view.frame.width, height: button1.frame.origin.y + button1.frame.height + margin)
That should be enough to get you started. The important thing is adjusting the scrollView's content size to extend past the frame of the view. To test where this would get you you still need to add as subviews and you could also set backround colors different colors and adjust as necessary.

UIView appears with wrong center position

In the following function I define all the necessary characteristics of a UIView:
func OpenController() {
var gameOverView: UIView = UIView()
gameOverView.center = super.view.center
gameOverView.frame.size = CGSize(width: 200, height: 300)
gameOverView.backgroundColor = UIColor.grayColor()
self.view.addSubview(gameOverView)
}
Even though I define the center of the UIView "gameOverView" as that of the the viewcontroller it resides in, it appears with a corner in the center of the viewcontroller and not centered in the viewcontroller. I have tried various other ways of defining the position (NSLayoutConstraints, frame.x, frame.y etc.) but all have this result.
If anyone can tell me why this happens and how to center the UIView within its parent view controller I would greatly appreciate it!
Your issue here is that your center is being set before the frame. Since you are creating the view without the frame argument your frame is {0, 0}.
So you are currently centering the subview then resizing it, so this is happening:
What you need to do is resize the subview then center it, like this:
So you can just swap your centering and framing logic:
gameOverView.frame.size = CGSize(width: 200, height: 300)
gameOverView.center = super.view.center
Otherwise even easier just pass the frame when creating the view (you could even pass in the proper x, y coordinates to center it here too):
var gameOverView: UIView = UIView(frame: CGRectMake(0, 0, 200, 300))
You have to set the center of the view after setting its size. This is because before setting the size or frame of a view its frame rect is (x:0,y:0,width:0,height:0). If you then immediately set its center, then a view of size zero will get centered so its new frame rect could be (x:20,y:20,width:0,height:0) (if the parent view is 40x40). If you now change the view's size, the origin point of the view will not actually move so the new frame could be (x:20,y:20,with:5,height:5) which means the view is no longer centered.
So to center a view you have to first set its size and the its center.

Resources