jonnysamps
jonnysamps

Reputation: 1086

Angular Nativescript - Using a ScrollView within an AbsoluteLayout

I'm building a photo browser app where the user should swipe between pages to see different photos. Here is the view that currently works for me.

<ScrollView orientation="horizontal" ios.pagingEnabled="true" >
  <StackLayout orientation="horizontal">
    <Image *ngFor="#picture of buffer" [src]="picture.originUrl" stretch="aspectFit"></Image>
  </StackLayout>
</ScrollView>

The problem comes when I try to apply an overlay. So I tried to wrap the whole thing in an AbsoluteLayout so that I could have the ScrollView operate as normal but keep the overlay in place on top. When I do this scrolling breaks all-together. Here is the view that breaks scrolling:

<AbsoluteLayout>
  <Label text="overlay" left="0" tope="0"></Label>
  <ScrollView orientation="horizontal" ios.pagingEnabled="true" left="0" top="0">
    <StackLayout orientation="horizontal">
      <Image *ngFor="#picture of buffer" [src]="picture.originUrl" stretch="aspectFit"></Image>
    </StackLayout>
  </ScrollView>
</AbsoluteLayout>

The layouts appear to work correctly, but scrolling breaks. Anybody have any ideas on how to accomplish this?

Upvotes: 0

Views: 4158

Answers (2)

jonnysamps
jonnysamps

Reputation: 1086

I got an answer from a bug I filed: https://github.com/NativeScript/nativescript-angular/issues/184

The problem comes from the fact that AbsoluteLayout measures all its children with infinity space, so the ScrollView is as big as its content and indeed scrolling will not work. A possible fix is it to set a size for the ScrollView. In this specific case % layout size can be used.

<AbsoluteLayout>
  <Label text="overlay" left="0" top="0"></Label>
  <ScrollView orientation="horizontal" ios.pagingEnabled="true" left="0" top="0" width="100%" height="75%">
    <StackLayout orientation="horizontal">
      <Image *ngFor="#picture of pictures" [src]="picture.originUrl" stretch="aspectFit"></Image>
    </StackLayout>
  </ScrollView>
</AbsoluteLayout>

Both % values are % from the size that parent layout control is measured (AbsoluteLayout). Since Absolute layout is a root element actually these values will be % of the screen size.

Upvotes: 1

Nathanael
Nathanael

Reputation: 5399

If I was doing this layout I would do this:

<GridLayout rows="*">
  <ScrollView row="0" orientation="horizontal" ios.pagingEnabled="true">
    <StackLayout orientation="horizontal">
      <Image *ngFor="#picture of buffer" [src]="picture.originUrl" stretch="aspectFit"></Image>
    </StackLayout>
  </ScrollView>
  <Label row="0" text="overlay"></Label>
</GridLayout>

By using the same row they will be positioned in the same place. I use this technique to create a entire search interface that will overlay part of the screen when they click the search button. Please note; the items later in the GridLayout show above items earlier in the GridLayout. So that is why the Label was moved to the bottom of the GridLayout, so it will be visible above the ScrollLayout.


Here is the actual test template I did:

<Page id="Page" onloaded="pageLoaded" class="">
    <GridLayout rows="100,*">
      <ScrollView row="0">
         <StackLayout>
           <Label visibility="{{ pageData.visible ? 'visible' : 'collapsed' }}" text="Hi1 this should appear/disappear" class ="lab1"/>
          <Label visibility="{{ pageObs.visible ? 'visible' : 'collapsed' }}" text="Hi2 this should appear/disappear" class ="lab1"/>
          <Label visibility="{{pageData, pageData.visible ? 'visible' : 'collapsed' }}"  text="Hi3 this should appear/disappear" class ="lab1"/>
          <Label left="10" top="70" visibility="{{visible ? 'visible' : 'collapsed' }}"  text="Hi4 this should appear/disappear" class ="lab1"/>
          <Label text="{{pageObs.visible}}"/>
          <Label text="I'm at 120"/>
          <Button text="tap"  tap="onTap"/>
          <Label text="Another text"/>
          <Label text="Another text 2"/>
        </StackLayout>
      </ScrollView> 
      <Label row="0" text="Overlay"/>
      <Label row="1" text="Grid row 1"/>
    </GridLayout>

</Page>

Scrolling example

This layout has two Grid rows, so that you can see where the ScrollView ends; the first row has the ScrollView AND the "Overlay"

Upvotes: 5

Related Questions