1
votes

I have a requirement as shown below to show a "speech bubble" on a zoomable+dragable image below.

The Speech bubble should NOT BE resizable or dragable and should keep pointing at the right place when the below image gets resized or dragged.

I am able to place the speech bubble at the right place initially. But I'm not able to get it to stay at the right place when dragging or zooming.

I've tried with doing calculations and placing it at the right place during "scrollviewenddragging" etc. but nothing works perfect. One of the main issues Iam seeing is that the floating view location "resets" to the storyboard x,y location during the second pass of "scrollviewdidscroll".

enter image description here

What is the best way to handle this. Any pointers ?

2
Are you using auto layout to place the bubble the first time? - Catalina T.
the first time its hidden and I;'m guessing laid out as per storyboard x,y. howver when its made visible I'm setting the frame for it with the correct origin-x,y values and then showing it. - user3034970

2 Answers

0
votes

You could try something like this:

Subscribe yourself as observer for the contentSize of the scrollView (in your init method, or viewDidLoad, depending on your project setup)

[self.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionInitial context:nil];

Then update the frame of the bubble in the observeValueForKeyPath method:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    CGRect bubbleFrame = self.bubble.frame;
    bubbleFrame.origin.y += self.scrollView.contentOffset.y;
    bubbleFrame.origin.x += self.scrollView.contentOffset.x;
    [self.bubble setFrame:bubbleFrame];
}

And don't forget to remove the observer:

- (void)dealloc {
    [self.scrollView removeObserver:self forKeyPath:@"contentSize"];
}

This should make the bubble keep pointing in the same place as you scroll.

Let me know if it worked out!

0
votes

Ok, there is more than one way to do this. (1) You could add the bubble view to your scrollview. It's position will remain anchored but will need to be resized when zooming occurs. Do this in the scrollView delegate method - scrollViewDidZoom when zooming occurs. (2) You could not add it to the scrollView but instead add it to say your ViewController's view (after the scrollView was added to the VC's view). Then you will not need to resize the bubble view but you will need to reposition it in the scrollView delegate - scrollViewDidScroll method when scrolling occurs.

Either way, the scrollView.zoomScale property is the link to the new size or position of your bubble view.

I'll describe method 2 above. First position the bubble view in the VC's view. Decide on an anchor point for the bubble view, i.e. where you want to place it in relation to the scrollView. I will pick a point (for the bubble view's center) from a point in the scrollView, say (500, 200) and map it to a point in my VC's view.

So in the VC's viewWillAppear method I'll put

CGPoint p = [self.view convertpoint:CGPointMake(500*self.scrollView.zoomScale, 200*self.scrollView.zoomScale) fromView:self.scrollView];
self.bubbleView.center = p;

Assuming I start of with a zoomScale of 1.0f when viewDidLoad occurs, this will correspond to the point (500, 200) in the scrollView.

Now we just want to maintain that relationship between the bubble view's center position when scrolling occurs.

- (void)scrollviewDidScroll:(UIScrollView *)scrollView 
{
CGPoint p = [self.view convertpoint:CGPointMake(500*self.scrollView.zoomScale, 200*self.scrollView.zoomScale) fromView:self.scrollView];
self.bubbleView.center = p;
}