components
components copied to clipboard
feat(sidenav): add swipe functionality
Bug, feature request, or proposal:
Feature request
What is the expected behavior?
It'd be great to have the functionality of swipe in md-sidenav, like in https://material.io/guidelines/.
What are the steps to reproduce?
Open https://material.io/guidelines/ in mobile and see how the swipe on menu works.
Is there anything else we should know?
The same feature request was requested in material(1) here and at some point it was implemented, but not merged.
We do plan on doing this.
Hi, I have only recently jumped on the angular wagon and find all of the different versions to be completely confusing. At the moment I have an app underway using Angular2 and the material web components which seems to be a fairly reliable stack, however following the evolution of this feature I'm beginning to question my choice.
This is absolutely basic functionality for a sidenav, which I have first encountered when using a similar component in Nativescript. The fact that this was first suggested in 2014 and yet 3 years later is only in the plans is extremely frustrating! Apparently someone has implemented the feature, but because of the management of the project and "surge focus on material 2" it never got merged. This is enough to make me dump the whole Angular2 project and take Polymer web components into use since they have implemented drag on their sidenav component. This is needless to say disappointing since otherwise the material library has worked reasonably well. There were a lot of plus ones originally on this feature, I suspect it should have been given higher priority.
@jelbourn, is there an ETA for when this will be implemented?
I don't see any reference to this in the "In progress, planned, and non-planned features" section of the readme.
Is there any workaround? thx
@rafaelss99, in fact there's a better example from the rival library: http://www.material-ui.com/#/components/drawer
Facebook-backed JS library has better material drawer (yes, they also use the official term) than Google-backed TS framework!
@AjawadMahmoud material-ui is for React.
Wasn't my comment clear enough, @airblader?
Well you are presenting it as an alternative to Angular Material. But it works with an entirely different technology.
This was just an example. At the end of the day it's JavaScript beneath it. I can rewrite the exact procedure back for Angular.
On Fri, 1 Dec 2017, 10:03 Ingo BΓΌrk, [email protected] wrote:
Well you are presenting it as an alternative to Angular Material. But it works with an entirely different technology.
β You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/angular/material2/issues/5712#issuecomment-348409445, or mute the thread https://github.com/notifications/unsubscribe-auth/AATVPmaVKb9QpeazZxuXF4QBP-hW7yhNks5s75atgaJpZM4OWUqo .
Polymer's swipeable sidenav is the only implementation I know of that enhances UX and it has been like that for at least two years: http://polymerelements.github.io/app-layout/templates/shrine A poor implementation (material-ui for instance) is worse than no implementation.
This is maybe a workaround but it works for the dialog should work for the sidenav to. This will require hammerjs.
Place a div around your content in the html:
<div style="width: 100%; height: 100%; position: absolute;" (swipeleft)="closeDialog()" (click)="closeDialog()">
Nothing new on this?
Currently using a forked ionic-split-pane to get a swipe/slideable sidenav: https://github.com/xcaliber-tech/ionic-split-pane
Which involved a lot of hacking and ripping out random ion dependencies on other unrelated things like ion-nav, ion-button and ion-content. Would be awesome to remove that monstrosity when swipe behaviour lands here :)
@Swoox's solution didn't work for me, but brought me to hammerjs and this solution:
app-container.component.scss
.app-container {
height: 100%;
width: 100%;
position: absolute;
}
app-container.component.html
<mat-sidenav-container class="app-container">
<mat-sidenav #sidenav>Sidenav content</mat-sidenav>
<mat-sidenav-content>
Main Content
</mat-sidenav-content>
</mat-sidenav-container>
app-container.component.ts
import { Component, Input, ElementRef, ViewChild } from '@angular/core';
import * as Hammer from 'hammerjs';
import { MatSidenav } from '@angular/material';
@Component({
selector: 'app-container',
templateUrl: './app-container.component.html',
styleUrls: ['./app-container.component.scss']
})
export class AppContainerComponent {
@ViewChild(MatSidenav)
public sidenav: MatSidenav;
constructor(elementRef: ElementRef) {
const hammertime = new Hammer(elementRef.nativeElement, {});
hammertime.on('panright', (ev) => {
this.sidenav.open();
});
hammertime.on('panleft', (ev) => {
this.sidenav.close();
});
}
}
It works as long as the content doesn't exceed the width of 100%, otherwise it will scroll the page and open the menu.
Thanks @maxfriedmann works like a charm!!! π π π π π π π π π
Thanks @maxfriedmann, If you need to prevent closing when you want to scroll up/down when your sidenav is more thant 100% height then add the following to your code :
const hammertime = new Hammer(elementRef.nativeElement, {});
hammertime.get('pan').set({direction:` Hammer.DIRECTION_ALL});
hammertime.on('panright', (ev) => {
this.sidenav.open();
});
hammertime.on('panleft', (ev) => {
this.sidenav.close();
});
hammertime.on('panup', (ev) => false);
hammertime.on('pandown', (ev) => false);
anyway...isn't this deadly to performance? I removed it since on mobile I'm wrapping the app in Ionic 3.9..
@maxfriedmann Like you solution but what if you add another drawer on the right side? How would you solve that?
I haven't had that problem, only used a single drawer.
Please have a look at https://hammerjs.github.io/recognizer-pan, you actually get the start and stop positions of the pan action. You could e.g. split the screen in 1/3 and 2/3 and decide programmatically, which drawer to open...
@maxfriedmann thx for pointing me in the right direction... but at this time it needs to much work to fine tune so I need to wait for a better and proper implementation.
@jelbourn is there any work started on you end for this feature?
If you only want to check for touch device swipes (and not mouse drags on desktop), you can check the event.pointerType property.
hammertime.on('panright', (event) => {
if (event.pointerType !== 'mouse') {
this.sidenav.open();
}
});
hammertime.on('panleft', (event) => {
if (event.pointerType !== 'mouse') {
this.sidenav.close();
}
});
@PascalTemel Didn't try this, since we decided to remove this snippet from the desktop and use the native menu in ionic...but, nice approach.
A slightly better option is to use the HostListener decorator. Then there is no need to create a new Hammer instance. For example, place this into the root AppComponent:
@HostListener('panright')
openSidenav() {
// open the sidenav
}
@HostListener('panleft')
closeSidenav() {
// close the sidenav
}
Does this implementation have any drawbacks ? (memory leaks, performance issues) Kind regards
Does this functionality not present issues in mobile browsers (like Chrome iOS) where a similar gesture is used for navigate forward and back in your history?
Hello everyone and thank you for those spectacular contributions. In my case they have helped me a lot. But I have a small inconvenience:
- Is it possible through Hammer to improve the animation performance of the sidenav?
When I open and close the sidenav, it has a lot of lag in the mobile devices, I have looked for how to change that for CSS and I have tried many solutions, but none has served me. I'm using Angular Material 7.3.1
- Is there any solution through Hammer or any other way that really works to improve the animation performance of sidenav?
And an even bolder question.
- Is it possible any solution through Hammer to move the sidenav according to touch of the finger? there is a very old library that does it and I have it for reference. http://jakiestfu.github.io/Snap.js/demo/apps/default.html
Thank you so much for the help you can give me.
This is my contribution for the sidenav to react on the left side of the screen to open.
const hammertime = new Hammer(elementRef.nativeElement, {});
hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL });
hammertime.on('panright', event => {
if (
event.pointerType !== 'mouse' &&
event.center.x >= 1 && event.center.x <= 50
) {
this.sidenav.open();
}
});
hammertime.on('panleft', event => {
if (event.pointerType !== 'mouse') {
this.sidenav.close();
}
});
hammertime.on('panup', event => false);
hammertime.on('pandown', event => false);
We really need a clean solution for that. Simply triggering the open is not an option.
Users are used to deferring the SideNav slowly. Depending on the slide progress, the cdk background layer must appear.
For example, with mode = "push", the content is moved slowly. Once more than 50% of the Sidenav wide is swiped, let the sidenav slide on. Less than 50% let go again.
Everything else is not a viable solution :)
We really need a clean solution for that. Simply triggering the open is not an option.
Users are used to deferring the SideNav slowly. Depending on the slide progress, the cdk background layer must appear.
For example, with mode = "push", the content is moved slowly. Once more than 50% of the Sidenav wide is swiped, let the sidenav slide on. Less than 50% let go again.
Everything else is not a viable solution :)
yes it should work exactly like it would in android studio, thinks like this is what makes your pwa feel native
Any update on this?