使材料选项卡可滚动 [英] Making Material tabs scrollable

查看:23
本文介绍了使材料选项卡可滚动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的应用程序中使用 Material 选项卡(mat-tabmat-tab-group 中)当有更多的标签时,可以显示比可以显示的标签,显示两个导航按钮显示其他选项卡:

I'm using Material tabs in my application (mat-tab s inside mat-tab-group) When there are more tabs than can be displayed, two navigation buttons are shown to display the other tabs:

我的要求是让用户能够在标签栏上滚动,以便显示其他标签.

My requirement is to enable the user to scroll on the tab bar so that other tabs are shown.

我尝试进行一些 css 更改,但无法解决.如果可以提供任何解决方案或建议,我们将不胜感激.

I tried to do some css changes but couldn't solve it. It's highly appreciated if any solution or suggestion can be given.

推荐答案

[长文本解决方案] 我的目标是让 mat-tabs 默认可滚动,没有控件,但能够在点击部分可见时自动滚动mat-tab 将其移动到可见的中心视口.

[Long text solution] My goal was to make mat-tabs scrollable by default, without controls, but with the ability to auto-scroll when clicking on partially visible mat-tab to move it to the visible center-ish viewport.

1) 在这个例子中已经部分实现了这种行为从盒子里" - https://stackblitz.com/edit/angular-mat-tabs-scrollalble-initial-behavior.问题是你不能正常向后滚动 - 有一些错误的行为将标签推到左边.所以它不像我想要的那样工作.

1) This behavior already partially realized in this example "from the box" - https://stackblitz.com/edit/angular-mat-tabs-scrollalble-initial-behavior. The problem is that you can't scroll backward normally - there some buggy behavior to push tabs to the left. So it does not work as I wanted.

2) 下一个变体是滚动事件 - 在 mat-tab-group 上使用 (wheel)="event" - 但它也不适用于移动设备.https://stackblitz.com/edit/angular-mat-tabs-scrollable-by-wheel-event 从这个上面的精彩评论得到它.

2) The next variant was with scrolling event - take a (wheel)="event" on mat-tab-group - but its also not work with mobile. https://stackblitz.com/edit/angular-mat-tabs-scrollable-by-wheel-event Got it from this awesome comment above.

3) 我自己的 mat-tabs 滚动,当您单击选项卡时,在移动设备上滚动并自动将单击的选项卡滚动到屏幕的视口中心并不太简单,但它确实有效!:)

3) My own scroll of mat-tabs with scrolling on mobile and autoscrolling clicked tab to center of screen' viewport when you click on the tab was not too simple but it works! :)

首先,您需要在点击选项卡和分页按钮时禁用从框中"滚动:

first, you need to disable "from the box" scrolling when tapping on tabs and pagination buttons:

mat-tabs-override.scss:

mat-tabs-override.scss:

$black: #121212;
@mixin media-query-for-mobile {
  @media (max-width: 768px) and (min-width: 1px) {
    @content;
  }
}
mat-tab-group {
  .mat-tab-header {
    .mat-tab-header-pagination {
      display: none !important; // <== disable pagination
    }
    .mat-tab-label-container {
      left: 0px; // if you need to use it on mobile - set left position to 0
      width: 100%;
      .mat-tab-list {
        overflow-x: auto !important; // <== set horisontal scroll bar imperatively
        // below rule prevents sliding of buttons' container - because it not sliding properly - to left it not slide as well
        transform: none !important;
        .mat-tab-labels {
          // some tweaks for tabs - up to you
          @include media-query-for-mobile {
            justify-content: unset !important; 
          }
          .mat-tab-label {
            // min-width: 20% !important;
            padding: 1.25% !important;
            margin: 0px !important;
            text-transform: uppercase;
            color: $black;
            font-weight: 600;
            min-width: 140px !important;
          }
        }
      }
    }
  }
}

在这种情况下,您会看到所有标签的宽度都相似,并且可以在移动设备上滚动.

in this case you will see that all tabs are similar by width and scrollable on mobile.

接下来,您需要在单击选项卡时自动滚动选项卡并将其位置更改为屏幕中心,基于当前视口 - 让我们开始吧!

Next, you need to make auto-scroll for tabs when you clicking on them and change their position to the center of the screen, based on the current viewport - let's do it!

我们可以创建一个指令,它会监听的主容器,检查可滚动容器的宽度.mat-tab-labels 并通过将 .mat-tabs-labels 容器自动滚动到所需方式来移动选项卡以在视口中可见:

We can create a directive, which will listen to the main container of <mat-tabs-group>, check width of scrollable container .mat-tab-labels and move the tab to be visible in viewport by auto-scrolling .mat-tabs-labels container to needed way:

模板中的指令:

<mat-tab-group scrollToCenter>
    <mat-tab label="tab 1"></mat-tab>
    <mat-tab label="tab 2"></mat-tab>
    <mat-tab label="tab 3"></mat-tab>
    <mat-tab label="tab 4"></mat-tab>
    <mat-tab label="tab 5"></mat-tab>
    <mat-tab label="tab 6"></mat-tab>
    <mat-tab label="tab 7"></mat-tab>
    <mat-tab label="tab 8"></mat-tab>
</mat-tab-group>

指令.ts:

import { Directive, ElementRef, OnDestroy } from '@angular/core';
import { fromEvent, Subscription } from 'rxjs';

interface DOMRectI {
  bottom: number;
  height: number;
  left: number; // position start of element
  right: number; // position end of element
  top: number;
  width: number; // width of element
  x?: number;
  y?: number;
}

@Directive({
  // tslint:disable-next-line:directive-selector
  selector: '[scrollToCenter]',
})
export class MatTabScrollToCenterDirective implements OnDestroy {
  isMobile: boolean;
  subs = new Subscription();
  constructor(
    private element: ElementRef
  ) {
    this.subs.add(
      fromEvent(this.element.nativeElement, 'click').subscribe((clickedContainer: MouseEvent) => {
        const scrollContainer = this.element.nativeElement.querySelector('.mat-tab-list');
        const currentScrolledContainerPosition: number = scrollContainer.scrollLeft;

        const newPositionScrollTo = this.calcScrollToCenterValue(clickedContainer, currentScrolledContainerPosition);
      })
    );
  }

/** calculate scroll position to center of viewport */
  calcScrollToCenterValue(clickedContainer, currentScrolledContainerPosition): number {
    const scrolledButton: DOMRectI = (clickedContainer.target as HTMLElement).getBoundingClientRect();
    const leftXOffset = (window.innerWidth - scrolledButton.width) / 2;
    const currentVisibleViewportLeft = scrolledButton.left;
    const neededLeftOffset = currentVisibleViewportLeft - leftXOffset;
    console.log(scrolledButton);
    const newValueToSCroll = currentScrolledContainerPosition + neededLeftOffset;
    return newValueToSCroll;
  }

  ngOnDestroy() {
    this.subs.unsubscribe();
  }
}


它有效!:0 但不是在 ios 和 IE ...为什么?因为ios和IE不支持Element.scroll()

And it works! :0 But not in ios and IE... Why? Because ios and IE don't support Element.scroll()

解决方案 - npm i element-scroll-polyfill并设置为 polyfills.ts

Solution - npm i element-scroll-polyfill and set to polyfills.ts

/** enable polufill for element.scroll() on IE and ios */
import 'element-scroll-polyfill';

太好了!但是现在滚动不是那么流畅...IE和ios不支持smooth-scroll-behavior.

Great! but now scroll is not so smooth... IE and ios not support smooth-scroll-behavior.

解决方案 - npm i smoothscroll-polyfill并添加到 polyfills.ts

Solution - npm i smoothscroll-polyfill and add to polyfills.ts

import smoothscroll from 'smoothscroll-polyfill';
// enable polyfill
smoothscroll.polyfill();

终于可以在任何地方使用了.希望它可以帮助某人修复 mat-tabs 自动滚动空白:)

Finally it works everywhere. Hope it helps somebody to fix mat-tabs autoscrolling emptiness :)

演示 享受吧 :)

DEMO Enjoy it :)

这篇关于使材料选项卡可滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆