I would like to make a side-scrolling object that is only 200 pixels wide and 50 pixels tall. This side-scrolling object would contain five different objects that, when scrolled into the middle, act as if selected. How could I go about doing this?
I want sort of the same effect that the iPhone home screen has where it latches on to a page when you slide it. Instead of latching on to the pages though, I want it to latch on to my five different objects.
The side-scrolling behavior is achieved with a UIScrollView with pagingEnabled set to YES. Set the scroll view's width to the size of your pages. Your scroll view delegate can calculate which object is on screen by dividing contentOffset.x by the scroll view's width.
If you want to show several items on the screen at once but still page between the individual items--think of the way the iWork apps show multiple documents, for example--there are three steps involved:
Set the scroll view's width to the width of the objects, not the width of the screen.
Set the scroll view's clipsToBounds property to NO so it displays the objects that aren't within the scroll view's frame.
Subclass UIScrollView and override -pointInside:withEvent: to return YES if the point is within the area you want to respond to touches within. (For example, if you want to respond to touches within the entire width of the screen, just ignore x and make sure y is between the top and bottom of the view.) Use this subclass instead of a standard UIScrollView.
Related
What is the correct formula for the location of an NSRulerMarker on a vertical NSRulerView, if the client view is flipped?
The situation: I have a view (let's call it the "main view") that is embedded in an NSScrollView with rulers, and it has subviews. The user can drag these subviews around, and while dragging, I want to indicate the current position on the rulers.
The main view is flipped: The zero point is top-left.
The horizontal position is pretty simple:
NSPoint scroll = myScrollView.documentVisibleRect.origin;
NSRect rect = mySubView.frame;
rulerMarkerDragLeft.markerLocation = rect.origin.x - scroll.x;
However the same method for the vertical position...
rulerMarkerDragTop.markerLocation = rect.origin.y - scroll.y;
does not work. The marker is only in the correct position when the scrollview has been scrolled down to the extreme bottom. For every n points scrolled back up, the marker location is n points too high. This is independent of the main view's size or the size of the visible area.
I can't seem to wrap my head around this problem; I guess there is a value I need to subtract from my result that expresses how far up the scrollview has been scrolled (or rather, how much further it can be scrolled down), but I don't think I can derive that value from myScrollView.documentVisibleRect...?
I may have overlooked something simple, but I can't find the solution.
Edit 2022-11-02 17:17 CET: Found the problem. I had set the NSRulerViews clientView to the contentView of the window. I am now setting it to the "main view" (ie. the view inside the scroll view), and now it works "automagically": I just set the marker locations to the subviews frame, no correction for scroll position or anything else needed.
The solution was simple: the ruler views' clientView needs to be set to the view that is inside the scroll view, not the main content view of the window.
The positioning of the ruler markers is now very straightforward: you just use the local coordinates inside the view, ie. the subviews' frame values.
No correction for scroll position, view height or such necessary.
My mistake was assigning the window's main content view as the rulers' clientView.
This seems like it should be simple...
I have a basic NSTableView in a window. The window is arbitrarily resizable (width + height). The tableview is pinned to the edges of the window and it has a single column that contains view-based table rows. The table rows have content pinned to the left and right edges of the cells, so as you resize the width of the window, you are effectively adjusting how much white space is in the middle of the cell.
I'm now trying to implement printing for this tableview. When I set up the NSPrintOperation, I'm passing my tableview subclass as the view to print. My desired result is this: I want the width of the tableview to be resized to the width of the page (regardless of how wide the window is right now on screen). I don't want to adjust the scaling factor (because that affects width + height) - I simply want the result to be as if I manually resized my window to exactly match the width of a printed page and then hit "print".
I've tried setting horizontalPagination to .fitPagination - but the problem there is that seems to apply a scaling factor to the width + height (which means if the window is currently "very wide", it makes the row height really small as it compensates for the width).
I've tried overriding adjustPageWidthNew:left:right:limit: in my tableview subclass - but that never gets called.
I suppose I could create a duplicate tableview and re-set it up exactly like the one I have on screen, but that feels like overkill when the view I want is already good to go - I just need to temporarily resize the width while I'm printing.
Any ideas?
I have an iPad app using Storyboards. I have one scene with a UIView, which has an additional UIView on the top half (which I draw on), and a UIScrollView on the bottom half (I needed to keeep them separate). I'm having a hard time figuring out how to address the UIView with this code that I copied from another SO question:
CGFloat scrollViewHeight = 0.0f;
for (UIView* view in scrollView.subviews)
{
scrollViewHeight += view.frame.size.height;
}
[scrollView setContentSize:(CGSizeMake(320, scrollViewHeight))];
The way I read the code above, I'm supposed to use the UIView, but that doesn't make sense, since the UIView covers the entire "scene/window". It makes more sense to me to use the UIScrollView to calculate the ContentSize.
So, what am I supposed to use?
Not completely clear on what you are asking. Once you have a reference to the scroll view, either through tags, properties or some other method, you should set its content size to the width and height of all of its content combined (accounting for overlap, etc). Ex. if you had a single image view that was 600 by 900 points inside the scroll view, you'd set its size to a 600 by 900 CGSize.
That goes through all of the subviews of the scroll view using a for...in loop (aka fast enumeration), adding their heights together, then uses that as the height of the content. I don't think that would be a good way to do it, because that assumes that all the subviews are stacked vertically on top of one another perfectly. It's basically going, "For every subview of my scroll view, add their height to this total and then use that as the content size's height."
The easiest way to manage scroll views is to slap all the content into one UIView, place that in the scroll view, then set the scroll view's content size to the frame of the UIView. If you need a reference to the UIView contained in the scroll view, you can set it to a property or give it a tag and use viewWithTag.
I've read a lot of documentation but still don't really understand how that UIScrollView works.
I have an example where I use an UINavigationViewController with the status bar (little top bar with wifi, battery, etc., icons) and a navigation bar (with the "back" button).
As the first subview of the UINavigatioViewController's main view I have a UIScrollView. Inside it I have created several subviews that make it's contents size to be 500 points.
In the "viewDidLoad" method I set the scroll view's "contentSize" equals to 500. But it doens't completely scroll down to show the last subview.
I read that I should add some points to the "contentInset" because of the "bars". I don't really know why. Isn't the scroll view inside the main view that is correctly framed? Why does it need to take the "bars" into account?
Anyway, I read that it should be like 64 points (44 navigation bar + 20 status bar). But it doesn't work.
The "magic" number (at least for me) is 84 points. I must add that quantity to the content size (584) or use it as:
self.scrollView.contentInset=UIEdgeInsetsMake(0.0,0.0,84.0,0.0); // AT THE BOTTOM!!
I'm really confused about this. Could anyone give a hand on understanding it?
Thanks.
self.scrollView.contentInset=UIEdgeInsetsMake(0.0,0.0,84.0,0.0);
UPDATE
I have seen that because I made my ScrollView size bigger in Interface Builder in order to add new elements beyond the normal small visible size, it had a "frame" size near to 500 points.
I set it frame size to 416 (just to fit and cover all the visible space) and now with a content size of 500 points (without any additional inset values) it scrolls perfectly.
But I still don't understand the previous behavior...
Right now, I have a UIScrollView which scales its UIView contents on zoom events. When I hit a certain zoomScale threshold, I want to be able to toggle on and off extra information within the UIViews. Right now, I am simply setting the hidden flag to YES/NO to accomplish this.
However, a problem occurs while attempting to get the bounds of the UIView. The bounds always returns a width and height that extends to include the invisible content.
Is there a way to limit the bounds to only return the size of visible content within a UIView?
You could derive new bounds as you zoom and not rely on the view's automatic bounds adjusting.
OR
If it doesn't make your code too complicated, I would remove those subviews from your resizing view instead of just hiding them.