滚动显示Ionic 4隐藏工具栏

时间:2018-10-10 16:33:06

标签: ionic-framework ionic4

我正在尝试实现一个指令以在滚动时隐藏工具栏。 我尝试使用本教程: https://medium.com/@gregor.srdic/ionic3-hidding-header-on-footer-on-content-scroll-15ab95b05dc5

这适用于Ionic 3,但不适用于Ionic4。

在以下代码上,我得到了错误:

private adjustElementOnScroll(ev) {
    if (ev) {
        console.log(ev);
        ev.domWrite(() => {
            let scrollTop: number = ev.scrollTop > 0 ? ev.scrollTop : 0;
            let scrolldiff: number = scrollTop - this.lastScrollPosition;
            this.lastScrollPosition = scrollTop;
            let newValue = this.lastValue + scrolldiff;
            newValue = Math.max(0, Math.min(newValue, this.config.maxValue));
            this.renderer.setStyle(this.element.nativeElement, this.config.cssProperty, `-${newValue}px`);
            this.lastValue = newValue;
        });
    }
}

错误:

ev.domWrite is not a function

我检查了一下,在离子4中,evCustomEvent,而不是ScrollEvent

有什么建议吗?

4 个答案:

答案 0 :(得分:4)

针对Ionic 4的修改指令。

while True:
       num_players_playing = 2
       while num_players_playing > 0:
             for i in player_display:
                 draw_text_2(i[x])
             num_players_playing -= 1

答案 1 :(得分:2)

该事件在Ionic 4中可能已更改,但是您仍然可以从DomController导入@ionic/angular

import {..., DomController } from "@ionic/angular";

并将其注入构造函数中

constructor(
    // ...
    private domCtrl: DomController
) { }

然后使用write()方法,如下所示:

private adjustElementOnScroll(ev) {
    if (ev) {
        this.domCtrl.write(() => {
            // ...
        });
    }
}

DomController只是Ionic为在后台使用window.requestAnimationFrame()方法编写写或读取DOM的回调创建队列的一种方式。

有关更多信息,请访问:

  1. DomController source code
  2. requestAnimationFrame MDN

答案 2 :(得分:2)

以上解决方案不再起作用。最近几个月,Ionic 4 beta API发生了很大变化。

您必须导入IonContent而不是Content

//scroll-hide.directive.ts
import { IonContent, DomController } from '@ionic/angular';
import { Directive, ElementRef, Input, Renderer2, SimpleChanges } from '@angular/core';

将指令导入到您想使用的位置,而不是app.module.ts

例如在相关模块中

//ex: home.module.ts
import { ScrollHideDirective } from '../../directives/scroll-hide.directive';

@NgModule({
    ...
  declarations: [...,ScrollHideDirective],
    ...
})


then in the ts file,


//ex: home.page.ts
import { ScrollHideConfig } from '../../directives/scroll-hide.directive';


export class HomePage implements OnInit {

...
    footerScrollConfig: ScrollHideConfig = { cssProperty: 'margin-bottom', maxValue: undefined };
    headerScrollConfig: ScrollHideConfig = { cssProperty: 'margin-top', maxValue: 54 };
...

}

指令的反向版本

//ex: scroll-hide.directive.ts    

import { IonContent, DomController } from '@ionic/angular';
import { Directive, ElementRef, Input, Renderer2, SimpleChanges } from '@angular/core';

    @Directive({
      selector: '[scrollHide]'
      })
export class ScrollHideDirective {

  @Input('scrollHide') config: ScrollHideConfig;
  @Input('scrollContent') scrollContent: IonContent;

  contentHeight: number;
  scrollHeight: number;
  lastScrollPosition: number;
  lastValue: number = 0;

  constructor(private element: ElementRef, private renderer: Renderer2, private  domCtrl: DomController) {
  }

  ngOnChanges(changes: SimpleChanges) {
    if(this.scrollContent && this.config) {
      this.scrollContent.scrollEvents = true;

      let scrollStartFunc = async (ev) => {
        const el = await this.scrollContent.getScrollElement();
        this.contentHeight = el.offsetHeight;
        this.scrollHeight = el.scrollHeight;
        if (this.config.maxValue === undefined) {
          this.config.maxValue = this.element.nativeElement.offsetHeight;
        }
        this.lastScrollPosition = el.scrollTop;
      };

      if(this.scrollContent && this.scrollContent instanceof IonContent) {
        this.scrollContent.ionScrollStart.subscribe(scrollStartFunc);
        this.scrollContent.ionScroll.subscribe(async (ev) => this.adjustElementOnScroll(ev));
        this.scrollContent.ionScrollEnd.subscribe(async (ev) => this.adjustElementOnScroll(ev));

      } else if(this.scrollContent instanceof HTMLElement) {
        (this.scrollContent as HTMLElement).addEventListener('ionScrollStart', scrollStartFunc);
        (this.scrollContent as HTMLElement).addEventListener('ionScroll',async (ev) => this.adjustElementOnScroll(ev));
        (this.scrollContent as HTMLElement).addEventListener('ionScrollEnd',async (ev) => this.adjustElementOnScroll(ev));
      }
    }
  }

  private adjustElementOnScroll(ev) {
    if (ev) {
      this.domCtrl.write(async () => {
        const el = await this.scrollContent.getScrollElement();
        let scrollTop: number = el.scrollTop > 0 ? el.scrollTop : 0;
        let scrolldiff: number = scrollTop - this.lastScrollPosition;
        this.lastScrollPosition = scrollTop;
        let newValue = this.lastValue + scrolldiff;
        newValue = Math.max(0, Math.min(newValue, this.config.maxValue));
        this.renderer.setStyle(this.element.nativeElement, this.config.cssProperty, `-${newValue}px`);
        this.lastValue = newValue;
      });
    }
  }
}

export interface ScrollHideConfig {
  cssProperty: string;
  maxValue: number;
}

html ex:page.html(不变)

<ion-header [scrollHide]="headerScrollConfig" [scrollContent]="pageContent">
  ...
</ion-header>

<ion-content #pageContent fullscreen>
  ...
</ion-content>

<ion-footer [scrollHide]="footerScrollConfig" [scrollContent]="pageContent">
...
</ion-footer>

希望有帮助。

答案 3 :(得分:0)

下面的代码对我有用,上面的代码做了一些小修改

import { Content, DomController } from '@ionic/angular';
import { Directive, ElementRef, Input, Renderer2, SimpleChanges } from '@angular/core';

@Directive({
  selector: '[scrollHide]'
  })
export class ScrollHideDirective {

  @Input('scrollHide') config: ScrollHideConfig;
  @Input('scrollContent') scrollContent: Content;

  contentHeight: number;
  scrollHeight: number;
  lastScrollPosition: number;
  lastValue: number = 0;

  constructor(private element: ElementRef, private renderer: Renderer2, private domCtrl: DomController) {
  }

  ngOnChanges(changes: SimpleChanges) {
    if(this.scrollContent && this.config) {
      this.scrollContent.scrollEvents = true;

      let scrollStartFunc = async (ev) => {
        const el = await this.scrollContent.getScrollElement();
        this.contentHeight = el.offsetHeight;
        this.scrollHeight = el.scrollHeight;
        if (this.config.maxValue === undefined) {
          this.config.maxValue = this.element.nativeElement.offsetHeight;
        }
        this.lastScrollPosition = el.scrollTop;
      };

      if(this.scrollContent && this.scrollContent instanceof Content) {
        this.scrollContent.ionScrollStart.subscribe(scrollStartFunc);
        this.scrollContent.ionScroll.subscribe(async (ev) => this.adjustElementOnScroll(ev));
        this.scrollContent.ionScrollEnd.subscribe(async (ev) => this.adjustElementOnScroll(ev));

      } else if(this.scrollContent instanceof HTMLElement) {
        (this.scrollContent as HTMLElement).addEventListener('ionScrollStart', scrollStartFunc);
        (this.scrollContent as HTMLElement).addEventListener('ionScroll',async (ev) => this.adjustElementOnScroll(ev));
        (this.scrollContent as HTMLElement).addEventListener('ionScrollEnd',async (ev) => this.adjustElementOnScroll(ev));
      }
    }
  }

  private adjustElementOnScroll(ev) {
    if (ev) {
      this.domCtrl.write(async () => {
        const el = await this.scrollContent.getScrollElement();
        let scrollTop: number = el.scrollTop > 0 ? el.scrollTop : 0;
        let scrolldiff: number = scrollTop - this.lastScrollPosition;
        this.lastScrollPosition = scrollTop;
        let newValue = this.lastValue + scrolldiff;
        newValue = Math.max(0, Math.min(newValue, this.config.maxValue));
        this.renderer.setStyle(this.element.nativeElement, this.config.cssProperty, `-${newValue}px`);
        this.lastValue = newValue;
      });
    }
  }
}
export interface ScrollHideConfig {
  cssProperty: string;
  maxValue: number;
}