这是一个使用 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=""></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;
}
}