CGAffineTransformMakeTranslation translate to a point rather then by a value. - iphone

My question is simple.
Let us say I use this method
CGAffineTransformMakeTranslation(5.0f, 0.0f);
which translates the image view 5 pixels to the right. But is there a similar method that does the exact same thing except takes the destination point as an argument rather then the values you want to move the image view by?
For example, if I wanted to move an image view to 100.0f, 0.0f what would I use?

You can use the following two options:
imgOne.center = CGPointMake(50, 50);
or
imgOne.frame = CGRectMake(50, 50, imgOne.frame.size.width, imgOne.frame.size.height);

If it's the center point you want to move to this coordinate, use:
imageView.center = CGPointMake(100.0f, 0.0f);
If it's one of the corner points, subtract/add half the view's frame's width/height to the coordinates. If you need this frequently, it's a good idea to write a small UIView category that allows you to position a view's corner on a particular coordinate.

Related

Rotating UIImageView Moves the Image Off Screen

I have a simple rotation gesture implemented in my code, but the problem is when I rotate the image it goes off the screen/out of the view always to the right.
The image view that is being rotated center X gets off or increases (hence it going right off the screen out of the view).
I would like it to rotate around the current center, but it's changing for some reason. Any ideas what is causing this?
Code Below:
- (void)viewDidLoad
{
[super viewDidLoad];
CALayer *l = [self.viewCase layer];
[l setMasksToBounds:YES];
[l setCornerRadius:30.0];
self.imgUserPhoto.userInteractionEnabled = YES;
[self.imgUserPhoto setClipsToBounds:NO];
UIRotationGestureRecognizer *rotationRecognizer = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:#selector(rotationDetected:)];
[self.view addGestureRecognizer:rotationRecognizer];
rotationRecognizer.delegate = self;
}
- (void)rotationDetected:(UIRotationGestureRecognizer *)rotationRecognizer
{
CGFloat angle = rotationRecognizer.rotation;
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, angle);
rotationRecognizer.rotation = 0.0;
}
You want to rotate the image around it's center, but that's not what it is actually happening. Rotation transforms take place around the origin. So what you have to do is to apply a translate transform first to map the origin to the center of the image, and then apply the rotation transform, like so:
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, self.imageView.bounds.size.width/2, self.imageView.bounds.size.height/2);
Please note that after rotating you'll probably have to undo the translate transform in order to correctly draw the image.
Hope this helps
Edit:
To quickly answer your question, what you have to do to undo the Translate Transform is to subtract the same difference you add to it in the first place, for example:
// The next line will add a translate transform
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, 10, 10);
self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, radians);
// The next line will undo the translate transform
self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, -10, -10);
However, after creating this quick project I realized that when you apply a rotation transform using UIKit (like the way you're apparently doing it) the rotation actually takes place around the center. It is only when using CoreGraphics that the rotation happens around the origin. So now I'm not sure why your image goes off the screen. Anyway, take a look at the project and see if any code there helps you.
Let me know if you have any more questions.
The 'Firefox' image is drawn using UIKit. The blue rect is drawn using CoreGraphics
You aren't rotating the image around its centre. You'll need correct this manually by translating it back to the correct position

UIView's position

I have 4 views and i am drawing circles inside these views.The user is able to move these views.How can i get the position of each view relative to the window(i mean relative to 320*480)?
I want to draw and fill a polygon using the position of views.
You can use the frame property of the UIView to retrieve its location and size. See the class reference for more information:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIView_Class/UIView/UIView.html
Example:
... = myView.frame.origin.x; //x-coord
... = myView.frame.origin.y; //y-coord
... = myView.frame.size.width; //width
... = myView.frame.size.height; //height
You can grab the position in the following way:
CGPoint positionOfAView = view.frame.origin;
or if transforms were applied:
CGPoint positionOFAView = view.bounds.origin;
Alternatively, you may want to grab the center:
CGPoint centerOfAView = view.center;
See this answer, too.
You have posted the same question again.(your first question) Before anybody answer's this question the same way it was answered earlier. Can you please tell,
Are you drawing the Circles in the view using CoreGraphics?
When you say 4 different views, how they are managed? Are they displayed at the same time?
Are there 4 View objects added on 1 ViewController?
You can get the position using
CGRect frame = [myView frame];
But remember it will send coordinates and origin based on its parent view
And after making changes
myView.frame = frame;
Hope this helps....
If you want to just move a view (without changing it size), consider using the center property, it might be more convenient.
Here's an example, assuming your circle structure is built in a certain way :)
myView.center = CGPointMake(circle.x + circle.width/2, circle.y + circle.height/2);

UIImageView coordinate to subview coordinates

If I start with a UIImageView, and I add a subview, how do I translate a coordinate in the original UIImageView to a corresponding coordinate (the same place on the screen) in the subview?
UIView provides methods for exactly this purpose. In your case you have two options:
CGPoint newLocation = [imageView convertPoint:thePoint toView:subview];
or
CGPoint newLocation = [subview convertPoint:thePoint fromView:imageView];
They both do the same thing, so pick whichever one feels more appropriate. There's also equivalent functions for converting rects. These functions will convert between any two views on the same window. If the destination view is nil, it converts to/from the window base coordinates. These functions can handle views that aren't direct descendants of each other, and it can also handle views with transforms (though the rect methods may not produce accurate results in the case of a transform that contains any rotation or skewing).
Subtract the subview's frame.origin from the point in the parents view to the same point in the subview's coordinate:
subviewX = parentX - subview.frame.origin.x;
subviewY = parentY - subview.frame.origin.y;
Starting with code like:
UIImageView* superView=....;
UIImageView subView=[
[UIImageView alloc]initWithFrame:CGRectMake(0,0,subViewWidth,subViewHeight)
];
subView.center=CGPointMake(subViewCenterX, subViewCenterY);
[superView addSubview:subView];
The (subViewCenterX, subViewCenterY) coordinate is a point, in superView, where the center of subView is "pinned". The subView can be moved around wrt the superView by moving its center around. We can go, for example
subView.center=CGPointMake(subViewCenterX+1, subViewCenterY);
to move it 1 point to the right. Now lets say we have a point (X,Y) in the superView, and we want to find the corresponding point (x,y) in the subView, so that (X,Y) and (x,y) refer to the same point on the screen. The formula for x is:
x=X+subViewWidth/2-subViewCenterX;
and similarly for y:
y=Y+subViewHeight/2-subViewCenterY;
To explain this, if you draw a box representing the superView, and another (larger) box representing the subView, the difference subViewWidth/2-subViewCenterX is "the width of the bit of the subView box sticking out to the left of the superView"

Curving/warping views with CoreAnimation or OpenGL for carousel effect

Right now I'm populating a UIScrollView with a series of views. The views need to be warped to make the UIScrollView appear like a carousel. In other words when the user scrolls it needs to be like a circle. I've never done anything quite like this before, but I'm assuming CoreAnimation is out of the question and OpenGL needs to be used. If this is possible with CoreAnimation or Quartz then I really just need a sample on how to warp the views and I can figure the rest out myself but I'm not familiar with OpenGL.
If you want to warp the views, you'll either need OpenGL or you could use Core Animation's CAShapLayer which allows you to specify a bezier path which can have this curve in it. But keep in mind that this curving you're seeing is likely just an optical illusion (though in your image above it looks like an actual curve). If you get enough rectangles with the correct y axis rotation in a row, I think you can come up with the effect you're looking for with straight Core Animation. I'm pretty sure that's how things are implemented in the Core Animation demos Apple provided a couple years ago. Here's a screenshot from the video from that presentation:
I messed around with the transform of a view's layer a little bit and came up with this:
- (IBAction)sliderDidChange:(id)sender
{
CGFloat value = [(UISlider*)sender value];
CGFloat xOff = value - 0.5;
CATransform3D trans = CATransform3DIdentity;
trans.m34 = 1.0f / -1000.0f;
trans = CATransform3DRotate(trans, degreesToRadians(xOff * -25.0f), 0.0f, 1.0f, 0.0f);
trans = CATransform3DTranslate(trans, 0.0f, 0.0f, 900.0f * fabs(xOff));
[[frameView layer] setTransform:trans];
CGPoint center= [frameView center];
[frameView setCenter:CGPointMake(1024.0 * value, center.y)];
}
I threw together a demo project that shows how the rotation works in response to a slider. It doesn't use a scroll view so you would have to adapt it, but I think you can track the current scroll offset and apply the transform accordingly. Not sure if it will help but there it is.
In my experience, it is a bit tricky to get the values right. The way to give a view perspective is by manipulating it's layer transform. I have used the following method to achieve the transfor for a similar effect:
-(CATransform3D)makeTransformForAngle:(CGFloat)angle from:(CATransform3D)start{
CATransform3D transform = start;
// the following two lines are the key to achieve the perspective effect
CATransform3D persp = CATransform3DIdentity;
persp.m34 = 1.0 / -1000;
transform = CATransform3DConcat(transform, persp);
transform = CATransform3DRotate(transform,angle, 0.0, 1.0, 0.0);
return transform;
}
This was done to create a "flip page" animation, so you may need to adapt. To use it, do the following:
flip_page.layer.transform = [self makeTransformForAngle:angle from:CATransform3DIdentity];
where flip_page is a UIView. Cheers!

Is it possible to set the position of an UIImageView's image?

I have a UIImageView that displays a bigger image. It appears to be centered, but I would like to move that image inside that UIImageView. I looked at the MoveMe sample from Apple, but I couldn't figure out how they do it. It seems that they don't even have an UIImageView for that. Any ideas?
What you need is something like (e.g. showing the 30% by 30% of the top left corner of the original image):
imageView.layer.contentsRect = CGRectMake(0.0, 0.0, 0.3, 0.3);
Description of "contentsRect":
The rectangle, in the unit coordinate space, that defines the portion of the layer’s contents that should be used.
Original Answer has been superseded by CoreAnimation in iOS4.
So as Gold Thumb says: you can do this by accessing the UIView's CALayer. Specifically its contentRect:
From the Apple Docs: The rectangle, in the unit coordinate space, that defines the portion of the layer’s contents that should be used. Animatable.
Do you want to display the image so that it is contained within the UIImageView? In that case just change the contectMode of UIImageView to UIViewContentModeScaleToFill (if aspect ratio is inconsequential) or UIViewContentModeScaleAspectFit (if you want to maintain the aspect ratio)
In IB, this can be done by setting the Mode in Inspector.
In code, it can be done as
yourImageView.contentMode = UIViewContentModeScaleToFill;
In case you want to display the large image as is inside a UIImageView, the best and easiest way to do this would be to have the image view inside a UIScrollView. That ways you will be able to zoom in and out in the image and also move it around.
Hope that helps.
It doesn't sound like the MoveMe sample does anything like what you want. The PlacardView in it is the same size as the image used. The only size change done to it is a view transform, which doesn't effect the viewport of the image. As I understand it, you have a large picture, and want to show a small viewport into it. There isn't a simple class method to do this, but there is a function that you can use to get the desired results: CGImageCreateWithImageInRect(CGImageRef, CGRect) will help you out.
Here's a short example using it:
CGImageRef imageRef = CGImageCreateWithImageInRect([largeImage CGImage], cropRect);
[UIImageView setImage:[UIImage imageWithCGImage:imageRef]];
CGImageRelease(imageRef);
Thanks a lot. I have found a pretty simple solution that looks like this:
CGRect frameRect = myImage.frame;
CGPoint rectPoint = frameRect.origin;
CGFloat newXPos = rectPoint.x - 0.5f;
myImage.frame = CGRectMake(newXPos, 0.0f, myImage.frame.size.width, myImage.frame.size.height);
I just move the frame around. It happens that portions of that frame go out of the iPhone's view port, but I hope that this won't matter much. There is a mask over it, so it doesn't look weird. The user doesn't totice how it's done.
You can accomplish the same by:
UIImageView *imgVw=[[UIImageView alloc]initwithFrame:CGRectMake(x,y,height,width)];
imgVw.image=[UIImage imageNamed:#""];
[self.view addSubView imgVw];
imgVw.contentMode = UIViewContentModeScaleToFill;
You can use NSLayoutConstraint to set the position of UIImageView , it can be relative to other elements or with respect to the frame.
Here's an example snippet:
let logo = UIImage(imageLiteralResourceName: "img")
let logoImage = UIImageView(image: logo)
logoImage.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(logoImage)
NSLayoutConstraint.activate([logoImage.topAnchor.constraint(equalTo: view.topAnchor,constant: 30),
logoImage.centerXAnchor.constraint(equalTo: view.centerXAnchor),logoImage.widthAnchor.constraint(equalToConstant: 100),logoImage.heightAnchor.constraint(equalToConstant: 100)
])
This way you can also resize the image easily. The constant parameter represents, how far should a certain anchor be positioned relative to the specified anchor.
Consider this,
logoImage.topAnchor.constraint(equalTo: view.topAnchor,constant: 30)
The above line is setting the top anchor of the instance logoImage to be 30 (constant) below the parent view. A negative value would mean opposite direction.