FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(ios): resize of scrollview content breaks layout (#6965) · NativeScript/NativeScript@a9d2043 · GitHub

Commit a9d2043

Browse files
authored
fix(ios): resize of scrollview content breaks layout (#6965)
1 parent 1ab3963 commit a9d2043

5 files changed

Lines changed: 100 additions & 27 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Observable } from "tns-core-modules/data/observable";
2+
import { ScrollView } from "tns-core-modules/ui/scroll-view";
3+
4+
export class LayoutOutsideScrollViewModel extends Observable {
5+
content: string = "Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium," +
6+
"totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo. " +
7+
"Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos " +
8+
"qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, " +
9+
"adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem. " +
10+
"Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? " +
11+
"Quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae consequatur, " +
12+
"vel illum qui dolorem eum fugiat quo voluptas nulla pariatur?";
13+
isVisible: boolean = true;
14+
15+
onChangeVisibility() {
16+
this.isVisible = !this.isVisible;
17+
this.notifyPropertyChange("isVisible", this.isVisible);
18+
}
19+
20+
onScrollToBottom(args) {
21+
const scrollView = <ScrollView>args.object.page.getViewById("scroll-view");
22+
scrollView.scrollToVerticalOffset(scrollView.scrollableHeight, false);
23+
}
24+
25+
onScrollToTop(args) {
26+
const scrollView = <ScrollView>args.object.page.getViewById("scroll-view");
27+
scrollView.scrollToVerticalOffset(0, false);
28+
}
29+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { EventData as ObservableEventData } from "tns-core-modules/data/observable";
2+
import { Page } from "tns-core-modules/ui/page";
3+
import { LayoutOutsideScrollViewModel } from "./layout-outside-scroll-view-model";
4+
5+
var viewModel = new LayoutOutsideScrollViewModel();
6+
7+
export function pageLoaded(args: ObservableEventData) {
8+
var page = <Page>args.object;
9+
10+
page.bindingContext = viewModel;
11+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="pageLoaded" class="page">
2+
<ScrollView id="scroll-view">
3+
<StackLayout>
4+
<GridLayout rows="auto, auto, auto" backgroundColor="lightgray">
5+
<Button row="0" text="Change w/ Visibility" tap="{{ onChangeVisibility }}"></Button>
6+
<Button row="1" text="Scroll To Bottom" tap="{{ onScrollToBottom }}"></Button>
7+
<Label row="2" visibility="{{ isVisible ? 'visible' : 'collapsed' }}" text="{{ content }}" color="black"></Label>
8+
</GridLayout>
9+
10+
<GridLayout height="2000" backgroundColor="yellow"></GridLayout>
11+
12+
<GridLayout rows="auto, auto, auto" backgroundColor="lightgray">
13+
<Button row="0" text="Change w/ Visibility" tap="{{ onChangeVisibility }}"></Button>
14+
<Button row="1" text="Scroll To Top" tap="{{ onScrollToTop }}"></Button>
15+
<Label row="2" visibility="{{ isVisible ? 'visible' : 'collapsed' }}" text="{{ content }}" color="black"></Label>
16+
</GridLayout>
17+
</StackLayout>
18+
</ScrollView>
19+
</Page>

‎apps/app/ui-tests-app/scroll-view/main-page.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,6 @@ export function loadExamples() {
1616
examples.set("safe-area-sub-element", "scroll-view/safe-area-sub-element");
1717
examples.set("safe-area-images", "scroll-view/safe-area-images");
1818
examples.set("safe-area-images-overflow", "scroll-view/safe-area-images-overflow");
19+
examples.set("layout-outside-scroll", "scroll-view/layout-outside-scroll");
1920
return examples;
2021
}

‎tns-core-modules/ui/core/view/view.ios.ts‎

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -789,36 +789,32 @@ export namespace ios {
789789
}
790790

791791
export function expandBeyondSafeArea(view: View, frame: CGRect): CGRect {
792-
const locationInWindow = view.getLocationInWindow();
793-
const inWindowLeft = layout.round(layout.toDevicePixels(locationInWindow.x));
794-
const inWindowTop = layout.round(layout.toDevicePixels(locationInWindow.y));
795-
const inWindowRight = inWindowLeft + layout.round(layout.toDevicePixels(frame.size.width));
796-
const inWindowBottom = inWindowTop + layout.round(layout.toDevicePixels(frame.size.height));
797-
798-
const availableSpace = getAvailableSpaceFromParent(view);
792+
const availableSpace = getAvailableSpaceFromParent(view, frame);
799793
const safeArea = availableSpace.safeArea;
800794
const fullscreen = availableSpace.fullscreen;
795+
const inWindow = availableSpace.inWindow;
801796

802797
const position = ios.getPositionFromFrame(frame);
803798
const safeAreaPosition = ios.getPositionFromFrame(safeArea);
804799
const fullscreenPosition = ios.getPositionFromFrame(fullscreen);
800+
const inWindowPosition = ios.getPositionFromFrame(inWindow);
805801

806802
const adjustedPosition = position;
807803

808-
if (position.left && inWindowLeft <= safeAreaPosition.left) {
804+
if (position.left && inWindowPosition.left <= safeAreaPosition.left) {
809805
adjustedPosition.left = fullscreenPosition.left;
810806
}
811807

812-
if (position.top && inWindowTop <= safeAreaPosition.top) {
808+
if (position.top && inWindowPosition.top <= safeAreaPosition.top) {
813809
adjustedPosition.top = fullscreenPosition.top;
814810
}
815811

816-
if (inWindowRight < fullscreenPosition.right && inWindowRight >= safeAreaPosition.right + fullscreenPosition.left) {
817-
adjustedPosition.right += fullscreenPosition.right - inWindowRight;
812+
if (inWindowPosition.right < fullscreenPosition.right && inWindowPosition.right >= safeAreaPosition.right + fullscreenPosition.left) {
813+
adjustedPosition.right += fullscreenPosition.right - inWindowPosition.right;
818814
}
819815

820-
if (inWindowBottom < fullscreenPosition.bottom && inWindowBottom >= safeAreaPosition.bottom + fullscreenPosition.top) {
821-
adjustedPosition.bottom += fullscreenPosition.bottom - inWindowBottom;
816+
if (inWindowPosition.bottom < fullscreenPosition.bottom && inWindowPosition.bottom >= safeAreaPosition.bottom + fullscreenPosition.top) {
817+
adjustedPosition.bottom += fullscreenPosition.bottom - inWindowPosition.bottom;
822818
}
823819

824820
const adjustedFrame = CGRectMake(layout.toDeviceIndependentPixels(adjustedPosition.left), layout.toDeviceIndependentPixels(adjustedPosition.top), layout.toDeviceIndependentPixels(adjustedPosition.right - adjustedPosition.left), layout.toDeviceIndependentPixels(adjustedPosition.bottom - adjustedPosition.top));
@@ -849,37 +845,54 @@ export namespace ios {
849845
layoutParent(view.parent);
850846
}
851847

852-
function getAvailableSpaceFromParent(view: View): { safeArea: CGRect, fullscreen: CGRect } {
848+
function getAvailableSpaceFromParent(view: View, frame: CGRect): { safeArea: CGRect, fullscreen: CGRect, inWindow: CGRect } {
853849
if (!view) {
854850
return;
855851
}
856852

857-
let fullscreen = null;
858-
let safeArea = null;
853+
let scrollView = null;
854+
let viewControllerView = null;
859855

860856
if (view.viewController) {
861-
const nativeView = view.viewController.view;
862-
safeArea = nativeView.safeAreaLayoutGuide.layoutFrame;
863-
fullscreen = nativeView.frame;
857+
viewControllerView = view.viewController.view;
864858
} else {
865859
let parent = view.parent as View;
866860
while (parent && !parent.viewController && !(parent.nativeViewProtected instanceof UIScrollView)) {
867861
parent = parent.parent as View;
868862
}
869863

870864
if (parent.nativeViewProtected instanceof UIScrollView) {
871-
const nativeView = parent.nativeViewProtected;
872-
const insets = nativeView.safeAreaInsets;
873-
safeArea = CGRectMake(insets.left, insets.top, nativeView.contentSize.width - insets.left - insets.right, nativeView.contentSize.height - insets.top - insets.bottom);
874-
fullscreen = CGRectMake(0, 0, nativeView.contentSize.width, nativeView.contentSize.height);
865+
scrollView = parent.nativeViewProtected;
875866
} else if (parent.viewController) {
876-
const nativeView = parent.viewController.view;
877-
safeArea = nativeView.safeAreaLayoutGuide.layoutFrame;
878-
fullscreen = nativeView.frame;
867+
viewControllerView = parent.viewController.view;
879868
}
880869
}
881870

882-
return { safeArea: safeArea, fullscreen: fullscreen }
871+
let fullscreen = null;
872+
let safeArea = null;
873+
874+
if (viewControllerView) {
875+
safeArea = viewControllerView.safeAreaLayoutGuide.layoutFrame;
876+
fullscreen = viewControllerView.frame;
877+
}
878+
else if (scrollView) {
879+
const insets = scrollView.safeAreaInsets;
880+
safeArea = CGRectMake(insets.left, insets.top, scrollView.contentSize.width - insets.left - insets.right, scrollView.contentSize.height - insets.top - insets.bottom);
881+
fullscreen = CGRectMake(0, 0, scrollView.contentSize.width, scrollView.contentSize.height);
882+
}
883+
884+
const locationInWindow = view.getLocationInWindow();
885+
let inWindowLeft = locationInWindow.x;
886+
let inWindowTop = locationInWindow.y;
887+
888+
if (scrollView) {
889+
inWindowLeft += scrollView.contentOffset.x;
890+
inWindowTop += scrollView.contentOffset.y;
891+
}
892+
893+
const inWindow = CGRectMake(inWindowLeft, inWindowTop, frame.size.width, frame.size.height);
894+
895+
return { safeArea: safeArea, fullscreen: fullscreen, inWindow: inWindow }
883896
}
884897

885898
export class UILayoutViewController extends UIViewController {

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL