I'm trying to figure out how to use the UIView's convertPoint function in the swift playground. I'm not getting the results I expect and I'm not sure why.
When I Try:
import UIKit
let large = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
let small = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
let point = CGPoint(x: 200, y: 200)
large.convertPoint(point, toView: small)
I expect: {x: 100, y: 100}
I actually get: {x: 200, y: 200}
What am I missing?
change your code (small view) to
let large = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
let small = UIView(frame: CGRect(x: 20, y: 20, width: 200, height: 200))
let point = CGPoint(x: 200, y: 200)
let convertedPoint = large.convertPoint(point, toView: small)
print(convertedPoint)
prints out: (180.0, 180.0)
and that is totally correct. take a look at the image:
as you can see the red dot is at 200, 200 (exactly in the middle) of the large - dark gray - view and at 180, 180 (near the bottom right) of the small - light gray - view.
if we now get back to your example with the small view's origin at 0, 0 instead of 20, 20 the red dot is at 200, 200 (exactly in the middle) of the large view and also at 200, 200 (exactly at the bottom right) of the small view. look:
so the output you get totally makes sense! hope i could help...
Related
I am making a photo app that I want the imagePicker screen to have blocks of red to pre mask the photo before it crops. My following code gets a roadblock on the top x axis. I would like to place another red box along the entire y axis where the yellow rectangle is.
let blockView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: self.view.frame.size.width, height: 150))
blockView.backgroundColor = UIColor.red
imagePicker.cameraOverlayView = blockView
Please try the following :
let mainView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height-150))
let blockView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: self.view.frame.size.width, height: 150))
blockView.backgroundColor = UIColor.red
let blockView1 = UIView.init(frame: CGRect.init(x: 0, y: 170, width: 100, height: self.view.frame.size.height-320))
blockView1.backgroundColor = UIColor.green
mainView.addSubview(blockView)
mainView.addSubview(blockView1)
imagePicker.cameraOverlayView = mainView
If I change a UIView's bounds from...
v2.bounds = CGRect(0, 0, 70, 70)
to...
v2.bounds = CGRect(-2000, 0, 70, 70)
... nothing happens - the dimensions stay the same upon rendering. Why is this?
To help understand what bounds does, run this sample code in a view controller's viewDidLoad method:
let newView = UIView(frame: CGRect(x: 50, y: 100, width: 30, height: 30))
newView.backgroundColor = UIColor.blue
let secondView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
secondView.backgroundColor = UIColor.red
newView.addSubview(secondView)
view.addSubview(newView)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
newView.bounds = CGRect(x: 10, y: 0, width: 30, height: 30)
}
Here we're moving the bounds to the right by 10 points, so you'll see the "second view" (which is red) move to the left by 10 points.
Changing the origin of the bounds changes the coordinate system of the view, which affects the location of all of it's subviews. It doesn't affect its origin with respect to its super view, however. For that, you should change the origin of the frame.
Bounds only takes into account width and height, you are only changing the origin in your example, only changing x to be precise. To accomplish this use frame property:
v2.frame = CGRect(-2000, 0, 70, 70)
For the life of me, I can't figure out how to center a UIButton in UIScrollView...
let sv = UIScrollView(frame: CGRect(x: 0, y: 0, width: 300, height: 600))
let b = UIButton(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
sv.addSubview(b)
b.center = sv.center
No matter what I do, the button seems to be off center. This logic works in normal UIView. Why doesn't it with UIScrollView?
you can also use
let b = UIButton(frame: CGRect(x: sv.frame.size.width/2 -15, y: sv.frame.size.height/2 -15, width: 30, height: 30))
for your code first check value of sv.center, if it is OK and your UI is not updating then call layoutIfneeded
Reference : How is layoutIfNeeded used?
I have the following code, which creates UIView, and some of its subViews, and adds them to a UIScrollView, all in a loop :
var count:CGFloat=bookScrollView.frame.minX
for var i=0;i<10;i++ {
var view=UIView(frame: CGRect(x: count + 20, y: bookScrollView.frame.minY + 30, width: 200, height: 300))
view.backgroundColor=UIColor.whiteColor()
view.layer.cornerRadius = 5;
view.layer.masksToBounds = true;
var imageView=UIImageView(frame: CGRect(x: count, y: view.frame.minY - 30, width: 150, height: 220))
// imageView.image=UIImage(named: "Sample_Book")!
view.addSubview(imageView)
var titleLabel=UILabel(frame: CGRect(x: count + 10, y: imageView.frame.maxY + 30, width: 185, height: 60))
titleLabel.text="Head First Javascript"
titleLabel.backgroundColor=UIColor.clearColor()
titleLabel.font=UIFont(name: "Menlo-Bold ", size: 15)
titleLabel.textAlignment = NSTextAlignment.Center
titleLabel.textColor=UIColor.grayColor()
view.addSubview(titleLabel)
bookScrollView.addSubview(view)
count+=220
}
bookScrollView.contentSize=CGSize(width: count, height: 200)
It works fine,except the fact that other than in the first view,imageView and titleLabel are not visible.
The label and the imageView have moved towards the right from the second view onwards.
Frames are expressed according to the superview's coordinate space.
Since you're adding your image view and label to the view not the scroll view, their frames should be specified in view's coordinate space. So you do not need to add count to their x position.
var imageView=UIImageView(frame: CGRect(x: 0.0, y: 0.0, width: 150, height: 220))
And:
var titleLabel=UILabel(frame: CGRect(x: 10.0, y: imageView.frame.maxY + 30, width: 185, height: 60))
Note: You should look into UICollectionView and autolayout for a more robust way of achieving this.
I can generate a square with this standard code.
func drawSquare() {
let width:CGFloat = 100
var square = UIBezierPath()
square.moveToPoint(CGPoint(x: 0, y: 0))
square.addLineToPoint(CGPoint(x: width, y: 0))
square.addLineToPoint(CGPoint(x: width, y: width))
square.addLineToPoint(CGPoint(x: 0, y: width))
square.lineWidth = 5
square.closePath()
UIColor.blackColor().setStroke()
square.stroke()
}
However, if I want to draw each addLineToPoint() segment in two steps, my square no longer draws correctly.
func drawSquare2Steps() {
let width:CGFloat = 200
let mult:CGFloat = 2
var square = UIBezierPath()
square.moveToPoint(CGPoint(x: 0, y: 0))
square.addLineToPoint(CGPoint(x: 100, y: 0)) // 1
square.addLineToPoint(CGPoint(x: 200, y: 0)) // 2
square.addLineToPoint(CGPoint(x: 200, y: 100)) // 3
square.addLineToPoint(CGPoint(x: 200, y: 200)) // 4
square.addLineToPoint(CGPoint(x: 100, y: 200)) // 5
square.addLineToPoint(CGPoint(x: 0, y: 200)) //6
square.lineWidth = 5
square.closePath() // 7
UIColor.orangeColor().setStroke()
square.stroke()
}
Here's the path that I see:
I tried to describe this function in this image:
My final goal isn't to draw a square but a more complicated path. The square simply illustrates the problem with my complex path.
Nothing is wrong except that your view size is (100, 100) but the square size is (200,200), so you don't see the whole square.