JoshDSommer / nativescript-slides

A NativeScript plugin that is for Intro Tutorials, Image Carousels or any other slide functionality
Other
70 stars 32 forks source link

Troubles with sliding when SlideContainer is inside of ScrollView on Android #72

Open terreb opened 7 years ago

terreb commented 7 years ago

I have a special case: SlideContainer is inside vertical ScrollView. For iOS sliding works ok, but on Android it looks like the ScrollView intercepts the panning at some point and it gets pretty difficult to change the slides. Especially from left to right.

The code to test.

XML:

            <Page xmlns="http://schemas.nativescript.org/tns.xsd"
                  xmlns:Slides="nativescript-slides"
                  navigatingTo="navigatingTo">
                <ScrollView id="scrollView">
                    <Repeater id="repeater" horizontalAlignment="center" width="100%"
                              items="{{ slideGroups }}">
                        <Repeater.itemTemplate>

                            <Slides:SlideContainer loaded="onSlideContainerLoaded"
                                                   horizontalAlignment="center">
                            </Slides:SlideContainer>

                        </Repeater.itemTemplate>
                    </Repeater>
                </ScrollView>
            </Page>

TS:

main-page.ts

            import {EventData} from 'data/observable';
            import {Page} from 'ui/page';
            import {MyModel} from './main-view-model';
            import * as labelModule from 'ui/label'
            import * as slides from 'nativescript-slides/nativescript-slides'

            export function navigatingTo(args:EventData) {
                let page = <Page>args.object;
                page.bindingContext = new MyModel();
            }

            export function onSlideContainerLoaded(args) {
                let slideContainer = <slides.SlideContainer>args.object;

                //Construct the slides
                slideContainer.addChild(getSlide("Slide 1", "slide-1"));
                slideContainer.addChild(getSlide("Slide 2", "slide-2"));
                slideContainer.addChild(getSlide("Slide 3", "slide-3"));
                slideContainer.addChild(getSlide("Slide 4", "slide-4"));
                slideContainer.addChild(getSlide("Slide 5", "slide-5"));

            }

            function getSlide(labelText: string, className: string)  {
                let slide = new slides.Slide();
                slide.className = className;
                let label = new labelModule.Label();
                label.text = labelText;
                slide.addChild(label)

                return slide;
            }

main-view-model.ts

            import {Observable} from 'data/observable';
            import {ObservableArray} from 'data/observable-array';

            export class MyModel extends Observable {
                public slideGroups
                constructor() {
                    super();
                    this.slideGroups = new ObservableArray([1,2,3])
                }
            }

CSS:

            SlideContainer {
                height: 400;
            }

            .slide-1{
                background-color: darkslateblue;
            }

            .slide-2{
                background-color: darkcyan;
            }
            .slide-3{
                background-color: darkgreen;
            }

            .slide-4{
                background-color: darkgoldenrod;
            }
            .slide-5{
                background-color: darkslategray;
            }
            Label{
                text-align: center;
                width: 100%;
                font-size: 35;
                margin-top: 35;
                horizontal-align: center;
                vertical-align: center;
            }

I understand this is not usual usage of the slides and probably a bad practice to have them inside ScrollView, but I have an app where I need to have them like this. Thank you for any advise or insight.

JoshDSommer commented 7 years ago

Unfortunately this has been an issue that has come up a couple times and I haven't found a good work around for it. If you figure something out please don't hesitate to post it here or a PR it would be greatly appreciated.

In the mean time i'm adding a note in the documentation about it. Thanks again.

terreb commented 7 years ago

The thing is the plugin fires the "start" event no matter how we drag slides (horizontally or vertically). If it would fire this event only when slides are dragged horizontally I could just disable the scroll view like I described here: http://stackoverflow.com/questions/36773101/nativescript-how-to-programmatically-disable-enable-scrollview-scrolling/36842883#36842883 ...and then enable it back on "finish" or "canceled" Horizontal dragging would mean the user wants to interact with slides, but when the user initiates vertical drag he wants to scroll the view.

patrickpereira commented 7 years ago

Did anybody have luck with a solution to this one?

manijak commented 7 years ago

Would be great if @tereb's idea could be implemented. I am using this in a "pull-to-refresh" container with ScrollView. So the entire UI experience feels kinda "all over the place", starts sliding left/right when trying to refresh or scroll down. This is iOS... but still.

This is the issue right here: https://github.com/TheOriginalJosh/nativescript-slides/issues/66

The funny thing is... In that same ScrollView, under the Slides control, I have another ScrollView that has a orientation="horizontal". When swiping left/right on it, the scroll is disabled, and when scrolling on it, the swipe is disabled. But that is not the issue on this Slides plugin.

markphoom commented 6 years ago

I got the same problem too and I fixed this (tested only iOS) by using swipe gestures with scrollView.ios.scrollEnabled variable https://docs.nativescript.org/angular/code-samples/ui/gestures https://stackoverflow.com/questions/36773101/nativescript-how-to-programmatically-disable-enable-scrollview-scrolling/36842883#36842883

This is the example of how I fix the problem using vanilla javascript

.xml

<GridLayout swipe="{{disableScrollWhenSlideLeftorRight}}">
<Slides:SlideContainer>
        .....
</Slides:SlideContainer>

javascript

disableScrollWhenSlideLeftorRight: function(args){
        var scrollView = page.getViewById('YOUR_VIEW_ID');
    if (args.direction == 1 || args.direction == 2){//left and right direction
        scrollView.ios.scrollEnabled = false;
    }
    else{
         component.bindingContext.scrollView.ios.scrollEnabled = true;
    }
}

and don't forget to enable scrollenabled where necessary by using enable scroll function

<ListView swipe="{{enableScroll}}" .....>

function enableScroll: function(args){
        var scrollView = page.getViewById('YOUR_VIEW_ID');
    scrollView.ios.scrollEnabled = true;
}
vahidvdn commented 6 years ago

I found a solution for this. (tested only in android) :

in app.android.css (seems that app.css doesn't work)

.slides {
  // without this, it doesn't work with ScrollView
  height: 240;
}
.slide-1{
    background-color: #448AFF;
  }

  .slide-2{
    background-color: #F44336;
  }
  .slide-3{
    background-color: #8BC34A;
  }
.slide-indicator-inactive{
    background-color: #000;
    opacity : 0.4;
    width : 10;
    height : 10;
    margin-left : 2.5;
    margin-right : 2.5;
    margin-top : 0;
    border-radius : 5;
}

.slide-indicator-active{
    background-color: #000;
    opacity : 0.9;
    width : 10;
    height : 10;
    margin-left : 2.5;
    margin-right : 2.5;
    margin-top : 0;
    border-radius : 5;
}

In view:

<ScrollView>
    <StackLayout>

        <!-- Add 'slides' class to StackLayout in order to get them work within ScrollView -->
        <StackLayout class="slides">
            <slides class="slides" loop="true" [pageIndicators]="true" [swipeSpeed]="20" pageHeight="100%" footerMarginTop="70%">
                <slide class="slide-1">
                    <Image style="height: 250" src="http://sazmand.com/images/projects/sazmand-retro-tour.png"></Image>
                </slide>
                <slide class="slide-2">
                    <Image style="height: 250" src="http://sazmand.com/images/projects/sazmand-retro-tour.png"></Image>
                </slide>
                <slide class="slide-3">
                    <Image style="height: 250" src="http://sazmand.com/images/projects/sazmand-retro-tour.png"></Image>
                </slide>
            </slides>
        </StackLayout>

        <StackLayout>
            <Label text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam eget rutrum tortor. Suspendisse aliquet, magna vel suscipit ullamcorper, nibh mi fringilla nulla, eu vehicula mi arcu eu ipsum. Nunc non diam nibh. Nullam ullamcorper vehicula dui, ut porttitor libero. Integer sit amet magna non velit vehicula efficitur sit amet ut nulla. Sed purus ante, placerat id odio at, lobortis aliquam enim. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet velit urna, scelerisque varius justo vulputate nec. Etiam ultrices elementum massa a maximus.

Maecenas consequat diam erat, a egestas libero facilisis eget. Phasellus tristique purus nec diam tincidunt lacinia. Nam quis porttitor elit. Vestibulum malesuada est ac tempus accumsan. Donec porttitor nulla et nisi pretium, ac efficitur sapien tincidunt. Praesent cursus urna a efficitur egestas. Nunc sed augue velit. Donec sagittis sagittis efficitur. Vestibulum et tortor in purus tincidunt mollis in et enim. Donec at placerat enim.

Sed libero nisi, pulvinar eget turpis pretium, consectetur tincidunt nibh. Sed et purus rutrum, pharetra justo eu, rhoncus metus. Mauris ac luctus nulla. In vulputate suscipit nisi eu molestie. Aliquam ornare, mauris vitae vestibulum sagittis, risus mauris viverra dolor, a pretium nibh odio quis massa. Cras purus ante, porttitor porttitor nisi sed, dictum cursus nisl. Mauris aliquet malesuada odio, vel feugiat odio dignissim hendrerit. Nam tempor felis porta quam pellentesque, vel tincidunt massa tincidunt. Nulla sit amet tincidunt quam. Proin vestibulum eros tellus. In ipsum nisl, tempor et lobortis nec, auctor in nulla. Suspendisse efficitur metus sit amet orci congue convallis. Proin id leo lorem. In at tellus at odio lobortis laoreet eu sit amet eros. Nullam vel congue leo. Maecenas eu pretium magna.

Nam aliquet, tellus at laoreet congue, libero mauris finibus neque, quis fringilla odio nisi vel nibh. Cras egestas sodales imperdiet. Curabitur interdum volutpat lorem, sit amet tincidunt libero blandit ut. Praesent a mi malesuada, fringilla augue quis, interdum tortor. Etiam sit amet mattis tellus, et interdum urna. Donec non leo laoreet, aliquet sem at, aliquet velit. Etiam id lobortis magna. Pellentesque egestas porttitor felis eu interdum. Mauris egestas, purus eget tincidunt tincidunt, turpis nibh hendrerit nisi, vel scelerisque quam risus mattis augue. Aliquam molestie, mi vitae bibendum luctus, diam justo posuere risus, id porttitor massa ligula ullamcorper nisi. Aliquam commodo mauris eu congue convallis. Quisque auctor vitae enim ac vestibulum. Vestibulum non massa eget augue viverra dapibus eget at turpis. Praesent lacinia, magna nec porttitor fermentum, quam lectus pulvinar velit, eget eleifend augue purus eget ligula. Pellentesque eget quam ac felis sagittis venenatis eu quis neque.

Vivamus auctor bibendum finibus. Maecenas lobortis felis sed semper finibus. Nulla condimentum quis massa vitae consequat. Sed pulvinar dapibus lorem, vel finibus ex aliquet sed. Pellentesque placerat tortor eget mauris faucibus, sed porttitor quam molestie. Donec tellus velit, porttitor ut magna sed, finibus pulvinar magna. Cras eu odio in diam ultricies bibendum." textWrap="true"></Label>
        </StackLayout>

    </StackLayout>
</ScrollView>

photo_2018-08-27_17-52-58