mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 03:00:58 +08:00
scroll end timing
This commit is contained in:
@ -71,18 +71,18 @@ export class SegmentView implements ComponentInterface {
|
|||||||
// Find the current segment content based on the scroll position
|
// Find the current segment content based on the scroll position
|
||||||
const currentIndex = Math.round(scrollLeft / offsetWidth);
|
const currentIndex = Math.round(scrollLeft / offsetWidth);
|
||||||
|
|
||||||
// Recursively search for the next enabled content in the scroll direction
|
// // Update active content ID and scroll to the segment content
|
||||||
const segmentContent = this.getNextEnabledContent(currentIndex, scrollDirection);
|
const activeContent = this.getSegmentContents().filter(
|
||||||
|
(ref) => !ref.classList.contains('segment-content-disabled')
|
||||||
|
)[currentIndex];
|
||||||
|
this.activeContentId = activeContent.id;
|
||||||
|
|
||||||
// Exit if no valid segment content found
|
// Only emit scroll end event if the active content is not disabled and
|
||||||
if (!segmentContent) return;
|
// the user is not touching the segment view
|
||||||
|
if (activeContent?.disabled === false && !this.isTouching) {
|
||||||
// Update active content ID and scroll to the segment content
|
this.ionSegmentViewScrollEnd.emit({ activeContentId: this.activeContentId });
|
||||||
this.activeContentId = segmentContent.id;
|
this.initialScrollLeft = undefined;
|
||||||
this.setContent(segmentContent.id);
|
}
|
||||||
|
|
||||||
// Reset the timeout to check for scroll end
|
|
||||||
this.resetScrollEndTimeout();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,35 +108,6 @@ export class SegmentView implements ComponentInterface {
|
|||||||
this.isTouching = false;
|
this.isTouching = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the scroll end detection timer. This is called on every scroll event.
|
|
||||||
*/
|
|
||||||
private resetScrollEndTimeout() {
|
|
||||||
if (this.scrollEndTimeout) {
|
|
||||||
clearTimeout(this.scrollEndTimeout);
|
|
||||||
this.scrollEndTimeout = null;
|
|
||||||
}
|
|
||||||
this.scrollEndTimeout = setTimeout(() => {
|
|
||||||
this.checkForScrollEnd();
|
|
||||||
}, 150);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the scroll has ended and the user is not actively touching.
|
|
||||||
* If the conditions are met (active content is enabled and no active touch),
|
|
||||||
* reset the scroll position and emit the scroll end event.
|
|
||||||
*/
|
|
||||||
private checkForScrollEnd() {
|
|
||||||
const activeContent = this.getSegmentContents().find((content) => content.id === this.activeContentId);
|
|
||||||
|
|
||||||
// Only emit scroll end event if the active content is not disabled and
|
|
||||||
// the user is not touching the segment view
|
|
||||||
if (activeContent?.disabled === false && !this.isTouching) {
|
|
||||||
this.ionSegmentViewScrollEnd.emit({ activeContentId: this.activeContentId });
|
|
||||||
this.initialScrollLeft = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is used to programmatically set the displayed segment content
|
* This method is used to programmatically set the displayed segment content
|
||||||
* in the segment view. Calling this method will update the `value` of the
|
* in the segment view. Calling this method will update the `value` of the
|
||||||
|
@ -28,8 +28,6 @@ export class Segment implements ComponentInterface {
|
|||||||
private valueBeforeGesture?: SegmentValue;
|
private valueBeforeGesture?: SegmentValue;
|
||||||
|
|
||||||
private segmentViewEl?: HTMLIonSegmentViewElement | null = null;
|
private segmentViewEl?: HTMLIonSegmentViewElement | null = null;
|
||||||
private scrolledIndicator?: HTMLDivElement | null = null;
|
|
||||||
private isScrolling = false;
|
|
||||||
|
|
||||||
@Element() el!: HTMLIonSegmentElement;
|
@Element() el!: HTMLIonSegmentElement;
|
||||||
|
|
||||||
@ -381,10 +379,6 @@ export class Segment implements ComponentInterface {
|
|||||||
|
|
||||||
@Listen('ionSegmentViewScroll', { target: 'body' })
|
@Listen('ionSegmentViewScroll', { target: 'body' })
|
||||||
handleSegmentViewScroll(ev: CustomEvent) {
|
handleSegmentViewScroll(ev: CustomEvent) {
|
||||||
if (!this.isScrolling) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dispatchedFrom = ev.target as HTMLElement;
|
const dispatchedFrom = ev.target as HTMLElement;
|
||||||
const segmentViewEl = this.segmentViewEl as EventTarget;
|
const segmentViewEl = this.segmentViewEl as EventTarget;
|
||||||
const segmentEl = this.el;
|
const segmentEl = this.el;
|
||||||
@ -464,6 +458,7 @@ export class Segment implements ComponentInterface {
|
|||||||
indicator.querySelector('div')!.style.backgroundColor = color;
|
indicator.querySelector('div')!.style.backgroundColor = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Scroll the segment container if the indicator is out of view
|
||||||
const indicatorX = indicator.getBoundingClientRect().x;
|
const indicatorX = indicator.getBoundingClientRect().x;
|
||||||
if (scrollDistance < 0 && indicatorX < 0) {
|
if (scrollDistance < 0 && indicatorX < 0) {
|
||||||
this.el.scrollBy({
|
this.el.scrollBy({
|
||||||
@ -482,17 +477,6 @@ export class Segment implements ComponentInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Listen('ionSegmentViewScrollStart', { target: 'body' })
|
|
||||||
onScrollStart(ev: CustomEvent) {
|
|
||||||
const dispatchedFrom = ev.target as HTMLElement;
|
|
||||||
const segmentViewEl = this.segmentViewEl as EventTarget;
|
|
||||||
const segmentEl = this.el;
|
|
||||||
|
|
||||||
if (ev.composedPath().includes(segmentViewEl) || dispatchedFrom?.contains(segmentEl)) {
|
|
||||||
this.isScrolling = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Listen('ionSegmentViewScrollEnd', { target: 'body' })
|
@Listen('ionSegmentViewScrollEnd', { target: 'body' })
|
||||||
onScrollEnd(ev: CustomEvent<{ activeContentId: string }>) {
|
onScrollEnd(ev: CustomEvent<{ activeContentId: string }>) {
|
||||||
const dispatchedFrom = ev.target as HTMLElement;
|
const dispatchedFrom = ev.target as HTMLElement;
|
||||||
@ -500,31 +484,10 @@ export class Segment implements ComponentInterface {
|
|||||||
const segmentEl = this.el;
|
const segmentEl = this.el;
|
||||||
|
|
||||||
if (ev.composedPath().includes(segmentViewEl) || dispatchedFrom?.contains(segmentEl)) {
|
if (ev.composedPath().includes(segmentViewEl) || dispatchedFrom?.contains(segmentEl)) {
|
||||||
this.isScrolling = false;
|
|
||||||
|
|
||||||
this.value = ev.detail.activeContentId;
|
this.value = ev.detail.activeContentId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the transition to end, then execute the callback
|
|
||||||
private waitForTransitionEnd(indicator: HTMLElement, callback: () => void) {
|
|
||||||
const onTransitionEnd = () => {
|
|
||||||
indicator.removeEventListener('transitionend', onTransitionEnd);
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
indicator.addEventListener('transitionend', onTransitionEnd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the Segment value after the ionSegmentViewScrollEnd transition has ended
|
|
||||||
private updateValueAfterTransition(activeContentId: string) {
|
|
||||||
this.value = activeContentId;
|
|
||||||
|
|
||||||
if (this.scrolledIndicator) {
|
|
||||||
this.scrolledIndicator.style.transition = '';
|
|
||||||
this.scrolledIndicator.style.transform = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the related segment view and sets its current content
|
* Finds the related segment view and sets its current content
|
||||||
* based on the selected segment button. This method
|
* based on the selected segment button. This method
|
||||||
|
Reference in New Issue
Block a user