21

I am creating a UIImageView and adding it in a loop to my view, I set the initial frame to 0,0,1,47 and each passage of the loop I change the center of the image view to space them out.

I am always using 0 as the origin.y

The problem is the origin reference is in the centre of the image view, assuming we was in interface builder, this is equivalent to the image below.

How can I change the reference point in code ?

enter image description here

Daniel
  • 23,129
  • 12
  • 109
  • 154

4 Answers4

46

After reading these answers and your comments I'm not really sure what is your point.

With UIView you can set position by 2 ways:

  • center – It definitely says it is the center.
  • frame.origin – Top left corner, can't be set directly.

If you want the bottom left corner to be at x=300, y=300 you can just do this:

UIView *view = ...
CGRect frame = view.frame;
frame.origin.x = 300 - frame.size.width;
frame.origin.y = 300 - frame.size.height;
view.frame = frame;

But if you go one level deeper to magical world of CALayers (don' forget to import QuartzCore), you are more powerful.

CALayer has these:

  • position – You see, it don't explicitely says 'center', so it may not be center!
  • anchorPointCGPoint with values in range 0..1 (including) that specifies point inside the view. Default is x=0.5, y=0.5 which means 'center' (and -[UIView center] assumes this value). You may set it to any other value and the position property will be applied to that point.

Example time:

  1. You have a view with size 100x100
  2. view.layer.anchorPoint = CGPointMake(1, 1);
  3. view.layer.position = CGPointMake(300, 300);
  4. Top left corner of the view is at x=200, y=200 and its bottom right corner is at x=300, y=300.

Note: When you rotate the layer/view it will be rotated around the anchorPoint, that is the center by default.

Bu since you just ask HOW to do specific thing and not WHAT you want to achieve, I can't help you any further now.

Tricertops
  • 8,492
  • 1
  • 39
  • 41
  • 1
    I was very confused when I asked this. In short, Xcode's IB feature you could set the metrics of a UIView with a helpful panel, setting the pixel values, but you could also change the point of reference from centre, to top middle, top right, bottom left, etc... and this made me think I could do this somehow in code, but it was just a UI helpful if not confusing addition to Apple's Xcode... – Daniel Jan 07 '13 at 03:05
  • 1
    I remember the whole point was for an easier and quicker way to align a subview to the right, by setting the origin to right centre, and then giving the value the width of it's parent. This means bypassing a need to do maths calculating width minus child width etc etc – Daniel Jan 07 '13 at 20:01
  • You can easily create a cetagory on `UIView` with properties like `frameBorderLeft` or `frameOrigin` and implement those accessors manually. Then you have it easier. – Tricertops Jan 16 '13 at 09:17
  • anchorPoint is pure magic, thanks so much for that! Had a slightly different issue, I was scaling views that are anchored at the bottom. anchorPoint property made this a total non-issue - removed about 20 lines of code... – n13 Aug 17 '15 at 03:08
8

The object's frame includes its position in its superview. You can change it with something like:

CGRect frame = self.imageView.frame;
frame.origin.y = 0.0f;
self.imageView.frame = frame;
Phillip Mills
  • 30,888
  • 4
  • 42
  • 57
  • 1
    Hi, the question is not so much how to change the frame, it's how to change the reference point of the origin. Currently setting y=0 means the centre of the view is put to y=0, not the top – Daniel Apr 04 '12 at 13:58
  • When you say origin, which origin are you talking about? The origin.y offset of the frame is the position of its top within the superview. There is a 'center' property for a view but I don't know of any movable reference point within a view. – Phillip Mills Apr 04 '12 at 14:08
  • 1
    Origin is probably not the best word to describe what I mean, you see in IB, you can change the origin reference point from top left, to say centre, or bottom middle, or centre right... see the image I attached. Well I added a view in code, and I wanted to set the origin (coordinates) to the top of the parent view, so say I would have y=0. However it seems my view's origin reference point is set not to the top left as seems to be the default, but it's set to the centre (see image). Therefore when I set y=0, the view is only showing it's bottom half as the centre of that view is set to y=0 – Daniel Apr 10 '12 at 23:36
  • @Daniel did you mark this as resolved? I don't think it answers your question. Have you found a solution yet? – Leonel Galán Oct 05 '12 at 16:23
  • 1
    You have the same problem? It's because Xcode's interface builder is just easier visually to layout things. Actually the origin is the centre... – Daniel Oct 05 '12 at 18:46
2

If I am understanding you correctly, you need to set the frame of the image view you are interested in moving. This can be done in the simple case like this:

_theImageView.frame = CGRectMake(x, y, width, height);

Obviously you need to set x, y, width, and height yourself. Please also be aware that a view's frame is in reference to its parent view. So, if you have a view that is in the top left corner (x = 0, y = 0), and is 320 points wide and 400 points tall, and you set the frame of the image view to be (10, 50, 100, 50) and then add it as a subview of the previous view, it will sit at x = 10, y = 50 of the parent view's coordinate space, even though the bounds of the image view are x = 0, y = 0. Bounds are in reference to the view itself, frame is in reference to the parent.

So, in your scenario, your code might look something like the following:

CGRect currentFrame = _theImageView.frame;
currentFrame.origin.x = 0;
currentFrame.origin.y = 0;
_theImageView.frame = currentFrame;

[_parentView addSubview:_theImageView];

Alternatively, you can say:

CGRect currentFrame = _theImageView.frame;
_theImageView.frame = CGRectMake(0, 0, currentFrame.size.width, currentFrame.size.height);

[_parentView addSubview:_theImageView];

Either approach will set the image view to the top left of the parent you add it to.

jmstone617
  • 5,707
  • 2
  • 24
  • 26
  • 1
    Hi the problem is the origin point is set to the absolute centre of that view, I need to change it to be the top left. – Daniel Apr 04 '12 at 14:00
  • As I explained above, you would just need to set the x and y of the image view to 0, 0. This will place it at 0, 0 of its parent view. – jmstone617 Apr 04 '12 at 14:02
  • 1
    What I really needed is to set the origin of my view to a known point without worrying about the view's size. – Daniel Oct 05 '12 at 19:59
  • Thanks jmstone. This helped in my case. – Dhammini F. Jul 31 '15 at 03:26
0

I thought I would take a cut at this in Swift.

If one would like to set a views position on the screen by specifying the coordinates to an origin point in X and Y for that view, with a little math, we can figure out where the center of the view needs to be in order for the origin of the frame to be located as desired.

This extension uses the frame of the view to get the width and height.

The equation to calculate the new center is almost trivial. See the below extension :

extension CGRect {
    
    // Created 12/16/2020 by Michael Kucinski for anyone to reuse as desired
    func getCenterWhichPlacesFrameOriginAtSpecified_X_and_Y_Coordinates(x_Position: CGFloat, y_Position: CGFloat)  -> CGPoint
    {
        // self is the CGRect
        let widthDividedBy2 = self.width / 2
        let heightDividedBy2 = self.height / 2
        
        // Calculate where the center needs to be to place the origin at the specified x and y position
        
        let desiredCenter_X = x_Position + widthDividedBy2
        let desiredCenter_Y = y_Position + heightDividedBy2
        
        let calculatedCenter : CGPoint = CGPoint(x: desiredCenter_X, y: desiredCenter_Y)
        
        return calculatedCenter // Using this point as the center will place the origin at the specified X and Y coordinates
    }
}

Usage as shown below to place the origin in the upper left corner area, 25 pixels in :

// Set the origin for this object at the values specified
maskChoosingSlider.center = maskChoosingSlider.frame.getCenterWhichPlacesFrameOriginAtSpecified_X_and_Y_Coordinates(x_Position: 25, y_Position: 25)

If you want to pass a CGPoint into the extension instead of X and Y coordinates, that's an easy change you can make on your own.

user3408691
  • 93
  • 1
  • 1
  • 7