Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mobile cannot scroll data with overflow scroll of css #10

Open
CHUN-WEI-HSU opened this issue Dec 10, 2018 · 30 comments
Open

mobile cannot scroll data with overflow scroll of css #10

CHUN-WEI-HSU opened this issue Dec 10, 2018 · 30 comments

Comments

@CHUN-WEI-HSU
Copy link

CHUN-WEI-HSU commented Dec 10, 2018

I cannot scroll data with ion-list, even I used following code, hammerjs still influence child elements.

	ion-bottom-drawer{
		.scroll-content{
		    touch-action: auto !important;
		}		
	}

this is good plugin. thanks your assistance,
sorry for my bad english.

@Kernolsie
Copy link

My workaround fix:

Add a scrollable div with a fixed height in the drawer:

<div scrollY="true" id="myScrollDiv">
   your contents or list or whatever
<div>

and on the CSS side:

#myScrollDiv {
  height: 150px;
}

div[scrollx=true], div[scrolly=true] {
  position: relative;
  overflow: hidden;

  ::-webkit-scrollbar {
    display: none;
  }
}

div[scrollx=true] {
  overflow-x: auto;
}

div[scrolly=true] {
  overflow-y: auto;
}

The problem is that the scrolling of the inner div influences the parent drawer to move, we don't want that, so:

Now, you want only the top of your drawer to have a draggable item (you can style this div and size it as your heart desires) which Enables or Disables the disableDrag property of the ion-bottom-drawer on its (touchstart) and (touchend) events. The dashScrollDisabled is a boolean in my class which is toggled by the drawerActuator div as seen below:

<ion-bottom-drawer [(state)]="state" [minimumHeight]="80" [dockedHeight]="80" [shouldBounce]="true"
    [distanceTop]="distanceFromTop" [disableDrag]="dashScrollDisabled">
  <div class="drawer-content" style='height:100%'>
    <div class='drawerActuator' (touchstart)='enableDashScroll()' (touchend)='disableDashScroll()'> 
    </div>
    <div scrollY="true" id="myScrollDiv">
       your contents or list or whatever
    <div>
  <div>
</ion-bottom-drawer>

@SirBenedick
Copy link

@Kernolsie it seems like your solution does not work on mobile.
My browser is fine but using the DevApp there is no scroll functionality.
Any suggestions?

@Kernolsie
Copy link

@SirBenedick My implementation is on mobile so I doubt that it is the problem. Is there enough items in your list to overflow the div so that you have something to scroll to? Explain what happens then, is everything including the drawer just stationary or what? iOS or Android?

@SirBenedick
Copy link

SirBenedick commented Jul 10, 2019

@Kernolsie test DevApp with iOS. Using the --lab flag my implementation works fine on android and iOS.
I used you css (only changed the height to 300px)
There are two lists and one card included in myScrollDiv. The lists are definitely long enough.
Not quit sure what you mean with 'stationary'. The drawer is always visible on the 'home' page and the contend within the drawer depends on what is selected.

Thanks for helping 🙏

<h1>{{ selectedLocation.title }}</h1>
<div scrollY="true" id="myScrollDiv">
    <ion-item-group *ngIf="selectedLocation.food">
        [...]
    </ion-item-group>
    <ion-item-group *ngIf="selectedLocation.drinks">
        [...]
    </ion-item-group>
    <ion-card>
        [...]
    </ion-card>
</div>

@SirBenedick
Copy link

@Kernolsie could you upload a working example?
I tried to replicate it again, but I can not get it working.

@IvanMoreFlores
Copy link

@Kernolsie
Sorry, but you could show the .ts code and the .css of this code, I've been trying to solve the scroll problem for several days, thanks

<div class='drawerActuator' (touchstart)='enableDashScroll()' (touchend)='disableDashScroll()'> 
    </div>

@jsmith347
Copy link

jsmith347 commented Aug 23, 2019

@IvanMoreFlores @toniantunovi This seems to be an issue with hammerjs handling the pan events for the ion-bottom-drawer

My workaround that worked on iOS and Android was to copy the ion-bottom-drawer folder at:

https://github.com/toniantunovi/ion-bottom-drawer/tree/master/src/app/modules/ion-bottom-drawer

and pasting it into my projects components folder and including the copied version where I use the component.

The following change must then be made in the ion-bottom-drawer.ts file:

hammer.get('pan').set({ enable: true, direction: Hammer.DIRECTION_VERTICAL });

must be changed to:

hammer.get('pan').set({ enable: false, direction: Hammer.DIRECTION_VERTICAL }); at line 45.

@maximilianloy
Copy link

Same here. Was not working for me on iOS (Android was ok) but with workaround from @jsmith347 its working!

@prescindivel
Copy link

I tried with @IvanMoreFlores solution and it worked great on Android, but on ios the ion-bottom-drawer state property has stopped working, I use it to swap a "docked" and "undocked" class.

Bounce also stopped working on iOS.

I tried using @jsmith347 workaround but it didn't work on Android or ios

@synapp009
Copy link

synapp009 commented Sep 20, 2019

@Kernolsie solution works for me. Add this to your .ts :

export class yourApp {
shouldBounce = true;
}

enableDashScroll() {
this.disableDrag = false;
}
disableDashScroll() {
this.disableDrag = false;
}

@prescindivel is right: no Bounce-Animation any more

@raminnoodle
Copy link

raminnoodle commented Oct 7, 2019

I cant for the life of me get this working in iOS. Iv tried so many different methods to get scrolling within a drawer to work with no avail. It works fine in the browser but once it goes into the ios simulator or device it doesn't scroll. I tried using a copy of the component with the .get('pan') enabled: false but that totally turns off the ion drawer all the way.

@jsmith347
Copy link

jsmith347 commented Oct 8, 2019

@raminnoodle Have you set the minimumHeight and dockedHeight properties on the ion-bottom-drawer component?

Another thing that I found is that the container of your item list must have a fixed height. For example, in my code I used an ion-grid to hold my list items and defined the height as follows:

     <ion-grid style='height:228px' no-padding>
     ...
     </ion-grid>

@raminnoodle
Copy link

raminnoodle commented Oct 8, 2019

Yea I tried that and many other combinations but could never get it to work in the emulator or ios device (spent about 10 hrs). I am pretty sure hammerjs makes changes to the css properties that wont allow anything within the drawer to scroll. In the browser, it worked no problem but never on ios for me. I finally got it to work by using the actuator code mentioned above combined with downloading a local copy of the component source code and modifying it by adding code to the ngOnChange in the ion-bottom-drawer.ts to remove the hammerjs instance when disableDrag was set to true and re-enables hammerjs when the disableDrag is set to false. Finally got it to work!

@synapp009
Copy link

synapp009 commented Oct 8, 2019

Yea I tried that and many other combinations but could never get it to work in the emulator or ios device (spent about 10 hrs). I am pretty sure hammerjs makes changes to the css properties that wont allow anything within the drawer to scroll. In the browser, it worked no problem but never on ios for me. I finally got it to work by using the actuator code mentioned above combined with downloading a local copy of the component source code and modifying it by adding code to the ngOnChange in the ion-bottom-drawer.ts to remove the hammerjs instance when disableDrag was set to true and re-enables hammerjs when the disableDrag is set to false. Finally got it to work!

I created a <div>Bar in the ion-bottom-drawer.html that disable hammer.js with mousedown/touchstart and at <ion-content></ion-content> the opposit. :)

@raminnoodle
Copy link

raminnoodle commented Oct 8, 2019

I tried that as well but it seems that once the pan has been enabled the css doesnt go away when its disabled. I event tried https://hammerjs.github.io/toggle-recognizer/ to create an inline function for the boolean with no luck.
I used the code below to remove hammer and re-enable hammer when the disableDrag changes.

ngOnChanges(changes: SimpleChanges) {
if (changes.disableDrag) {
if (changes.disableDrag.currentValue) {
console.log("DISABLED!!!");
this.hammer.off("pan panstart panend", null);
this.hammer.remove("pan");
} else {
console.log("ENABLED!!!");
this.hammer.off("pan panstart panend", null);
this.hammer.remove("pan");
this.hammer = new Hammer(this._element.nativeElement);
this.hammer.get("pan").set({ enable: true, direction: Hammer.DIRECTION_VERTICAL });
this.hammer.on("pan panstart panend", (ev: any) => {
if (this.disableDrag) {
return;
}
switch (ev.type) {
case "panstart":
this._handlePanStart();
break;
case "panend":
this._handlePanEnd(ev);
break;
default:
this._handlePan(ev);
}
});
}
return;
}

@synapp009
Copy link

synapp009 commented Oct 8, 2019

No CSS involved. It's very simple:
ion-bottom-drawer.html:

<div (mousedown)="drawEnable()" (touchstart)="drawEnable()" style="height:30px;width:100%"> </div> <ion-content (mousedown)="drawDissable()" (touchstart)="drawDissable()" id="content" class="ion-bottom-drawer-scrollable-content" no-bounce > <ng-content ></ng-content> </ion-content>

ion-bottom-drawer.js:

`drawEnable(){
this.hammer.get('pan').set({ enable: true, direction: Hammer.DIRECTION_VERTICAL });
}

drawDissable(){
this.hammer.get('pan').set({ enable: false, direction: Hammer.DIRECTION_VERTICAL });
}`

At least in Xcode it works fine. Have you tested it on a real device?

@raminnoodle
Copy link

Are you using UIWebView or WKWebview?

@synapp009
Copy link

I'm using WKWebView by default ( "cordova-plugin-ionic-webview": "^4.1.1", )

@ericjmachado
Copy link

Same problem here, any solution?

@rlfrahm
Copy link

rlfrahm commented Jan 6, 2020

The following html/scss only solution worked for me as it allows the user to scroll through a list that is taller than the drawer content area. I can still drag the drawer closed using the top handle though too.

html

<ion-bottom-drawer [(state)]="fontFamilyDrawer.state" [distanceTop]="fontFamilyDrawer.minimumHeight">
  <div class="drawer-content">
    <!-- Step 1: A little handle to grab and drag with and close the drawer -->
    <div padding>
      <div style="background-color: var(--ion-color-medium-tint);width:4rem;height:.25rem;border-radius:6px;display:block;margin:0 auto"></div>
    </div>
    <!-- Step 2: `scrollY="true"` and set a fixed height for the scroll container -->
    <ion-list [style.height]="fontFamilyDrawer.contentHeight" style="overflow-y: auto">
      <!-- ... -->
    </ion-list>
  </div>
</ion-bottom-drawer>

scss

ion-bottom-drawer {
  [scrollY=true] {
    overflow-y: auto;
  }
}

Exhibit A:

Screen Shot 2020-01-05 at 7 00 41 PM

@jwburnside
Copy link

@rlfrahm Hey Ryan, thanks for this, it is working almost perfectly in my case. The only small issue is that when scrolling, the catch moves with the list content, so that it disappears from the top. I have been experimenting with trying to get the catch to remain at the top even after scrolling, but have not had much luck so far.

Are you seeing this same behavior? And if not, do you know how I might get the catch to stay visible even while scrolling?

I'm going to continue to mess with it, and will post my results if I succeed, thanks!

@DaniilVysotskiy
Copy link

@jwburnside I guess, I've found simple way to control the way the content section inside the drawer is scrolled on touch devices without effecting the drawer state and its position. The solution made up using only ionic native events and drawer options, and keeps up shouldBounce option:

component.html

<ion-bottom-drawer
  class="drawer"
  [(state)]="drawerOptions.drawerState"
  [minimumHeight]="drawerOptions.minimumHeight"
  [dockedHeight]="drawerOptions.dockedHeight"
  [shouldBounce]="drawerOptions.shouldBounce"
  [distanceTop]="drawerOptions.distanceTop"
  [disableDrag]="drawerOptions.disableDrag"
>
  <div class="drawer-content">
    <div class="drawer-toolbar"> // <- Drawer pull-up/pull-down handler area
      <...>
    </div>
    <div
      class="drawer-body"
      (touchstart)="drawDisable()"
      (touchend)="drawEnable()"
    > // <- Drawer inner content area with scrollable list
      <...>
  </div>
</ion-bottom-drawer>

component.ts

// component imports

export class Component implements OnInit {
  drawerOptions: any = {
    shouldBounce: true,
    dockedHeight: 85,
    distanceTop: 56,
    drawerState: DrawerState.Docked,
    states: DrawerState,
    disableDrag: false, // <- By default drag gesture is enabled
    minimumHeight: 85
  };

  constructor( ... ) { ... }

  drawEnable() {
    this.drawerOptions.disableDrag = false;
  }

  drawDisable() {
    this.drawerOptions.disableDrag = true;
  }
}

component.scss

.drawer {
  box-shadow: 0px -1px 3px 0px rgba(0,0,0,.15);
}

.drawer-content {
  position: relative;
}

.drawer-toolbar {
  border-bottom: 2px solid var(--ion-color-light-warm);
  background-color: var(--ion-color-primary-contrast);
  position: fixed;
  top:0;
  left: 0;
  width: 100%;
  z-index: 2;
}

.drawer-body {
  transform: translateY(85px);
  height: calc(100vh - 85px - 56px);
  overflow-y: auto;
}

@rlfrahm
Copy link

rlfrahm commented Jan 30, 2020

@rlfrahm Hey Ryan, thanks for this, it is working almost perfectly in my case. The only small issue is that when scrolling, the catch moves with the list content, so that it disappears from the top. I have been experimenting with trying to get the catch to remain at the top even after scrolling, but have not had much luck so far.

Are you seeing this same behavior? And if not, do you know how I might get the catch to stay visible even while scrolling?

I'm going to continue to mess with it, and will post my results if I succeed, thanks!

I'm unfortunately not in front of the project right now, but only my ion-list was scrolling, not the handle. First thing to make sure is that your handle div is outside of the container that you have [scrollY=true] set true on. The second thing is that you have to have [style.height] set for the element that you want to overflow scroll, otherwise I believe the scrolling will bubble up to the parent elements (which sounds like your problem). The way that I test to see what changes I need made is to open up the browser console and just inline edit your drawer to figure out what is going wrong.

1 similar comment
@rlfrahm
Copy link

rlfrahm commented Jan 30, 2020

@rlfrahm Hey Ryan, thanks for this, it is working almost perfectly in my case. The only small issue is that when scrolling, the catch moves with the list content, so that it disappears from the top. I have been experimenting with trying to get the catch to remain at the top even after scrolling, but have not had much luck so far.

Are you seeing this same behavior? And if not, do you know how I might get the catch to stay visible even while scrolling?

I'm going to continue to mess with it, and will post my results if I succeed, thanks!

I'm unfortunately not in front of the project right now, but only my ion-list was scrolling, not the handle. First thing to make sure is that your handle div is outside of the container that you have [scrollY=true] set true on. The second thing is that you have to have [style.height] set for the element that you want to overflow scroll, otherwise I believe the scrolling will bubble up to the parent elements (which sounds like your problem). The way that I test to see what changes I need made is to open up the browser console and just inline edit your drawer to figure out what is going wrong.

@rlfrahm
Copy link

rlfrahm commented Jan 30, 2020 via email

@roman-rr
Copy link

Hello everyone, don’t sure if this repo under regular maintenance.
So try similar component with correct overflow implementation
https://github.com/roman-rr/cupertino-pane/

@raminnoodle
Copy link

Hello everyone, don’t sure if this repo under regular maintenance.
So try similar component with correct overflow implementation
https://github.com/roman-rr/cupertino-pane/

Exactly what iv been looking for! Thank you!

@SackeyDavid
Copy link

The following html/scss only solution worked for me as it allows the user to scroll through a list that is taller than the drawer content area. I can still drag the drawer closed using the top handle though too.

html

<ion-bottom-drawer [(state)]="fontFamilyDrawer.state" [distanceTop]="fontFamilyDrawer.minimumHeight">
  <div class="drawer-content">
    <!-- Step 1: A little handle to grab and drag with and close the drawer -->
    <div padding>
      <div style="background-color: var(--ion-color-medium-tint);width:4rem;height:.25rem;border-radius:6px;display:block;margin:0 auto"></div>
    </div>
    <!-- Step 2: `scrollY="true"` and set a fixed height for the scroll container -->
    <ion-list [style.height]="fontFamilyDrawer.contentHeight" style="overflow-y: auto">
      <!-- ... -->
    </ion-list>
  </div>
</ion-bottom-drawer>

scss

ion-bottom-drawer {
  [scrollY=true] {
    overflow-y: auto;
  }
}

Exhibit A:

Screen Shot 2020-01-05 at 7 00 41 PM

Hi @rlfrahm,

How did you get the border radius of the ion-bottom-drawer?

@rlfrahm
Copy link

rlfrahm commented Jun 13, 2020

It’s been a while since I did this but I just opened up the Safari console’s elements tab and started applying border-radius until it changed it on the screen.

@SackeyDavid
Copy link

It’s been a while since I did this but I just opened up the Safari console’s elements tab and started applying border-radius until it changed it on the screen.

Ok, thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests