Ionic v3 Segment - 滚动时更改活动段
Ionic v3 Segment - Change active segment while scrolling
我最近想知道为什么不能通过在 ionScroll.subscribe() 中修改 [(ngModel)] 来更改 ionic v3 中的活动段。我将我的片段内容堆叠在彼此之下。所以我正在使用 "anchor-scrolling" 的按钮,并希望当我的滚动位置超过特定位置时使它们显示反之亦然。这是我的代码:
<ion-segment [(ngModel)]="segData">
<ion-segment-button (click)="this.scrollToCard('card1')" value="seg1">Card1</ion-segment-button>
<ion-segment-button (click)="this.scrollToCard('card2')" value="seg2">Card2</ion-segment-button>
</ion-segment>
<div [ngSwitch]="segData">
<ion-list *ngSwitchCase="'seg1'">
<ion-item>
<ion-card #card1>...</ion-card>
</ion-item>
<ion-item>
<ion-card #card2>...</ion-card>
</ion-item>
</ion-list>
</div>
example.ts
segData: string;
export class ShowCar
{
@ViewChild(Content) content : Content;
...
constructor(...)
{
this.segData = "seg1";
}
...
ionViewDidLoad()
{
//This would work
//setTimeout( () => { this.segData = "seg2"; }
//Inside ionScroll.subscribe() it is not working
//Even if i wrap this into "setTimeout"
this.content.ionScroll.subscribe( scrollData =>
{
if( scrollData.scrollTop > seg1PosFromTop)
this.segData = "seg2";
});
}
...
}
我尝试了很多东西,可能会发生一些疯狂的事情。例如,由于最新的 angular 允许直接使用 DOM 中的元素,我触发了元素上的点击事件。然后该段很快显示为活动状态,并且在一毫秒后,先前的段再次变为活动状态。我也在玩弄 css 类。但是,当单击分段按钮时,我必须捕获它,删除所有 segment-button segment-active
类 并将其手动添加到所选按钮。
好吧,既然没有人回答我的问题,我就花了很多时间尝试和研究。我们开始吧,解决方案:
出于性能原因,离子应用程序中的每个滚动运动恰好在 angular 的 外部 之外。因此不能修改 angular 变量或在任何滚动事件处理程序(ionScroll
、ionScrollStart
、ionScrollEnd
)中执行 content.resize()
。
所以你必须将每个代码包装成:this.zone.run()
import { Component, NgZone } from '@angular/core';
@Component({
template: `
<ion-header>
<ion-navbar>
<ion-title></ion-title>
</ion-navbar>
</ion-header>
<ion-content (ionScroll)="scrollHandler($event)">
<p> Some realllllllly long content </p>
</ion-content>
`})
class E2EPage {
public scrollAmount = 0;
constructor( public zone: NgZone){}
scrollHandler(event) {
console.log(`ScrollEvent: ${event}`)
this.zone.run(()=>{
// since scrollAmount is data-binded,
// the update needs to happen in zone
this.scrollAmount++
})
}
}
https://ionicframework.com/docs/api/components/content/Content/#advanced
这是 ionic4 的完整解决方案:
// tab.page.html
<ion-header >
<!-- Scrollable Segment -->
<ion-toolbar class="less-height" color="primary">
<ion-segment scrollable mode="md" (ionChange)="segmentChanged(segment)" [(ngModel)]="segment" >
<ion-segment-button mode="md" id="seg-1" value="0">
<p>Description</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-2" value="1">
<p>Interconnections</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-3" value="2">
<p>Declensions</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-4" value="3">
<p>Phraseologisms</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-5" value="4">
<p>Etymology</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-6" value="5">
<p>Analysis</p>
</ion-segment-button>
</ion-segment>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-slides (ionSlideDidChange)="slideChanged()" class="word-slides">
<ion-slide>
<p>Slide 1</p>
</ion-slide>
<ion-slide>
<p>Slide 2</p>
</ion-slide>
<ion-slide>
<p>Slide 3</p>
</ion-slide>
<ion-slide>
<p>Slide 4</p>
</ion-slide>
<ion-slide>
<p>Slide 5</p>
</ion-slide>
<ion-slide>
<p>Slide 6</p>
</ion-slide>
</ion-slides>
</ion-content>
// tab.page.ts
@ViewChild(IonSlides) slider: IonSlides;
segment = 0;
constructor() {}
async segmentChanged(event) {
await this.slider.slideTo(this.segment);
this.slider.update();
}
async slideChanged() {
this.segment = await this.slider.getActiveIndex();
this.focusSegment(this.segment+1);
}
focusSegment(segmentId) {
document.getElementById('seg-'+segmentId).scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
}
我最近想知道为什么不能通过在 ionScroll.subscribe() 中修改 [(ngModel)] 来更改 ionic v3 中的活动段。我将我的片段内容堆叠在彼此之下。所以我正在使用 "anchor-scrolling" 的按钮,并希望当我的滚动位置超过特定位置时使它们显示反之亦然。这是我的代码:
<ion-segment [(ngModel)]="segData">
<ion-segment-button (click)="this.scrollToCard('card1')" value="seg1">Card1</ion-segment-button>
<ion-segment-button (click)="this.scrollToCard('card2')" value="seg2">Card2</ion-segment-button>
</ion-segment>
<div [ngSwitch]="segData">
<ion-list *ngSwitchCase="'seg1'">
<ion-item>
<ion-card #card1>...</ion-card>
</ion-item>
<ion-item>
<ion-card #card2>...</ion-card>
</ion-item>
</ion-list>
</div>
example.ts
segData: string;
export class ShowCar
{
@ViewChild(Content) content : Content;
...
constructor(...)
{
this.segData = "seg1";
}
...
ionViewDidLoad()
{
//This would work
//setTimeout( () => { this.segData = "seg2"; }
//Inside ionScroll.subscribe() it is not working
//Even if i wrap this into "setTimeout"
this.content.ionScroll.subscribe( scrollData =>
{
if( scrollData.scrollTop > seg1PosFromTop)
this.segData = "seg2";
});
}
...
}
我尝试了很多东西,可能会发生一些疯狂的事情。例如,由于最新的 angular 允许直接使用 DOM 中的元素,我触发了元素上的点击事件。然后该段很快显示为活动状态,并且在一毫秒后,先前的段再次变为活动状态。我也在玩弄 css 类。但是,当单击分段按钮时,我必须捕获它,删除所有 segment-button segment-active
类 并将其手动添加到所选按钮。
好吧,既然没有人回答我的问题,我就花了很多时间尝试和研究。我们开始吧,解决方案:
出于性能原因,离子应用程序中的每个滚动运动恰好在 angular 的 外部 之外。因此不能修改 angular 变量或在任何滚动事件处理程序(ionScroll
、ionScrollStart
、ionScrollEnd
)中执行 content.resize()
。
所以你必须将每个代码包装成:this.zone.run()
import { Component, NgZone } from '@angular/core';
@Component({
template: `
<ion-header>
<ion-navbar>
<ion-title></ion-title>
</ion-navbar>
</ion-header>
<ion-content (ionScroll)="scrollHandler($event)">
<p> Some realllllllly long content </p>
</ion-content>
`})
class E2EPage {
public scrollAmount = 0;
constructor( public zone: NgZone){}
scrollHandler(event) {
console.log(`ScrollEvent: ${event}`)
this.zone.run(()=>{
// since scrollAmount is data-binded,
// the update needs to happen in zone
this.scrollAmount++
})
}
}
https://ionicframework.com/docs/api/components/content/Content/#advanced
这是 ionic4 的完整解决方案:
// tab.page.html
<ion-header >
<!-- Scrollable Segment -->
<ion-toolbar class="less-height" color="primary">
<ion-segment scrollable mode="md" (ionChange)="segmentChanged(segment)" [(ngModel)]="segment" >
<ion-segment-button mode="md" id="seg-1" value="0">
<p>Description</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-2" value="1">
<p>Interconnections</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-3" value="2">
<p>Declensions</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-4" value="3">
<p>Phraseologisms</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-5" value="4">
<p>Etymology</p>
</ion-segment-button>
<ion-segment-button mode="md" id="seg-6" value="5">
<p>Analysis</p>
</ion-segment-button>
</ion-segment>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-slides (ionSlideDidChange)="slideChanged()" class="word-slides">
<ion-slide>
<p>Slide 1</p>
</ion-slide>
<ion-slide>
<p>Slide 2</p>
</ion-slide>
<ion-slide>
<p>Slide 3</p>
</ion-slide>
<ion-slide>
<p>Slide 4</p>
</ion-slide>
<ion-slide>
<p>Slide 5</p>
</ion-slide>
<ion-slide>
<p>Slide 6</p>
</ion-slide>
</ion-slides>
</ion-content>
// tab.page.ts
@ViewChild(IonSlides) slider: IonSlides;
segment = 0;
constructor() {}
async segmentChanged(event) {
await this.slider.slideTo(this.segment);
this.slider.update();
}
async slideChanged() {
this.segment = await this.slider.getActiveIndex();
this.focusSegment(this.segment+1);
}
focusSegment(segmentId) {
document.getElementById('seg-'+segmentId).scrollIntoView({
behavior: 'smooth',
block: 'center',
inline: 'center'
});
}