fix(header): avoid flicker on collapsible header load (#19682)

* fix flicker on collapse load

* remove old test
This commit is contained in:
Liam DeBeasi
2019-10-29 14:36:26 -04:00
committed by GitHub
parent 39fb8f6720
commit 0a7aae28a7
3 changed files with 33 additions and 28 deletions

View File

@ -51,8 +51,8 @@
padding-bottom: 13px; padding-bottom: 13px;
} }
ion-toolbar.in-toolbar ion-title, .header-collapse-main ion-toolbar.in-toolbar ion-title,
ion-toolbar.in-toolbar ion-buttons { .header-collapse-main ion-toolbar.in-toolbar ion-buttons {
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
} }

View File

@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Host, Prop, h, readTask, writeT
import { getIonMode } from '../../global/ionic-global'; import { getIonMode } from '../../global/ionic-global';
import { cloneElement, createHeaderIndex, handleContentScroll, handleToolbarIntersection, setHeaderActive } from './header.utils'; import { cloneElement, createHeaderIndex, handleContentScroll, handleToolbarIntersection, setHeaderActive, setToolbarBackgroundOpacity } from './header.utils';
/** /**
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use. * @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
*/ */
@ -19,6 +19,7 @@ export class Header implements ComponentInterface {
private scrollEl?: HTMLElement; private scrollEl?: HTMLElement;
private contentScrollCallback?: any; private contentScrollCallback?: any;
private intersectionObserver?: any; private intersectionObserver?: any;
private collapsibleMainHeader?: HTMLElement;
@Element() el!: HTMLElement; @Element() el!: HTMLElement;
@ -77,6 +78,11 @@ export class Header implements ComponentInterface {
this.scrollEl.removeEventListener('scroll', this.contentScrollCallback); this.scrollEl.removeEventListener('scroll', this.contentScrollCallback);
this.contentScrollCallback = undefined; this.contentScrollCallback = undefined;
} }
if (this.collapsibleMainHeader) {
this.collapsibleMainHeader.classList.remove('header-collapse-main');
this.collapsibleMainHeader = undefined;
}
} }
private async setupCollapsibleHeader(contentEl: HTMLIonContentElement | null, pageEl: Element | null) { private async setupCollapsibleHeader(contentEl: HTMLIonContentElement | null, pageEl: Element | null) {
@ -84,18 +90,18 @@ export class Header implements ComponentInterface {
this.scrollEl = await contentEl.getScrollElement(); this.scrollEl = await contentEl.getScrollElement();
readTask(() => {
const headers = pageEl.querySelectorAll('ion-header'); const headers = pageEl.querySelectorAll('ion-header');
const mainHeader = Array.from(headers).find((header: any) => header.collapse !== 'condense') as HTMLElement | undefined; this.collapsibleMainHeader = Array.from(headers).find((header: any) => header.collapse !== 'condense') as HTMLElement | undefined;
if (!mainHeader || !this.scrollEl) { return; } if (!this.collapsibleMainHeader) { return; }
const mainHeaderIndex = createHeaderIndex(mainHeader); const mainHeaderIndex = createHeaderIndex(this.collapsibleMainHeader);
const scrollHeaderIndex = createHeaderIndex(this.el); const scrollHeaderIndex = createHeaderIndex(this.el);
if (!mainHeaderIndex || !scrollHeaderIndex) { return; } if (!mainHeaderIndex || !scrollHeaderIndex) { return; }
setHeaderActive(mainHeaderIndex, false); setHeaderActive(mainHeaderIndex, false);
setToolbarBackgroundOpacity(mainHeaderIndex.toolbars[0], 0);
readTask(() => { readTask(() => {
const mainHeaderHeight = mainHeaderIndex.el.clientHeight; const mainHeaderHeight = mainHeaderIndex.el.clientHeight;
@ -109,7 +115,6 @@ export class Header implements ComponentInterface {
const toolbarIntersection = (ev: any) => { handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex); }; const toolbarIntersection = (ev: any) => { handleToolbarIntersection(ev, mainHeaderIndex, scrollHeaderIndex); };
this.intersectionObserver = new IntersectionObserver(toolbarIntersection, { threshold: [0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], rootMargin: `-${mainHeaderHeight}px 0px 0px 0px` }); this.intersectionObserver = new IntersectionObserver(toolbarIntersection, { threshold: [0.25, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1], rootMargin: `-${mainHeaderHeight}px 0px 0px 0px` });
this.intersectionObserver.observe(scrollHeaderIndex.toolbars[0].el); this.intersectionObserver.observe(scrollHeaderIndex.toolbars[0].el);
});
/** /**
* Handle scaling of large iOS titles and * Handle scaling of large iOS titles and
@ -117,12 +122,14 @@ export class Header implements ComponentInterface {
* in primary header * in primary header
*/ */
this.contentScrollCallback = () => { handleContentScroll(this.scrollEl!, scrollHeaderIndex); }; this.contentScrollCallback = () => { handleContentScroll(this.scrollEl!, scrollHeaderIndex); };
this.scrollEl.addEventListener('scroll', this.contentScrollCallback); this.scrollEl!.addEventListener('scroll', this.contentScrollCallback);
}); });
writeTask(() => { writeTask(() => {
cloneElement('ion-title'); cloneElement('ion-title');
cloneElement('ion-back-button'); cloneElement('ion-back-button');
this.collapsibleMainHeader!.classList.add('header-collapse-main');
}); });
this.collapsibleHeaderInitialized = true; this.collapsibleHeaderInitialized = true;

View File

@ -45,7 +45,7 @@ export const createHeaderIndex = (headerEl: HTMLElement | undefined): HeaderInde
innerTitleEl: (ionTitleEl) ? ionTitleEl.shadowRoot!.querySelector('.toolbar-title') : null, innerTitleEl: (ionTitleEl) ? ionTitleEl.shadowRoot!.querySelector('.toolbar-title') : null,
ionButtonsEl: Array.from(toolbar.querySelectorAll('ion-buttons')) || [] ionButtonsEl: Array.from(toolbar.querySelectorAll('ion-buttons')) || []
} as ToolbarIndex; } as ToolbarIndex;
}) || [[]] }) || []
} as HeaderIndex; } as HeaderIndex;
}; };
@ -60,7 +60,7 @@ export const handleContentScroll = (scrollEl: HTMLElement, scrollHeaderIndex: He
}); });
}; };
const setToolbarBackgroundOpacity = (toolbar: ToolbarIndex, opacity: number | undefined) => { export const setToolbarBackgroundOpacity = (toolbar: ToolbarIndex, opacity: number | undefined) => {
if (opacity === undefined) { if (opacity === undefined) {
toolbar.background.style.removeProperty('--opacity'); toolbar.background.style.removeProperty('--opacity');
} else { } else {
@ -124,13 +124,11 @@ export const handleToolbarIntersection = (ev: any, mainHeaderIndex: HeaderIndex,
}; };
export const setHeaderActive = (headerIndex: HeaderIndex, active = true) => { export const setHeaderActive = (headerIndex: HeaderIndex, active = true) => {
writeTask(() => {
if (active) { if (active) {
headerIndex.el.classList.remove('header-collapse-condense-inactive'); headerIndex.el.classList.remove('header-collapse-condense-inactive');
} else { } else {
headerIndex.el.classList.add('header-collapse-condense-inactive'); headerIndex.el.classList.add('header-collapse-condense-inactive');
} }
});
}; };
export const scaleLargeTitles = (toolbars: ToolbarIndex[] = [], scale = 1, transition = false) => { export const scaleLargeTitles = (toolbars: ToolbarIndex[] = [], scale = 1, transition = false) => {