Angular2:用于 md-tab-group 的 HammerJS 滑动

Angular2: HammerJS swipe for md-tab-group

我已经在我的 Angular2 webapp 中实现了 HammerJS,并且我还测试了 example 代码。这段代码使用了一个对象数组,并且似乎可以完美地工作。但是,我一直在尝试为@angular2-material/tabs 实现相同的系统。因此我有一个 <md-tab-group> 和多个 <md-tab>,应该从一个选项卡滑动到另一个选项卡。问题是我什至无法触发滑动功能。

HTML-文件:

<md-tab-group md-stretch-tabs [(selectedIndex)]="selectedIndex" (selectedIndexChange)="selectChange()">
      <div class="swipe-box" (swipeleft)="swipe(idx, $event.type)" (swiperight)="swipe(idx, $event.type)">
        <md-tab>
           (...) //Content Tab 1
        </md-tab>
        <md-tab>
           (...) //Content Tab 2
        </md-tab>
      </div>
</md-tab-group>

在示例中可以看出,*ngFor*ngFor="let avatar of avatars; let idx=index" 一样用于滑动框-<div>。但是由于我是从 <md-tab-group> 获取索引,所以它似乎没有必要,即使我包含它,我的事件也没有触发,但我的 <md-tab>-content 被隐藏了。因此,我将其排除在外。我确实在函数中保留了 idx 参数,因为滑动方法需要一个数字(第二个参数是可选的)。 Documentation

对于 TypeScript 文件,我已经实现了以下代码(有些代码可能无法运行,但由于未调用滑动方法,因此无法对其进行测试)。

TS-文件:

export class HomeComponent {

  selectedIndex: number = 1;

  selectChange(): void{
    console.log("event triggered INDEX: " + this.selectedIndex);
  }

  SWIPE_ACTION = { LEFT: 'swipeleft', RIGHT: 'swiperight' };

  // Action triggered when user swipes
  swipe(selectedIndex: number, action = this.SWIPE_ACTION.RIGHT) {
    console.log("swiped"); //DOES NOT GET TRIGGERD
    // Out of range
    if (selectedIndex < 0 || selectedIndex > 1 ) return;

    let nextIndex = 0;
    // Swipe right, next tab
    if (action === this.SWIPE_ACTION.RIGHT) {
      const isLast = selectedIndex === 1;
      nextIndex = isLast ? 0 : selectedIndex + 1;
      console.log("swipe right");
    }

    // Swipe left, previous tab
    if (action === this.SWIPE_ACTION.LEFT) {
      const isFirst = selectedIndex === 0;
      nextIndex = isFirst ? 1 : selectedIndex - 1;
      console.log("swipe left");
    }
  }
}

Live demo of what HammerJS does 是的,我已经实现了index.html[=24中需要的脚本=]

<!-- Hammer JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.js"></script>

您需要在每个选项卡上进行滑动检测,而不是容器。

  <div class="swipe-box">
    <md-tab (swipeleft)="swipe(1, $event.type)" 
            (swiperight)="swipe(1, $event.type)">
       (...) //Content Tab 1
    </md-tab>
    <md-tab (swipeleft)="swipe(2, $event.type)" 
            (swiperight)="swipe(2, $event.type)">
       (...) //Content Tab 2
    </md-tab>
  </div>

问题似乎是滑动事件用错了<div>。该事件需要在parent<div>中触发。这是工作代码:

HTML-文件:

<div class="md-content" flex md-scroll-y (swipeleft)="swipe(idx, $event.type)" (swiperight)="swipe(idx, $event.type)">
   <md-tab-group md-stretch-tabs [(selectedIndex)]="selectedIndex" (selectedIndexChange)="selectChange()">
           <md-tab>
              (...) //Content Tab 1
           </md-tab>
           <md-tab>
              (...) //Content Tab 2
           </md-tab>
   </md-tab-group>
</div

TS-文件:

export class HomeComponent {

  selectedIndex: number = 1;

  selectChange(): void{
    console.log("Selected INDEX: " + this.selectedIndex);
  }

  SWIPE_ACTION = { LEFT: 'swipeleft', RIGHT: 'swiperight' };

  // Action triggered when user swipes
  swipe(selectedIndex: number, action = this.SWIPE_ACTION.RIGHT) {
    // Out of range
    if (this.selectedIndex < 0 || this.selectedIndex > 1 ) return;

    // Swipe left, next tab
    if (action === this.SWIPE_ACTION.LEFT) {
      const isLast = this.selectedIndex === 1;
      this.selectedIndex = isLast ? 0 : this.selectedIndex + 1;
      console.log("Swipe right - INDEX: " + this.selectedIndex);
    }

    // Swipe right, previous tab
    if (action === this.SWIPE_ACTION.RIGHT) {
      const isFirst = this.selectedIndex === 0;
      this.selectedIndex = isFirst ? 1 : this.selectedIndex - 1;
      console.log("Swipe left - INDEX: " + this.selectedIndex);
    }
  }
}

我写了一个小指令来实现与您的代码相同的效果:

import { Directive, HostListener, EventEmitter, Input, Output } from '@angular/core';

@Directive({
  selector: '[swipeTab]'
})
export class SwipeTabDirective {

  @HostListener('swipeleft', ['$event'])
  onSwipeleft(event) {
    if(this.selectedIndex + 1 <= this.tabs - 1) {
      this.selectedIndex += 1;
      this.selectedIndexChange.emit(this.selectedIndex);
    }
  }

  @HostListener('swiperight', ['$event'])
  onSwiperight(event) {
    if(this.selectedIndex - 1 >= 0) {
      this.selectedIndex -= 1;
      this.selectedIndexChange.emit(this.selectedIndex);
    }
  }

  @Input() tabs: number;
  @Input()  selectedIndex: number;
  @Output() selectedIndexChange = new EventEmitter<number>();

}

模板应如下所示:

<md-tab-group md-stretch-tabs [(selectedIndex)]="selectedIndex" [(tabs)]="tabs" swipeTab>
       <md-tab>
          (...) //Content Tab 2
       </md-tab>
       <md-tab>
          (...) //Content Tab 2
       </md-tab>
       <md-tab>
          (...) //Content Tab 3
       </md-tab>           
</md-tab-group>

并且在组件中您必须声明以下变量:

  selectedIndex: number = 0;
  tabs: number = 3;

玩得开心。