diff --git a/README.md b/README.md index 64d11e5..96132b7 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Easily create a map screen, complete with annotations. class MyMapScreen < PM::MapScreen title "My Map" start_position latitude: 35.090648651123, longitude: -82.965972900391, radius: 4 + tap_to_add def annotation_data [{ @@ -235,6 +236,75 @@ end `radius` is the zoom level of the map in miles (default: 10). +#### tap_to_add(length: Float, target: Object, action: Selector, annotation: Hash) + +Lets a user long press the map to drop an annotation where they pressed. + +##### Default values: + +You can override any of these values. The `annotation` parameter can take any options specified in the annotation documentation above except `:latitude`, `:longitude`, and `:coordinate`. + +```ruby +length: 2.0, +target: self, +action: "gesture_drop_pin:", +annotation: { + title: "Dropped Pin", + animates_drop: true +} +``` + +##### Notifications + +This feature posts two different `NSNotificationCenter` notifications: + +**ProMotionMapWillAddPin:** Fired the moment the long press gesture is recognized, before the pin is added. + +**ProMotionMapAddedPin:** Fired after the pin has been added to the map. + +##### Example: + +```ruby +# Simple Example +class MyMapScreen < PM::MapScreen + title "My Map Screen" + tap_to_add length: 1.5 + def annotations + [] + end +end +``` + +```ruby +# A More Complex Example +class MyMapScreen < PM::MapScreen + title "My Map Screen" + tap_to_add length: 1.5, annotation: {animates_drop: true, title: "A Cool New Pin"} + def annotations + [] + end + + def will_appear + NSNotificationCenter.defaultCenter.addObserver(self, selector:"pin_adding:") , name:"ProMotionMapWillAddPin", object:nil) + NSNotificationCenter.defaultCenter.addObserver(self, selector:"pin_added:") , name:"ProMotionMapAddedPin", object:nil) + end + + def will_disappear + NSNotificationCenter.defaultCenter.removeObserver(self) + end + + def pin_adding(notification) + # We only want one pin on the map at a time + clear_annotations + end + + def pin_added(notification) + # Once the pin is dropped we want to select it + select_annotation_at(0) + end +end +``` + --- ### CocoaTouch Property Convenience Methods diff --git a/app/test_screens/test_map_screen.rb b/app/test_screens/test_map_screen.rb index 89e3b37..a114025 100644 --- a/app/test_screens/test_map_screen.rb +++ b/app/test_screens/test_map_screen.rb @@ -3,6 +3,7 @@ class TestMapScreen < PM::MapScreen start_position latitude: 35.090648651123, longitude: -82.965972900391, radius: 4 title "Gorges State Park, NC" + tap_to_add length: 1.5, annotation: {animates_drop: false, title: "A new park?"} def on_load @action_called = false diff --git a/lib/ProMotion/map/map_screen_module.rb b/lib/ProMotion/map/map_screen_module.rb index ba0d80b..07dd63b 100644 --- a/lib/ProMotion/map/map_screen_module.rb +++ b/lib/ProMotion/map/map_screen_module.rb @@ -9,6 +9,7 @@ def screen_setup check_annotation_data @promotion_annotation_data = [] set_up_start_position + set_up_tap_to_add end def view_will_appear(animated) @@ -160,9 +161,11 @@ def annotation_view(map_view, annotation) end def set_start_position(params={}) - params[:latitude] ||= 37.331789 - params[:longitude] ||= -122.029620 - params[:radius] ||= 10 + params = { + latitude: 37.331789, + longitude: -122.029620, + radius: 10 + }.merge(params) meters_per_mile = 1609.344 @@ -177,6 +180,42 @@ def set_up_start_position end end + def set_tap_to_add(params={}) + params = { + length: 2.0, + target: self, + action: "gesture_drop_pin:", + annotation: { + title: "Dropped Pin", + animates_drop: true + } + }.merge(params) + @tap_to_add_annotation_params = params[:annotation] + + lpgr = UILongPressGestureRecognizer.alloc.initWithTarget(params[:target], action:params[:action]) + lpgr.minimumPressDuration = params[:length] + self.view.addGestureRecognizer(lpgr) + end + + def gesture_drop_pin(gesture_recognizer) + if gesture_recognizer.state == UIGestureRecognizerStateBegan + NSNotificationCenter.defaultCenter.postNotificationName("ProMotionMapWillAddPin", object:nil) + touch_point = gesture_recognizer.locationInView(self.view) + touch_map_coordinate = self.view.convertPoint(touch_point, toCoordinateFromView:self.view) + + add_annotation({ + coordinate: touch_map_coordinate + }.merge(@tap_to_add_annotation_params)) + NSNotificationCenter.defaultCenter.postNotificationName("ProMotionMapAddedPin", object:@promotion_annotation_data.last) + end + end + + def set_up_tap_to_add + if self.class.respond_to?(:get_tap_to_add) && self.class.get_tap_to_add + self.set_tap_to_add self.class.get_tap_to_add_params + end + end + # TODO: Why is this so complex? def zoom_to_fit_annotations(args={}) # Preserve backwards compatibility @@ -288,6 +327,7 @@ def type=(type) end module MapClassMethods + # Start Position def start_position(params={}) @start_position_params = params @start_position = true @@ -300,6 +340,22 @@ def get_start_position_params def get_start_position @start_position ||= false end + + # Tap to drop pin + def tap_to_add(params={}) + @tap_to_add_params = params + @tap_to_add = true + end + + def get_tap_to_add_params + @tap_to_add_params ||= nil + end + + def get_tap_to_add + @tap_to_add ||= false + end + + end def self.included(base) base.extend(MapClassMethods) @@ -313,6 +369,5 @@ def location_manager @location_manager end - end end diff --git a/spec/func_map_screen_spec.rb b/spec/func_map_screen_spec.rb index 730cee0..70c4ce3 100644 --- a/spec/func_map_screen_spec.rb +++ b/spec/func_map_screen_spec.rb @@ -35,7 +35,7 @@ def add_image_annotation map_screen.navigationController.should.be.kind_of(UINavigationController) end - it "should have the map properly centered" do + it "should start the map in the correct location" do center_coordinate = map_screen.center center_coordinate.latitude.should.be.close 35.090648651123, 0.02 center_coordinate.longitude.should.be.close -82.965972900391, 0.02