MapKit - How do I change my custom annotation view's tap "zone"? - ios

I just implemented a custom annotation view and I have a custom callout for it as well. Showing the callout ONLY works when I tap the very top-left corner of my custom annotation view (which is a rectangle). How can I fix it so that I can tap the center of my custom annotation view and it will show the callout ? It is very annoying to have to tap a specific corner of the custom annotation view just to see the callout appear.
I tried to create give my annotation view a centerOffSet value but it did not fix the problem at all... how do I make it so that tapping anywhere on the custom annotation view will bring up the callout view ?

Did you set your custom annotation view's frame correctly? Try set the frame to say CGRectMake(0, 0, 100, 100), and self.backgroundColor to [UIColor grayColor], I think the clickable area will be (100, 100) big shown as gray rectangle.

Related

Creating a transparent circle in overlay, around a view in superview

I have a UILabel added as a subview in a UIViewController.
I am adding subview (overlay view) view on UIViewController.view.
How to make a transparent circle in overlay view so that the UILabel is visible from transparent circle.
What I am able to do for now:
I am able to create a transparent circle with hardcoded coordinates.What I want is that I just pass UILabel and get a overlay with transparent circle around UILabel.
Any thoughts.
My source code here

MKMapView center not correct

I have an app where i'm creating a views hierarchy where i have a mapview and a tableview. The mapview is under the tableview and is visible on the top when the table vertical offset is negative.
The Structure of the view is something like this:
Where the yellow is the map, the green on the top is a navigation bar and green at the bottom is the tableview.
When you scroll the table view the map should show the user location at the center of the visible portion of the map.
The problem i'm experiencing is that when i apply the parallax the map center is not the location i'm setting.
This is a screenshot from a sample project that i did to isolate the problem. The center coordinate is Buckingham Palace.
The orange square is a debug view that is at the center of the mapView (where the center coordinate should be). I'm sure that the parallax effect it's correct.
The structure of my view hierarchy regarding the mapView in the sample project is represented in the following image. The position of the views reflects the screenshot above.
The following code is used to set the frame.origin.y value of the mapContainerView. I'm using the mapContainerView to avoid to touch the frame of the mapView to perform the parallax effect. The mapView is a subview of the mapContainerView (at the begin I was using a translation on the mapView but i changed the code to try to isolate the cause of this problem)
self.mapViewContainer.frame = CGRectMake(0, self.currentY, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame));
if (!CGRectEqualToRect(self.mapViewContainer.bounds, self.mapView.bounds)) {
self.mapView.bounds = CGRectMake(0,
0,
CGRectGetWidth(self.mapViewContainer.bounds),
CGRectGetHeight(self.mapViewContainer.bounds));
self.mapView.center = CGPointMake(CGRectGetMidX(self.mapViewContainer.bounds),
CGRectGetMidY(self.mapViewContainer.bounds));
}
self.squareView.bounds = CGRectMake(0, 0, 22.0f, 22.0f);
self.squareView.center = CGPointMake(CGRectGetMidX(self.mapViewContainer.bounds),
CGRectGetMidY(self.mapViewContainer.bounds));
My guess is that the status bar is doing something to the mapView. If you look to the simulator screenshot you can notice how the center coordinate are exactly located at the center of the vertical space that goes from the status bar to the bottom of the mapView.
If i set the center of the coordinate in the viewDidLoad, after the creation of the map (when it's frame is CGRectZero) the center of the map is correctly in the center of the map.
If i change it later (for example with a timer that, to simulate the location update, sets the same map region that it is set in the viewDidLoad) the map view decide to change the center as showed above.
I can't find any method to disable or change this behaviour. Am I doing something wrong here? I'm working on a workaround but i'm curious to know if someone know what i'm missing here.
This is the code of the sample project i created to reproduce the problem in an isolate scenario. https://gist.github.com/lucabartoletti/a5f103cb74a3edb178d6
Some restriction i have.
The map must be big enough to cover the window frame
The status bar must be visible
Try this:
_mapView.delegate = self;
func mapView(mapView: MKMapView!, didUpdateUserLocation
userLocation: MKUserLocation!) {
mapView.centerCoordinate = userLocation.location.coordinate
}

How to bring a subview's subview to top?

The following print screen shows my layout:
I have the main view , then a Top view and then a picture.
When I press on the picture, I want a semi transaprent black screen appearing on the entire view:
let scrennRect = UIScreen.mainScreen().bounds
let coverView = UIView(frame: scrennRect)
coverView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3)
self.view.addSubview(coverView)
But I want my picture to stay on top of the coverView ?
Is there a way I can bring only the picture to be in front of the coverView ?
The problem is that your coverView and imageView have different super views.
That's why you cannot bring the imageView to the front.
In order to bring the imageView to the front you need to move it outside of the Top View so your View contains the Top view and the imageView.
Then, you can add the coverView to the main view, and bring the imageView to the front.
Another solution:
Place an image view inside the coverView at the exact same position.
This should do your work. Any view maintains a stack of its subviews.
self.view.addSubView(blackTransparentView);
self.view.bringSubViewToFront(myImageView);

Create a draggable UIView on long press of a different view

I have implemented something that does the following:
I am showing a full-screen UICollectionView with different items. Underneath this view (out of sight) is a "detail" view for one of the items.
When a user long-presses one of the UICollectionView items, I would like to hide the UICollectionView to reveal the "detail" view behind.
I will then instantiate a new UIView which is hovering over this view and is draggable. The user can then drag and drop this new UIView into position on the "detail" screen.
The only part which I am having trouble with is the syncing of the long-press with the draggable view. I would like the user to long-press on the UICollectionView, and then be immediately dragging the draggable view.
How do I connect these two actions?
At the moment the UICollectionView calls a delegate on the lower view, which instantiates the draggable view:
- (void)contactAlgorithm:(ContactAlgorithmViewController *)contactFlowViewController didLongPressContact:(CDContact *)contact {
DraggableContactView *draggableView= [[DraggableContactView alloc] initWithContact:contact];
[self.view addSubview:draggableView.view];
}
But how do I make this draggable view the view which is being dragged by the long.press?
First get the frame of the item which was long pressed.
Add the draggable view at exactly that frame.
Now, add pan gesture recogniser to that view and set delegate of that gesture to viewController , and whenever move occurs delegate method will be called.
There change the frame of draggable view to follow touch.
Instead of adding pan gesture, you can use touchesMoved method of viewController.
CODE:
using below code, you can drag the view without using pan gesture.
//have a class property of DraggableContactView
#implementation ViewController{
DraggableContactView *dragableView;
}
Selector method of longPressGestureRecogniser
-(void)longPress:(UILongPressGestureRecognizer *)ges{
if(dragableView==nil){
dragableView=[[DraggableContactView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
dragableView.backgroundColor =[UIColor greenColor];
[self.view addSubview:dragableView];
}
CGPoint p =[ges locationInView:self.view];
[dragableView setCenter:p];
}

How to force an element in a view to be non-transparent when parent view has alpha set to translucent

I have a view that is slightly translucent, I set the alpha to about .75 and it contains a button as a sub element.
I want the button to be completely opaque and I set the opaque property in IB but still the button appears as translucent.
Any pointers?
Thanks!
A subview of a superview is allways minimum as transparent as its subview.
Subview alpha = 0.5 and superview alpha = 0.1 would result in an alpha of the subview of 0.05.
The only way of achieving that is changing the view hierarchy. Your subview must not be a subview any more. It may still be at the same position. (May require different position value).
An example.
Your background view is backgroundView
Your superview is firstView
Your subview is overlayView
Your current hierarchy is
backgroundView -> firstView -> overlayView
You should change that to:
backgroundView -> first View
\-> overlay View.
If your firstView's position is (10, 10) and your overlayView's position was (20,20) then change your overlayView's position to (30,30) because it now is within the coordinate system of background view.
For your code:
At some point you used to have
[backgroundView addSubView:firstView];
[fisrtView addSubView:overlayView];
change that to
[backgroundView addSubView:firstView];
[backgroundView addSubView:overlayView];
If you did not code that but defined it within IB then just move overlayView within the views tree accordingly so that it is on the same level as firstView.
Regardless whether you code it or draw it in IB, make sure that firstView comes first and overlayView comes next. Otherwise firstView could hide overlayView when its alpa is greater than 0.

Resources