【问题标题】:Nativescript Show element while scrolling up in ListView - parallax effectNativescript 在 ListView 中向上滚动时显示元素 - 视差效果
【发布时间】:2019-01-12 12:03:22
【问题描述】:

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

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

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

谢谢!

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

【问题讨论】:

    标签: nativescript nativescript-telerik-ui nativescript-angular radlistview


    【解决方案1】:

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

    【讨论】:

    • 您好,感谢您的回复。我知道您所指的示例,这是我想到的那个:“确实找到了一个带有 ScrollView 和常规 StackLayout 的示例,而不是里面的 ListView”。它以非常简单的方式实现视差,然而,滚动部分是一个简单的 StackLayout,而不是 ListView。并且由于所有内容都包含在 ScrollView 中,因此无法以相同的方式实现,因为没有将 Listview 放入 ScrollView 的约束。
    • 嗯,知道了。好吧,我还没有看到任何关于列表组件内视差效果的示例或讨论。您描述“始终不可见”的方式可能是在谈论“动态操作栏”而不是视差效果?
    • 您好,我不确定确切的术语是什么,当您说“动态操作栏”时,您的意思是什么?我用谷歌搜索了它,但没有找到一个可以证明我要做什么的例子。我能给出的最好的例子是 SearchBar 在 android 上的 Whatsapp 和 Facebook 应用程序中隐藏和显示的方式,同时上下滚动列表。有些应用程序在发生这种情况时也有很好的动画效果,非常类似于视差示例,即在滚动底部布局时导致标题出现\缩小。
    • 如果你在谈论这样的事情:androcode.es/wp-content/uploads/2015/10/simple_coordinator.gif,在来自“CoordinatorLayout”的 Android 上,我不确定 iOS 是否有类似的内置功能。在 NativeScript 中,CoordinatorLayout 不会被框架公开,但有人可以通过插件实现和公开它。
    • 是的,非常相似,感谢您为我提供了正确的术语。我发现这个功能请求github.com/NativeScript/NativeScript/issues/4908 也谈到了它。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2014-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      • 2012-02-18
      • 2015-01-04
      相关资源
      最近更新 更多