contentInsetAdjustmentBehavior seems not act right for child UIControllerView 's UIScrollview - objective-c

i use WMPageController as my one of viewcontroller, as we know , on iphoneX, scrollview will by default has a safeArea which constrain your content view in center ,that is top with 44 status height and 44 normal navibar height and to the bottom with 49 normal tabbar height and 34 home indicator height. then your scrollview can automatically be changed it's contentInset when scroll to the bottom to guarantee bottom contents of the scrollview will not be covered by home indicator, but when i use wmpagecontroller, it needs some uiviewcontrollers to make is easy to change vc in a single viewcontroller, then every single viewcontroller i test the scrollview in it , it runs with no problem,but when set to the umpagecontroller, i mean those controllers i set to doesn't be recognized its scrollView's contentInsetAdjustmentBehavior properly, when i scroll to the bottom, the outside vc(wmpagecontroller)'s home indicator is on my table cell's contents.
it‘s not normal , when i release my finger, the scroll indicator just clipped by the right bottom round corner ☹️
when it's normal it should look like this.....👍
who knows how to handle this situation ?

It's hard to tell from your description/screenshot if the content inset on your tableview is correct. If it is, you can adjust the scroll indicator insets in viewDidLayoutSubviews():
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.scrollIndicatorInsets = tableView.contentInset
}
Additionally, you adjust the tableView.contentInset before tableView.scrollIndicatorInsets as needed.

Related

How to calculate the correct location of a vertical NSRulerMarker?

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.

Sub View with 50% height of the space left between navigation bar & tabbar

I don't want to do this programatically. Please show me the storyboard way to achieve this.
I want orang view to of half size of the space between nav-bar & tabbar. Refere dashed rect, I want half of that rect.
There are a couple of ways to approach this that I can think of.
Use a container view
The first is to add a UIView to the superView to act as a container. You can "pin" this container view to the bottom of the navigation bar and the top of the tab bar.
Now add your orange view to this container. With constraints pinning it to the top, left and right. You can then give it equal height with the container and a 0.5 multiplier and it will have half the height between the nav bar and tab bar.
Use a "spacer" view
The other method is to use a spacer view. Add your orange view and then add another view beneath it. Pin them to the nav bar and tab bar respectively and give them a vertical spacing of 0 between them.
Now give them equal heights.
This will make them both take up half the space between the nav bar and the tab bar.
Now make the "spacer view" hidden. It will hide but the constraints will still work.
Both of these will work for any device size and any orientation. Also, for edge cases like if satnav guidance or an incoming call changes the height of the nav bar etc...
As #Fogmeister mentioned You can use spacer view
Pin both of them and make their heights Equal Height.
And set blue view Hidden.
Very easy, add the following constraints.
Left and right constraints pinning the view to the superview.
Top constraint pinning view to superview with a constant of 64 to offset the nav bar.
Equal heights constraint with the superview. Change the multiplier of this constraint to 0.5 and the constant to -54 (half of the 64pt nav bar + status bar and half of the 44pt tab bar) and update frames.
Job done. :)

iOS7 - Get UIView's useful height (excluding statusBar, navigationBar and tabBar)

Introduction
This is a rather common question, however I have certain extra points to observe. One of them is that I don't want to make my bars opaque. I like the iOS7 translucent bars.
I have an UIImageView inside a UIScrollView, and I'm trying to set the initial scrollView.zoomScale to fit the image in the screen just like the stock Photos app does. That means: the image should not be cropped and should fill the screen as much as possible.
However for my app this is a bit more complicated as I have visible statusBar, navigationBar and tabBar. I will adopt the solution to hide them until the user touches the screen, but I'm still curious for a solution when hiding is not desirable.
Done so far
I'm currently calculating the zoom based on a relation between the image's height and the view's height:
double heightRelation = self.image.size.height / self.view.frame.size.height;
After applying 1/heightRelation to the scrollView.zoomScale, the image is still bigger than the useful space. Then I found the iOS7 default heights for statusBar (20pt), tabBar (49pt) and navigationBar (44pt) from the documentation and also from:
NSLog(#"status : %f", CGRectGetHeight([[UIApplication sharedApplication] statusBarFrame]));
NSLog(#"tab : %f", self.tabBarController.tabBar.frame.size.height);
NSLog(#"nav : %f", self.navigationController.navigationBar.frame.size.height);
... and after playing a little, I found that the exact combination would be to subtract statusBar and navBar heights from the view's height:
double heightRelation = self.image.size.height / (self.view.frame.size.height - CGRectGetHeight([[UIApplication sharedApplication] statusBarFrame]) - self.navigationController.navigationBar.frame.size.height);
This works great for the Portrait mode, but doesn't for Landscape. I know I could also make a condition to set the zoom according to the orientation but... The code is probably getting unnecessarily ugly.
So I ask you: what's the best method to get the useful height?
P.S.: Interface Builder's option "Adjust Scroll View Insets" has no effect.
Don't use the bars directly. Use the length properties of bottomLayoutGuide and topLayoutGuide of the view controller to determine how much of the view is "wasted" under the bars. These take into account navigation bars, toolbars, status bar, tab bars, etc., and are maintained by the system when the bars are resized (for example, after rotation to landscape on phone/pod idioms).

How to set ContentSize of a UIScrollView which is a sub-view?

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.

How do I resize a UIScrollView so that it's not 100% of the parent UIView?

I've built an app using the UITabBar template. I have a few tabbar items, one item displays a view. That view has a UIScrollView element that has paging enabled to mimic the behaviour of the iPhone springboard i.e. pages that can be scrolled left to right.
I'm trying to drop in a UIPageControl, so I've resize the UIScrollView so that it's slightly shorter than the parent UIView height and have placed a UIPageControl below it.
When I run the app the UIScrollView is always 100% of the height of the parent UIView and I can't see the UIPageControl.
I've got the following code in my viewDidLoad method of the view controller for the tab:
UIScrollView *tempScrollView=(UIScrollView *)self.view;
tempScrollView.contentSize=CGSizeMake(640,377);
This sets the content size ok and I can scroll left to right. I've tried adding:
tempScrollView.frame=CGRectMake(0, 0, 640, 377);
To to resize the scroll view but it still shows 100%. See diagram below showing the issue:
I think you shouldn't resize the frame to 640, 377 because it would make the paging stop working, once the contentSize would be the same as the frame size.
One solution would be to set the desired frame size in the interface builder (like the left most figure) and set proper autosizing masks. I gues what you are looking for is the configuration below
To check if the changes are working, I would use a uiscrollview of height visibly smaller, just to make sure the behaviour is the desired.
If you want your view to scroll you need to change the tempScrollView.contentSize to be bigger than tempScrollView.frame
If you do this:
CGFloat contentWidth = tempScrollView.frame.size.width*2;
tempScrollView.contentSize=CGSizeMake(contentWidth,377);
You will have 2 pages.
You need to activate paging too with:
[tempScrollView setPagingEnabled:TRUE];