Add space between UIimageview layer's border and content - iphone

Hi i have the CALayer with content has images. Now i need to add the Tap gesture on it. How is is it possible please give any example for add Tap for CALayer.
This is my code:
CALayer *imageLayer=[CALayer layer];
imageLayer.frame=frame;
imageLayer.cornerRadius=10.0;
imageLayer.borderWidth=2.0;
imageLayer.borderColor=[UIColor colorWithRed:0.957 green:0.957 blue:0.957 alpha:1].CGColor;
CALayer *imagecontent=[CALayer layer];
imagecontent.frame=CGRectMake(16, 26, 153, 153);
UIImage *image=[self.pageImages objectAtIndex:page];
imagecontent.contents=(id)image.CGImage;
imagecontent.masksToBounds = YES;
[imageLayer addSublayer:imagecontent];
[self.scrollView.layer addSublayer:imageLayer];
Here i want add Tap gesture for "image content" please help me.

You cannot add gesture recognizers to layers, so you need to add a gesture recognizer to its containing view, and then perform an additional test to see if the tap happens to overlap the layer in question.
Add tap gesture recognizer to the parent view of the layer (let's assume that it's called parentView), then add this code to the selector of your gesture recognizer:
- (void)handleTap:(UITapGestureRecognizer *)sender {
CGRect layerFrame = CGRectMake(16, 26, 153, 153);
CGPoint tapPoint = [sender locationInView:parentView];
if (CGRectContainsPoint(layerRect, tapPoint)) {
// The tap happened inside the rectangle of your layer
...
}
}

Also you can do hitTest: on a CALayer to check whether you are tapping on that layer.
Just check the apple documentation for hittest.

Related

Image view should not move outside the its superview using UIPangesture

I am using a UIPangesture to move a imageview and this imageview is subview of of view of class, when I move imageview then it move outside its superview. I want to set the boundary of moving this imageview, means the imageview should move only inside its superview.
i guess in the selector that is called by the pan gesture you are setting the view's center or origin accordingly to the point of the pan.
this is how your code should look in order to solve your problem:
- (void)thePanSelector:(id)sender{
UIPanGestureRecognizer *recognizer = (UIPanGestureRecognizer *)sender;
CGPoint p = [recognizer locationInView:theSuperView];
float boundedX = MAX(0,MIN(theSuperView.frame.size.width,p.x));
float boundedY = MAX(0,MIN(theSuperView.frame.size.height,p.y));
CGPoint boundedPoint = CGPointMake(boundedX,boundedY);
view.center = p;
}
this code is untested so you may need to play a little with the values of boundedX and boundedY

Detect tap touches on CALayer

My setup is as follows
- UIView
- CALayer (container)
-CAShapeLayer
-CAShapeLayer
-..
And i want to detect tap touches on every shapelayer to change its color
I have put a UITapGestureRecognizer on my UIView and have the following code
CGPoint point = [self tapWithPoint:[recognizer locationInView:pieView]];
PieSliceLayer* layerThatWasTapped = (PieSliceLayer *)[_containerLayer hitTest:point];
[(PieSliceLayer *)[layerThatWasTapped modelLayer] setFillColor:UIColor.redColor];
But it seems that it only changes 1 CAShapeLayer always the first that was added.

Custom shaped (inverted T) bordered Uiview in iOS

I have to create a custom shaped (inverted T) bordered Uiview on iOS. I am attaching the screenshot below. I have researched a lot and I found a way using UIBezierPath from here.
But I didn't get any idea to shape my view as inverted T shaped.
UIViews are always rectangular. From the documentation:
The UIView class defines a rectangular area on the screen and the interfaces for managing the content in that area.
Even though the view is limited to being rectangular, you can shape your active area in any way that you like. By combining that with a transparent background, you can imitate a view of any shape that you can draw.
When your rectangular view receives touches and other events, your event handlers should first check if the activity has happened in the inverted-T area. If the activity is outside, the event should be ignored.
Phew.. Finally I have done it. I have used two UiViews subclasses (top & bottom).
The main challenge I faced was about the border, because if I set the border to my two views (top & bottom), it will not show as a single container item. :)
Steps that I done:
Created two UiView subclasses. Lets call topView and bottomView.
TopView *topView = [[TopView alloc] initWithFrame:CGRectMake(220, 60, 200, 200)];
[topView setBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:topView];
BottomView *bottomView = [[BottomView alloc] initWithFrame:CGRectMake(130, 260, 380, 200)];
[bottomView setBackgroundColor:[UIColor yellowColor]];
bottomView.customShape = topView; //Set the custom shape as TopView to frame to draw the border.
[self.view addSubview:topView];
I have drawn three borders (top,right,left) for TopView and two full borders (bottom, right), two partial borders (top left, top right) for BottomView through overriding the drawRect method.
See my TopView class here.
See my BottomView class here.
Thanks to all.
Output:
It should be possible to create a view with a CAShapeLayer as layer.
Make a subclass of UIView and override the layerClass method:
+ (Class)layerClass {
return [CAShapeLayer class];
}
Then in the viewDidLoad you can specify the bezierPath to the shapeLayer:
- (void)viewDidLoad {
[(CAShapeLayer *)self.layer setPath:someBezierPath.CGPath];
[self.layer setBackgroundColor:[UIColor redColor].CGColor];
}

UIScrollView and detecting subview of tap gesture

I've added a TapGestureRecognizer to my self.view:
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(singleTap:)];
tap.numberOfTapsRequired = 1;
tap.numberOfTouchesRequired = 1;
[self.view addGestureRecognizer:tap];
[tap release];
The view contains a single UIScrollView with images and labels. I want to detect if the user taps on a label or not.
- (void)singleTap:(UIGestureRecognizer*)gestureRecognizer {
CGPoint pt = [gestureRecognizer locationInView:self.view];
UIView *v = [self.view hitTest:pt withEvent:nil];
if ([v isKindOfClass:[UILabel class]]) {
NSLog(#"label!");
return;
}
// else do other stuff if its not a label
However I don't see the label! in my log.
I think it's because userInteractionEnabled is by default NO on UILabels. Try turning that on.
EDIT: It was really a guess, but just to confirm, Apple docs on [UIView hitTest:withEvent:] state:
This method ignores view objects that are hidden, that have disabled user interaction, or have an alpha level less than 0.01.
Your subviews, such as the labels themself, actually hide the user interactions from the underlying view.
Why don't you add the gesture recognizers to your label(s).
Alternatively you may want to use UIButton for the labels.
Or -
if you do not want to determine which label has been touched, you may want to add an invisible view (an empty view, neither a hidden one nor one with alpha=0) on top of all labels and add the gesture recognizers to those.

How do i drag a button?

I have a UIButton that i'd like the user to be able to drag with TouchDragInside. How do i get the button to move as the user moves their finger?
As Jamie noted, a pan gesture recognizer is probably the way to go. The code would look something like what follows.
The button's view controller might add a gesture recognizer to the button (possibly in viewDidLoad) as follows:
UIPanGestureRecognizer *pangr = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(pan:)];
[myButton addGestureRecognizer:pangr];
[pangr release];
And, the view controller would have the following target method to handle the gesture:
- (void)pan:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateChanged ||
recognizer.state == UIGestureRecognizerStateEnded) {
UIView *draggedButton = recognizer.view;
CGPoint translation = [recognizer translationInView:self.view];
CGRect newButtonFrame = draggedButton.frame;
newButtonFrame.origin.x += translation.x;
newButtonFrame.origin.y += translation.y;
draggedButton.frame = newButtonFrame;
[recognizer setTranslation:CGPointZero inView:self.view];
}
}
CORRECTED as per rohan-patel's comment.
In the previously posted code , the x and y coordinate's of the origin of the button's frame were set directly. It was incorrect as: draggedButton.frame.origin.x += translation.x. A view's frame can be changed, but the frame's components cannot be changed directly.
You probably don't want to use TouchDragInside. That is a method of recognizing that a button or other control has been activated in a certain way. To move the button, you probably want to use a UIPanGestureRecognizer and then change the buttons position in its superview as the users finger moves around.
You have to implement these four methods, touchesBegan:withEvent:, touchesMoved:withEvent:, touchesEnded:withEvent:, and touchesCancelled:withEvent: in the view that holds the button. The property you are referring to cannot be used directly to drag any uiview