NSScrollView clipping overlaid UI elements - objective-c

I have a button that sits on top of an NSScrollView, not within. When the scrollview scrolls, the button get's clipped with part of the button going along with the scrolling and the other part staying positioned.
To better describe the issue here's a video of the issue:
http://dl.dropbox.com/u/170068/ScrollTest.mov
The planned goal was to have a button sit in the top right corner of a text view but stay there when the text view scrolls. So if anyone has any thoughts on how to achieve this it would be greatly appreciated.

You should subclass NSScrollView and override "tile" method to position sub-controls of the scroll view.
- (void)tile
{
[super tile];
if (subControl)
{
NSRect subControlFrame = [subControl frame];
// adjust control position here in the scrollview coordinate space
// move controls
[subControl setFrame:subControlFrame];
}
}
I have used this way to implement a custom ScrollView with zoom control and background color selector embedded.

Overlapping views isn't recommended for non-layer-backed views. I think Interface Builder will even warn you about this. The easiest way to work around this would be to make your button layer-backed.

Related

Scrolling a NSScrollView not working

I'm trying to scroll an NSScrollView to the bottom of the view using this code:
NSPoint newScrollOrigin;
if ([[self.chatScreen documentView] isFlipped]) {
newScrollOrigin=NSMakePoint(0.0,NSMaxY([[self.chatScreen documentView] frame])-NSHeight([[self.chatScreen contentView] bounds]));
} else {
newScrollOrigin=NSMakePoint(0.0,0.0);
}
self.chatScreen.backgroundColor=[NSColor redColor];
[[self.chatScreen documentView] scrollPoint:newScrollOrigin];
which came from here: Apple doucmentation on scrolling
When I run my program, it partially scrolls to the bottom of the view, where the screen shows the top of the view (default starting position) but when I attempt to scroll, it jumps to the bottom of the page, where I can then scroll normally.
If I scroll around to any part of the view, the next time it receives an update (which triggers it to jump back to the bottom) it looks like nothing happened, until you try to scroll, which again causes it to jump back to the bottom of the page.
Thanks in advance.
You need to scroll the clip view and not the document view.
The document view fills out the entire scroll view and the clip view is kind of an overlay which scrolls around deciding which parts are visible.
[[self.chatScreen contentView] scrollToPoint:newScrollOrigin];
Notice the scrollToPoint instead of NSView's layer backed scrollPoint
After you scroll a NSClipView its always good practice to reflectScrolledClipView so that the scrollers update.
- (void)reflectScrolledClipView:(NSClipView *)aClipView;

Setting UIScrollView's origin for pinch gestures

I'm creating a scroll view for displaying a very large view, and I need both scroll and zoom functionality (just like an image viewer). Here are the steps that I've taken:
In interface builder, I've put a scroll viewer to the view controller.
I've added a pinch gesture recognizer to the scroll viewer.
I've connected the gesture recognizer's action to the code to handle the gesture events.
When the view controller is loaded, I change my view's origin to the center (viewer is my scroll viewer): self.viewer.contentOffset = CGPointMake(384, 512);
In my code for the handler, I handled the event as such:
(startScale is 1.0 in the beginning)
- (IBAction)handlePinch:(UIPinchGestureRecognizer *)sender {
if(sender.state == UIGestureRecognizerStateEnded){
startScale *= sender.scale;
}else{
float result = sender.scale * startScale;
self.viewer.transform = CGAffineTransformMakeScale(result, result);
}
}
When I run the app, the gesture is recognized and scaling works correctly, however, the whole view scales with respect to the 0,0 point of the screen (top left). I want it to scale with respect to the middle point that I'm applying the gesture, just as a natural pinch gesture for zooming into a photo.
I've also tried setting self.viewer.frame's origin, but nothing changed. I've searched about the problem and found these:
How to set a UIView's origin reference? (already tried)
https://stackoverflow.com/questions/13163279/pinch-punch-gestures-center (about my problem, but unanswered)
UIPinchGestureRecognizer for zooming and panning an image in xcode (looks like an overkill, too complicated for me, and I'm not sure if this would really help my situation)
How can I achieve natural pinching with my scroll view, what am I doing wrong?
Thanks,
Can.
Well, the answer to the problem is very simple: Remove the pinch gesture altogether. The benefit of using a UIScrollView is that it handles the panning/zooming internally, and you have to do nothing
Edit: To make sure the content is scaled properly, you are going to need a UIView (called contentView or whatever you want) where you put all the content, and then on the delegate method of your UIScrollView do this:
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
return contentView;
}
This should solve your problem
Edit 2: Also remember to set the minimum / maximum zoom scales for your UIScrollView

Starting Position of NSSplitView divider

How can I set the start position of a NSSplitView?
The closest thing I've found that looks like it would work is setPosition
//Set splitView position.
[splitView setPosition:330 ofDividerAtIndex:0];
This doesn't seem to do anything though, my splitview still starts with the divider in the center.
ANy ideas?
You don't set the position of the divider, you set the sizes of your NSSplitView's subviews. The divider is then repositioned automatically.
This is how I positioned my divider and subview size (in swift):
let subview: NSView = mySplitView.subviews[1] as NSView
subview.setFrameSize(NSMakeSize(subview.frame.size.width, 100))
In the view's class housing the split view
override func viewWillAppear() {
self.mySplitView.setPosition(120, ofDividerAtIndex: 0)
}
or wherever you want it to start.
NSSplitView needs initial non-sized bounds to make them layout correctly.
If your view has zero-size, then it will not show expected layout.
The best way is providing non-zero layout (this is what IB does), but sometimes this is impossible.
If you cannot provide non-zero size, then I think you have to provide proper - (void)splitView:(NSSplitView *)splitView resizeSubviewsWithOldSize:(NSSize)oldSize delegate method implementation to layout everything manually yourself. (this is my current best practice)
Maybe that is the center? If splitView is correctly hooked up to your split view, that code should work. You should probably log [splitView minPossiblePositionOfDividerAtIndex:0] and [splitView maxPossiblePositionOfDividerAtIndex:0] before trying to set the position of the divider so you know the possible values.

How to control nested scrollviews

In my iphone application I want to use 2 scrollviews and they have some images inside. Well, my question is when I scroll vertically on my first scrollview I want to explore the content of it however when I scroll horizontally I want to move to my second scrollview. I hope I explained clearly.
Well, I tried to use 3 scrollviews first of them located on the background, others are located on the first scrollview but I can only control the background scrollview or the others at once.
Is there a way to control first one horizontally and the others vertically.sorry for my english, hope it makes sense.
I have two recommendations.
1) Scrollviews can scroll horizontally and vertically - so you dont need two of them if you have content in a vertical direction and content in a horizontal direction. You can use one.
2) If for some reason you really do need 2, then you can detect a horizontal swipe by subclassing UIScrollView and switch to the other.
Remember that a UIScrollView will scroll in any direction that exceeds its contentSize. So all you need to do in the first case (1) is take the view that is inside say scrollview 2 (the horizontal scrollview) and put that view in the scroll view to the left or the right outside of the scrollviews viewport when the user scrolls they will see that view and can of course scroll vertically there as well.
If you use method 2 - make sure that the content size of scrollview one is at leat a few pixels more wide than the content size so that you can detect a horizontal swipe then invoke the coe to switch to your other scroll view. If you dont subclass UIScrollview to get the swipe you probably wont get the event. So do that add a little to the width of that view and then look for a value less than the left edge of the scroll view and switch to the other scroll view. You can do the same in reverse to go back to the previous scrollview.
I hope this helps - sorry no code at the moment, but I do have code working on iOS and OSX that does this.
You can distinguish both UIScrollView via if statement
Set delegate of both UIScrollView
Then compare your scrollView in its delegate method. You can change your delegate method according to your requirement -
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
if(firstScrollView == scrollView)
{
//Do your work for firstScrollView
}
if(secondScrollView == scrollView)
{
//Do your work for secondScrollView
}
}
try to do in delegates methords
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
set some conditions like
if(myScroll1)
{
//scroll vatical.
}
if(myScroll2)
{
//scroll horizontal.
}
this is not complete code this is an idea Best of luck..

How to use NSScrollview?

I can't figure out how to actually use NSScrollview. I dragged the scroll view object onto an NSWindow in the interface builder. I then dragged some NSButtons onto the scroll view. My question is:
How do I actually make it scroll down, for example, 2x the original height?
Of course the user can scroll automatically using their UI. I assume what you want to do is to scroll programmatically.
A bit of background: An NSScrollView has a documentView, which is the underlying view that the scroll view shows a part of, and a clipView, which is the view that is shown on the screen. So the clip view is like a window into the document view. To scroll programmatically you tell the document view to scroll itself in the clip view.
You have two options on how to scroll programmatically:
- (void)scrollPoint:(NSPoint)aPoint –– This scrolls the document so the given point is at the origin of the clip view that encloses it.
- (BOOL)scrollRectToVisible:(NSRect)aRect –– This scrolls the document the minimum distance so the entire rectangle is visible. Note: This may not need to scroll at all in which case it returns NO.
So, for example, here is an example from Apple's Scroll View Programming Guide on how to scroll to the bottom of the document view. Assuming you have an IBOutlet called scrollView connected up to the NSScrollView in your nib file you can do the following:
- (void)scrollToBottom
{
NSPoint newScrollOrigin;
if ([[scrollview documentView] isFlipped]) {
newScrollOrigin = NSMakePoint(0.0,NSMaxY([[scrollview documentView] frame])
-NSHeight([[scrollview contentView] bounds]));
} else {
newScrollOrigin = NSMakePoint(0.0,0.0);
}
[[scrollview documentView] scrollPoint:newScrollOrigin];
}