How restrict movement in animateWithDuration - iphone

I'm creating app where UILabel object will move over the screen. My question is how I can restrict the label to go over the specific border. For example if the label have a message, I want have the whole message visible, not just the first part of it.
This is the code:
#define kHeight 320.0
#define kWidth 400.0
#define kTransitionDuration 1.50
#define kTopPlacement 80.0
- (void)myMover {
for (UIView *view in self.view.subviews) {
if( [view isKindOfClass:[UILabel class]]){
[UIView animateWithDuration:4.0 animations:^{
//set the point from where the move will start
[self setRandomLocationForLabel:view];
}];
}
}
}
- (void) setRandomLocationForView:(UIView *)view
{
[view sizeToFit];
CGRect messageViewBounds = CGRectMake(round((self.view.bounds.size.width - kWidth) / 2.0),
200, kWidth, kHeight);
CGRect newFrame = CGRectMake( 0, 300, 100 , 20 );
while (view.frame.size.width > kWidth) {
newFrame.size.width /= 2;
newFrame.size.height /= 2;
}
view.frame = newFrame;
CGFloat x = (CGFloat) (arc4random() % (int) messageViewBounds.size.width + view.frame.size.width/2);
CGFloat y = (CGFloat) (arc4random() % (int) messageViewBounds.size.height + view.frame.size.height/2);
view.center = CGPointMake (x,y);
}
Thank you for any advice!

Since you have the view you know its size. By knowing the width you know how far you need to position the center of the view from left or right (half the width). By knowing the height you know how from top or bottom (half the height).
Now you can calculate the rectangle that contains only the valid center points for that view by taking the full view and create an inset rectangle with half the width of your view subtracted on both left and right and half the height of your view subtracted on both top and bottom.
CGSize viewSize = view.bounds.size; // The view you are positioning
CGRect rectOfValidCenters = CGRectInset(self.view.bounds, // The view you are placing it in
viewSize.width/2.0, // subtract the width/2 from left and right
viewSize.height/2.0); // subtract the height/2 form top and bottom
CGFloat randomX = // generate random value from 0.0 to 1.0
CGFloat randomY = // generate random value from 0.0 to 1.0
// Random valid center point is:
// ( minX + randomX * width , minY + randomY * height)
//
// if x and y are zero then the view's center will be in the upper left
// of the rect of valid centers (making its upper left corner be in the
// top left of the view it's placed in).
// if x and y are one then the view's center will be in the lower right
// of the rect of valid centers (making its lower right corner be in the
// lower right of the view it's placed in).
CGPoint randomValidPoint = CGPointMake(CGRectGetMinX(rectOfValidCenters) + randomX * CGRectGetWidth(rectOfValidCenters),
CGRectGetMinY(rectOfValidCenters) + randomY * CGRectGetHeight(rectOfValidCenters));
view.center = randomValidPoint;

My question is how I can restrict the label to go over the specific border. For example if the label have a message, I want have the whole message visible, not just the first part of it.
You will need to take into account the length/width and height of the label when determining the random position it should land on. As such, your random selection should land in the area of
CGSize labelSize = [messageString sizeWithFont:messageString.font
constrainedToSize:maximumLabelSize
lineBreakMode:messageString.lineBreakMode];
CGFloat minX = 0;
CGFloat minY = 0;
CGFloat maxX = self.view.frame.size.width - labelSize.width;
CGFloat maxY = self.view.frame.size.height - labelSize.height;
// Use minX/Y and maxX/Y in your random co-ordinate algorithm

Related

adding the new view according to the finger touch location in iPhone using UITapGestureRecognizer

To all
I am using the
UITapGestureRecognizer*singleTap = [[[UITapGestureRecognizer alloc] initWithTarget: self action:#selector(doSingleTap:)] autorelease];
singleTap.numberOfTouchesRequired = 2;
[self.view addGestureRecognizer:singleTap
for getting the touch
And in doSingleTap: method i have this
-(void)doSingleTap:(UITapGestureRecognizer *)recognizer
{
CGPoint point = [recognizer locationOfTouch:0 inView:self.view];
NSLog(#"location X =>%f,location =>%f ",point.x,point.y);
CGPoint point1 = [recognizer locationOfTouch:1 inView:self.view];
NSLog(#"location X =>%f,location =>%f ",point1.x,point1.y);
NSLog(#"location X =>%f,location =>%f ",x,y);
UIView *test1 = [[UIView alloc]initWithFrame:CGRectMake(point.x, point1.y, x, y)];
test1.backgroundColor= [UIColor greenColor];
[self.view addSubview:test1];
}
getting the problem in adding the new view on the main view according to the finger location or position View is properly getting add on the view according to the position .
I want that view get add according to the two finger and automatically adjust their (x,y,w,h).
I need help if any one help me
Thanks in advance I google on this but didn't get any help
Compare with point.x and point1.x take lesser 1 as x and do same for y (compare with point.y and point1.y smaller 1 as y). take the difference between point.x and point1.x as width and do same for height (difference between point.y and point1.y) will sove the issue
float x = (point.x < point1.x) ? point.x : point1.x;
float y = (point.y < point1.y) ? point.y : point1.y;
float width = fabsf(point.x - point1.x);
float height = fabsf(point.y - point1.y);
UIView *test1 = [[UIView alloc]initWithFrame:CGRectMake(x, y,width,height)];
Try to calculate rect of view with the next:
float x = MIN(point.x, point1.x);
float y = MIN(point.y, point1.y);
float width = fabsf(point.x - point1.x);
float height = fabsf(point.y - point1.y);
CGRect frame = CGRectMake(x, y, width, height);

How to draw polygons in cocoa touch using UIBezierPath

I want to draw polygon of different sides (4-12). What is the logic for drawing a polygon. For e.g. if user selects 6 side, it should draw a hexagon, if user enters 8 sides it should draw a octagon. I have found the following code but i also want to resize the UIView in which i am drawing a polygon so that the shape inside of the view also grows along with the view. Any body can help me please. Following is the code i am using currently but it is not positioned at the center also when i resize the view that shape moves to another position in the view.
int radius = MINIMUM(widht, height)*0.4 ;
for (int i = 0; i < _numberOFsides; i++){
CGPoint point = CGPointMake(widht/2+radius *cosf(i*2*M_PI/_numberOFsides), widht/2+radius*sinf(i*2*M_PI/_numberOFsides));
if (i==0) {
[_shapePath moveToPoint:point];
}
else{
[_shapePath addLineToPoint:point];
[_shapePath stroke];
}
}
now to resize ur UIBazierPath you can add below code,
CGRect bazierRect = CGPathGetBoundingBox(bezierpath.CGPath)
CGFloat scaleX = view.frame.size.width / bazierRect.frame.size.width;
CGFloat scaleY = view.frame.size.height / bazierRect.frame.size.height;
CGAffineTransform transform = CGAffineTransformMakeScale(scaleX, scaleY);
CGPathRef newPath = CGPathCreateCopyByTransformingPath(bezierpath.CGPath, &transform);
bezierPath.CGPath = newPath;
CFRelease(newPath);
If you want to make a regular polygon with any number of sides the following code will give you the vertices of each edge and it is easy to rescale in size and number of sides:
int n = 10; //number of edges
float j = 20; //length of each edge
float x = 130;
float y = 250;//the point 130,250 will be at the bottom of the figure
float angle = 2*M_PI;
for (int i = 0; i < n; i++) {
CGRect frame = CGRectMake(x, y, 2, 2);//put a dot on x,y
NSLog(#"%f | %f, %f", angle, x, y);
x = x + j*cosf(angle);
y = y + j*sinf(angle); //move to the next point
angle = angle - 2*M_PI/n; //update the angle
//display the dot
UIView *rect = [[UIView alloc] initWithFrame:frame];
rect.backgroundColor = [UIColor blueColor];
[self.view addSubview:rect];
}
Hope this helps. If you have any questions feel free to ask and have a great day!
~Deadly Porcupine

properly zooming in scrollview with 3 imageviews

I'm having a scrollview containing view. In view there is 3 imageViews (screen sized).
At anytime user stands on second imageview.
I want to let user to zoom this imageview.
How to properly implement zooming in my situation?
Please refer to this tutorial , hope it helps :)
how-to-use-uiscrollview-to-scroll-and-zoom-content
you can set scrollview Maximum and Minimum zoom scale like bellow..
on your second page on second image just set your scrollview with maximumzoomscale property...
CGFloat minScale = MIN(yourScrollView.frame.size.width, yourScrollView.frame.size.height);
yourScrollView.minimumZoomScale = minScale;
yourScrollView.maximumZoomScale = 1.0f; /// set here your zoom scale...
yourScrollView.zoomScale = minScale;
UPDATE
// Get a zoom scale that's zoomed in slightly, capped at the maximum zoom scale specified by the scroll view
CGFloat newZoomScale = yourScrollView.zoomScale * 1.5f;
newZoomScale = MIN(newZoomScale, yourScrollView.maximumZoomScale);
// Figure out the rect we want to zoom to, then zoom to it
CGSize scrollViewSize = yourScrollView.bounds.size;
CGFloat w = scrollViewSize.width / newZoomScale;
CGFloat h = scrollViewSize.height / newZoomScale;
CGFloat x = yourScrollView.center.x - (w / 2.0f);
CGFloat y = yourScrollView.center.y - (h / 2.0f);
CGRect rectToZoomTo = CGRectMake(x, y, w, h);
[yourScrollView zoomToRect:rectToZoomTo animated:YES];
i hope this help you...

Restrirct Boundary 320 x 480, while scaling UIImage

I am working on Interior Decoration Application, we can add Sofa, Table, Chair Table Lamp on Camera screen then can scale UIImage with touch to zoom picture. But by zooming we don't want to increase UIImage Size greater then 320 x 480, I mean want to restrict in iphone Boundary.
any suggestion, I had implemented and tried, but couldn't get exact solution. I use to check on base of center but this approach is not working, want some thing like Edge detection may be that would be exact solution,
Already Thanks, looking forwards
here is some code that I am using to Resize my UIImageView
-(BOOL)isValidSizeForView:(UIView *)myView forSize:(CGSize)size
{
BOOL Decision = NO;
CGRect rect = myView.frame;
CGRect BoundRect = CGRectMake(0, 0, 320, 480);
float MinX = (BoundRect.origin.x+(myView.frame.size.width/2));
float MaxX = ((BoundRect.origin.x+BoundRect.size.width)-(myView.frame.size.width/2));
float MinY = (BoundRect.origin.y+(myView.frame.size.height/2));
float MaxY = ((BoundRect.origin.y+BoundRect.size.height)-(myView.frame.size.height/2));
if(rect.origin.x > MinX && rect.origin.x< MaxX && rect.origin.y> MinY && rect.origin.y<MaxY)
{
Decision = YES;
}
else
{
printf(":( no sorry \n");
}
return Decision;
}
You could get the maximum zoomed size for your image by doing something like this:
- (CGSize)zoomedSizeForImage:(UIImage *)image constrainedTo:(CGSize)maxSize {
CGFloat width = image.size.width;
CGFloat height = image.size.height;
if (width > maxSize.width) {
width = maxSize.width;
height = height * maxSize.width / width;
}
if (height > maxSize.height) {
width = width * maxSize.height / height;
height = maxSize.height;
}
return CGSizeMake(width, height);
}

Is it Possible to Center Content in a UIScrollView Like Apple's Photos App?

I have been struggling with this problem for some time and there seems to be no clear answer. Please let me know if anyone has figured this out.
I want to display a photo in a UIScrollView that is centered on the screen (the image may be in portrait or landscape orientation).
I want to be able to zoom and pan the image only to the edge of the image as in the photos app.
I've tried altering the contentInset in the viewDidEndZooming method and that sort of does the trick, but there's several glitches.
I've also tried making the imageView the same size as the scrollView and centering the image there. The problem is that when you zoom, you can scroll around the entire imageView and part of the image may scroll off the view.
I found a similar post here and gave my best workaround, but no real answer was found:
UIScrollView with centered UIImageView, like Photos app
One elegant way to center the content of UISCrollView is this.
Add one observer to the contentSize of your UIScrollView, so this method will be called everytime the content change...
[myScrollView addObserver:delegate
forKeyPath:#"contentSize"
options:(NSKeyValueObservingOptionNew)
context:NULL];
Now on your observer method:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
// Correct Object Class.
UIScrollView *pointer = object;
// Calculate Center.
CGFloat topCorrect = ([pointer bounds].size.height - [pointer viewWithTag:100].bounds.size.height * [pointer zoomScale]) / 2.0 ;
topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
topCorrect = topCorrect - ( pointer.frame.origin.y - imageGallery.frame.origin.y );
// Apply Correct Center.
pointer.center = CGPointMake(pointer.center.x,
pointer.center.y + topCorrect ); }
You should change the [pointer
viewWithTag:100]. Replace by your
content view UIView.
Also change imageGallery pointing to your window size.
This will correct the center of the content everytime his size change.
NOTE: The only way this content don't works very well is with standard zoom functionality of the UIScrollView.
This code should work on most versions of iOS (and has been tested to work on 3.1 upwards).
It's based on the Apple WWDC code for the PhotoScroll app.
Add the below to your subclass of UIScrollView, and replace tileContainerView with the view containing your image or tiles:
- (void)layoutSubviews {
[super layoutSubviews];
// center the image as it becomes smaller than the size of the screen
CGSize boundsSize = self.bounds.size;
CGRect frameToCenter = tileContainerView.frame;
// center horizontally
if (frameToCenter.size.width < boundsSize.width)
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
else
frameToCenter.origin.x = 0;
// center vertically
if (frameToCenter.size.height < boundsSize.height)
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
else
frameToCenter.origin.y = 0;
tileContainerView.frame = frameToCenter;
}
Here is the best solution I could come up with for this problem. The trick is to constantly readjust the imageView's frame. I find this works much better than constantly adjusting the contentInsets or contentOffSets. I had to add a bit of extra code to accommodate both portrait and landscape images.
If anyone can come up with a better way to do it, I would love to hear it.
Here's the code:
- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
CGSize screenSize = [[self view] bounds].size;
if (myScrollView.zoomScale <= initialZoom +0.01) //This resolves a problem with the code not working correctly when zooming all the way out.
{
imageView.frame = [[self view] bounds];
[myScrollView setZoomScale:myScrollView.zoomScale +0.01];
}
if (myScrollView.zoomScale > initialZoom)
{
if (CGImageGetWidth(temporaryImage.CGImage) > CGImageGetHeight(temporaryImage.CGImage)) //If the image is wider than tall, do the following...
{
if (screenSize.height >= CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is greater than the zoomed height of the image do the following...
{
imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), 368);
}
if (screenSize.height < CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is less than the zoomed height of the image do the following...
{
imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]);
}
}
if (CGImageGetWidth(temporaryImage.CGImage) < CGImageGetHeight(temporaryImage.CGImage)) //If the image is taller than wide, do the following...
{
CGFloat portraitHeight;
if (CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale] < 368)
{ portraitHeight = 368;}
else {portraitHeight = CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale];}
if (screenSize.width >= CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is greater than the zoomed width of the image do the following...
{
imageView.frame = CGRectMake(0, 0, 320, portraitHeight);
}
if (screenSize.width < CGImageGetWidth (temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is less than the zoomed width of the image do the following...
{
imageView.frame = CGRectMake(0, 0, CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale], portraitHeight);
}
}
[myScrollView setZoomScale:myScrollView.zoomScale -0.01];
}
Here is how I calculate the the min zoom scale in the viewDidLoad method.
CGSize photoSize = [temporaryImage size];
CGSize screenSize = [[self view] bounds].size;
CGFloat widthRatio = screenSize.width / photoSize.width;
CGFloat heightRatio = screenSize.height / photoSize.height;
initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;
[myScrollView setMinimumZoomScale:initialZoom];
[myScrollView setZoomScale:initialZoom];
[myScrollView setMaximumZoomScale:3.0];