1

我想获得有关如何实现在许多应用程序(如 Whatsapp 或 Facebook)中看到的功能的建议,其中您有一个列表和一个标题,它始终不可见,但当用户开始向上滚动时逐渐显示列表中的任何位置。

在 whatsapp 和 facebook 中,向上滚动手势会导致搜索栏慢慢出现在屏幕顶部,而列表本身不会滚动,直到搜索栏完全出现(至少这是 android 实现)。

我需要关于如何使用带有 Telerik RadListView (android + ios) 的 Nativescript angular 来实现这一点的建议。据我所知,telerik 通常不建议将 ListView 放在 ScrollView 中。

谢谢!

编辑:我了解到它被称为视差效果,并在本机 android 中找到了它的示例,但是,在带有 ListView 的 nativescript 中没有找到它(确实找到了一个带有 ScrollView 和常规 StackLayout 的示例,而不是里面的 ListView)。

4

2 回答 2

2

您可以在 NativeScript 市场官方网站的“示例”部分查看可用的“实现视差滚动效果”示例,该示例显示了如何实现该效果。只需转到Market.nativescript.org并搜索“视差”。还有一个提供此类功能的插件,但我不确定它的质量。

于 2018-08-06T08:23:57.660 回答
0

这是一个使用 Angular 实现的可滚动视差效果 RadListView 的示例(不需要 ScrollView)。它还提供了将列表标题粘贴在顶部的示例。

请告诉我它是否适合您。

组件模板:

<GridLayout class="page">
<RadListView (scrolled)="onScroll($event)" [items]="dataItems" itemReorder="true"
    (itemReordered)="onItemReordered($event)">
  <ListViewGridLayout tkListViewLayout scrollDirection="Vertical" spanCount="1" ios:itemHeight="150"
      dynamicItemSize="false"></ListViewGridLayout>

  <ng-template tkListItemTemplate let-item="item">
    <StackLayout orientation="vertical">
      <!-- list item content goes here -->
    </StackLayout>
  </ng-template>

  <ng-template tkListViewHeader>
    <StackLayout>
      <GridLayout #fixedHeaderContainer class="fixed-header-container">
        <label text="Fixed Content" verticalAlignment="center"></label>
      </GridLayout>

      <StackLayout class="list-header-container">
        <StackLayout #listHeaderContainer>
          <label text="List Title"></label>
        </StackLayout>
      </StackLayout>
    </StackLayout>
  </ng-template>
</RadListView>

<GridLayout verticalAlignment="top" [height]="dockContainerHeight" [opacity]="dockContainerOpacity">
  <FlexboxLayout justifyContent="flex-start" alignItems="center" class="docked-label-wrapper">
    <button class="fas" text="&#xf053;"></button>

    <StackLayout flexGrow="1" height="100%" [opacity]="dockContentOpacity" orientation="horizontal">
      <label text="List Title"></label>
    </StackLayout>
  </FlexboxLayout>
</GridLayout>
组件scss:
.fixed-header-container {
  height: 200;
  padding: 0 16;
  background-color: green;

  label {
    font-size: 30;
    font-weight: 700;
    color: $white;
  }
}

.list-header-container {
  margin-top: -12;
  border-radius: 12 12 0 0;
  background-color: #ffffff;

  label {
    margin: 16 0;
    font-size: 22;
    color: black;
    vertical-align: center;
  }

  .smaller-label {
    font-size: 12;
    color: #909090;
  }
}

RadListView {
  height: 100%;
  background-color: #ffffff;
}

.docked-label-wrapper {
  margin: 0 0 10;
  background-color: #ffffff;

  .fas {
    margin: 0;
    font-size: 18;
  }

  label {
    font-size: 18;
    color: black;
    vertical-align: center;
  }
}

组件 ts:

  import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
  import { ListViewEventData, ListViewScrollEventData } from 'nativescript-ui-listview';
  import { DataItem, DataItemService } from './data-items.service';

  export const DOCK_HEADER_HEIGHT = 58;

  @Component({
    moduleId: module.id,
    selector: 'app-comp-name',
    templateUrl: './comp-name.component.html',
    styleUrls: ['./comp-name.component.scss']
  })
  export class CompNameComponent implements OnInit {
    dataItems: DataItem[];
    dockContainerHeight = DOCK_HEADER_HEIGHT;
    dockContainerOpacity = 0;
    dockContentOpacity = 0;

    @ViewChild('fixedHeaderContainer', { static: false })
    fixedHeaderContainerRef: ElementRef;

    @ViewChild('listHeaderContainer')
    listHeaderContainerRef: ElementRef;

    constructor(private _dataItemService: DataItemService) {}

    ngOnInit(): void {
        this.dataItems = this._dataItemService.getDataItems();
    }

    onItemReordered(args: ListViewEventData) {
        console.log('Item reordered. Old index: ' + args.index + ' ' + 'new index: ' + args.data.targetIndex);
    }

    onScroll(args: ListViewScrollEventData) {
        if (!this.fixedHeaderContainerRef) {
        return;
        }

        const offset = args.scrollOffset < 0 ? 0 : args.scrollOffset;
        const fixedHeaderHeight = this.fixedHeaderContainerRef.nativeElement.getActualSize().height;

        this.applyFixedHeaderTransition(offset);
        this.applyTitleTransition(offset, fixedHeaderHeight);
        this.applyDockHeaderTransition(offset, fixedHeaderHeight);
    }

    private applyFixedHeaderTransition(scrollOffset: number) {
        this.fixedHeaderContainerRef.nativeElement.translateY = scrollOffset;
    }

    private applyTitleTransition(scrollOffset: number, fixedHeaderHeight: number) {
        const maxHeightChange = fixedHeaderHeight - DOCK_HEADER_HEIGHT;
        const titleElement = this.listHeaderContainerRef.nativeElement;

        if (maxHeightChange < scrollOffset) {
        titleElement.translateX = -(scrollOffset - maxHeightChange) / 1.2;
        titleElement.translateY = -(scrollOffset - maxHeightChange) * 2;
        titleElement.scaleX = 1 - (scrollOffset - maxHeightChange) / fixedHeaderHeight;
        titleElement.scaleY = 1 - (scrollOffset - maxHeightChange) / fixedHeaderHeight;
        } else {
        titleElement.translateX = 0;
        titleElement.translateY = 0;
        titleElement.scaleX = 1;
        titleElement.scaleY = 1;
        }
    }

    private applyDockHeaderTransition(scrollOffset: number, fixedHeaderHeight: number) {
        const maxHeightChange = fixedHeaderHeight - DOCK_HEADER_HEIGHT;
        const containerOpacity = 1 - scrollOffset / maxHeightChange;

        this.dockContainerOpacity = containerOpacity <= 0 ? 1 : 0;
        this.dockContentOpacity = (scrollOffset - (fixedHeaderHeight - DOCK_HEADER_HEIGHT)) / DOCK_HEADER_HEIGHT - 0.2;
    }
  }
于 2021-02-23T09:29:35.623 回答