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

Slidebox swipe sensitivity too high, vertical scroll + tap-hold extremely poor in Android 4.4.4 #2317

Closed
marcsyp opened this issue Sep 30, 2014 · 24 comments

Comments

@marcsyp
Copy link

marcsyp commented Sep 30, 2014

I have scrollable content in each slide of an Ionic slide-box.

Everything worked perfectly, great user experience until I updated my Galaxy S5 from 4.4.2 to 4.4.4 this morning. Now the UX is an absolute nightmare. Scrollable content inside a slidebox is very difficult to work with. Side to side swiping sensitivity is super super high and prevents vertical scrolling unless absolutely perfectly vertical.

Tap-hold gestures are also really difficult to engage (again due to the side to side swipe sensitivity).

I have noticed this on my wife's Nexus 5 as well (which has always been running 4.4.4).

I am going to need to find a solution to this ASAP, since my Galaxy S5 is my primary demo device and it is a total train-wreck to work with now.

I recently updated to Ionic beta13, no change. As in, a complete app UX fail, an embarrassment to have out in the wild. :(

I also uninstalled the Chrome update that came with Android 4.4.4 (37->35) in the hopes that the WebView would be downgraded to a previous version, no luck.

I'm wondering if there is something specific about my HTML setup, or what else I could provide to get at the issue. I'm surprised I haven't seen more activity on this issue, because it is making my previously smooth app completely useless. Obviously I'm a bit exasperated. Anyway, it leads me to believe that it is an isolated problem, but I don't know where to start.

Attached is an HTML template where this is happening to me. Any thoughts greatly appreciated.

    <ion-view title="LOVE.">
    <ion-nav-buttons side="left">
        <button ng-if="activeSearchSlide == 2" class="button no-animation button-icon icon ion-ios7-arrow-back" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);" ng-click="clearSearch()">
        </button>   
    </ion-nav-buttons>
    <ion-nav-buttons side="right">
        <button class="button no-animation button-icon icon ion-ios7-gear" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); float: left;" on-tap="gotoSettings()" on-hold="holdMe()">
        </button>
        <button class="button no-animation button-icon icon ion-ios7-paperplane" style="-webkit-user-select: none; -webkit-user-drag: none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);" on-tap="sendFeedback()" on-hold="holdMe()">
        </button>
    </ion-nav-buttons>
    <ion-content has-header="true" >  
        <ion-slide-box does-continue="false" auto-play="false" active-slide="activeSearchSlide" on-slide-changed="slideChanged(index)">

            <ion-slide>
                <div>

                    <label class="tagLabel" on-tap="clickTag()" on-hold="tagMenu($index, tag)" ng-repeat="tag in templates.categories track by $index" style="{{tag.checked | myTagStyle}}"> 
                        <p>{{tag.name}}<span ng-show="!tag.active">*</span><span class="searchCount">{{tag.bundleCount}}</span></p>
                    </label>

                    <form ng-submit="addTag(newTagText)">
                        <div>
                        <div style="border-left: none; border-top: none; border-bottom: none; border-right: 40px solid #f8f8f8">
                            <input type="text" id="inputText" ng-model="newTagText" placeholder="new tag category...">
                        </div>
                        </div>
                    </form>
                </div>
                <br/>
                <br/>
                <br/>
                <br/>
            </ion-slide>
            <ion-slide>
                <div ng-if="!somethingSelected" >
                <br/>
                <br/>
                <br/>
                <br/>
                <br/>
                <br/>
                <p style="font-size:45pt;color:#DDD;">
                ???
                </p>
                </div>   
                <div>
                    <div ng-repeat="tag in templates.categories track by $index" ng-show="tag.checked" class="check-element animate-show" >
                            <label class="tagLabel" on-tap="clickTag()" on-hold="tagMenu($index, tag)" style="{{tag.checked | myTagStyle}}">                            
                                <p>{{tag.name}}<span ng-show="!tag.active">*</span><span class="searchCount">{{tag.bundleCount}}</span></p>
                            </label>
                            <label class="tagLabel" on-tap="clickSubTag($parent)" on-hold="subTagMenu($index, item)" ng-repeat="item in tag.items track by $index" style="{{item.checked | myTagletStyle}}" >

                                <p><span style='display:inline-block;'>&nbsp;&nbsp;</span>{{item.name}}<span ng-show="!item.active">*</span><span class="searchCount">{{item.bundleCount}}</span></p>
                            </label>
                        <form ng-submit="addSubTag()">
                            <div>
                                <div>
                                    <input type="text" class="subtagTextInput" id="inputText" placeholder="new {{tag.name}} taglet..." ng-model="inputText">
                                </div> 
                            </div>    
                        </form>
                        <br/>
                    </div> 
                </div>
                <br/>
                <br/>
                <br/>
                <br/>
            </ion-slide>
            <ion-slide style="padding-left: 3px; padding-right: 3px;">

                            <h1>{{searchString}}</h1>

                            <div ng-repeat="bundle in searchResults track by $index | orderBy:attributes.timestamp:reverse">
                                <div on-tap="viewBundle($index)" on-hold="openBundleModal($index, bundle)" style="background-image: url('{{bundle.firstThumb}}');" class="item {{bundle.attributes.tagged | paintUntagged}}">
                                    <div class="bundleCount"><p>{{bundle.URLcount}}</p></div>
                                </div>
                            </div>
            </ion-slide>
        </ion-slide-box>
    </ion-content>
    <div>
        <button ng-if="locked && overLimit && onSearchPage" class="button button-energized inAppPurchase" ng-click="unlockApp()">{{searchLimit}}/{{totalBundles}}</button>
    </div>
@dbaq
Copy link

dbaq commented Sep 30, 2014

@marc, I can confirm this issue.

I have no time to write a codepen but put a simple ion refresher inside a slide box and you can reproduce it. It is also doing that on my nexus 5 android 4.4.
Note: as far as I know I haven't noticed this issue on iOS (with the exact same code)

@marcsyp
Copy link
Author

marcsyp commented Sep 30, 2014

@dbaq, thanks for confirming. I thought I was going crazy over here, surprised that very few people are talking about this.

I can also confirm that my code works fine in iOS 7.1 and Android 4.4.2, it's only a problem with the 4.4.4 update. Unfortunately, this update is stock OS for all Nexus 5 devices and is rolling out currently to most high-end Android phones if they don't already have it.

@marcsyp
Copy link
Author

marcsyp commented Oct 3, 2014

@mlynch @mhartington

Still wondering why people aren't flocking to this thread in droves and why there has been no response from the Ionic team. The scroll inside Slidebox problem exists in emulators and codepens of all varieties as well. Using Chrome Version 37.0.2062.124 m.

Try scrolling down in this list within a Slide Box:

http://codepen.io/calendee/pen/sofdv

My app is dead in the water until I can resolve this issue. Perhaps it's not an Ionic issue, but I am seeking some direction. Any thoughts???

Thanks,
Marc

@marcsyp
Copy link
Author

marcsyp commented Oct 6, 2014

Happy to see an assignment here! I will be very very thankful if this is resolved, will tweet to the high heavens with joy.

Anyway, wanted to add another bit of detail.

There is another part of my app where I am using rn-carousel instead of a slidebox for swipeable content. I am also having the same problem not being able to tap-hold inside the carousel without being absolutely perfectly still with my touch. The behaviour is slightly different in that even on a failed tap-hold I don't see the horizontal swipe engage at the moment of touch, but if I move left or right it is indeed engaged.

Anyway, thanks for taking this on.

Marc

@marcsyp
Copy link
Author

marcsyp commented Oct 7, 2014

Don't know if this is helpful, but I ran across a known bug in Chrome + hammer that is affecting the scrollability of the Angular carousel, perhaps it has some relationship to the problem in the Slidebox as well:

https://github.com/hammerjs/hammer.js/wiki/How-to-fix-Chrome-35--and-IE10--scrolling-(touch-action)

ajoslin added a commit that referenced this issue Oct 8, 2014
Closes #2336. Closes #2317. Closes #2290. Closes #2228. Closes #2067.
Closes #1890. Closes #1865. Closes #1850. Closes #1755. Closes #1688.
Closes #1578. Closes #1501. Closes #1353. Closes #1342. Closes #782.
Closes #416. Closes #2288.

BREAKING CHANGE: The slideBox's API has undergone many changes.

- **`<ion-slide-box>`** attributes have changed (see
  [documentation](http://ionicframework.com/docs/api/directive/ionSlideBox)):

  * `active-slide` has changed to `selected`. Change your code from
  this:

    ```html
    <ion-slide-box active-slide="activeSlideIndex"></ion-slide-box>
    ```

    To this:

    ```html
    <ion-slide-box selected="activeSlideIndex"></ion-slide-box>
    ```

  * `does-continue` has changed to `loop`.  Change your code from this:

    ```html
    <ion-slide-box does-continue="shouldLoop"></ion-slide-box>
    ```

    To this:

    ```html
    <ion-slide-box loop="shouldLoop"></ion-slide-box>
    ```

  * `auto-play` and `slide-interval` have been merged into `auto-play`.
  Change your code from this:

    ```html
    <!-- autoPlay is on -->
    <ion-slide-box auto-play="true" slide-interval="1000">
    </ion-slide-box>
    <!-- autoPlay is off -->
    <ion-slide-box auto-play="false" slide-interval="1000">
    </ion-slide-box>
    ```

    To this:

    ```html
    <!-- autoPlay is on -->
    <ion-slide-box auto-play="1000"></ion-slide-box>
    <!-- autoPlay is off -->
    <ion-slide-box auto-play="false"></ion-slide-box>
    ```

  * `show-pager` and `pager-click` have been removed. Use
  a child `<ion-slide-pager>` element. See the [`ion-slide-pager`
  documentation](http://ionicframework.com/docs/api/directive/ionSlidePager).
  Change your code from this:

  ```html
  <!-- pager using default click action -->
  <ion-slide-box show-pager="true">
  </ion-slide-box>
  <!-- pager with custom click action -->
  <ion-slide-box show-pager="true" pager-click="doSomething(index)">
  </ion-slide-box>
  ```

  To this:

  ```html
  <ion-slide-box>
    <!-- pager using default click action -->
    <ion-slide-pager></ion-slide-pager>
  </ion-slide-box>
  <ion-slide-box>
    <!-- pager with custom click action -->
    <ion-slide-pager ng-click="doSomething(index)"></ion-slide-pager>
  </ion-slide-box>
  ```

- **`$ionicSlideBoxDelegate`** methods have changed (see
  [documentation](http://ionicframework.com/docs/api/service/$ionicSlideBoxDelegate)):

  - `update()` has been removed. slideBox updates on its own now.

  - `stop()` has been removed. See `autoPlay()` below.

  - `start()` hass been removed. See `autoPlay()` below.

  - `slide(newIndex[, speed])` has been renamed to `select(newIndex[,
    speed]);

  - `currentIndex()` has been renamed to `selected()`.

  - `slidesCount()` has been renamed to `count()`.

  - New method `$ionicSlideBoxDelegate.autoPlay()`. Change your code
    from this:

    ```js
    // stop auto sliding
    $ionicSlideBoxDelegate.stop();
    // later... start auto sliding
    $ionicSlideBoxDelegate.start();
    ```

    To this:

    ```js
    var autoPlaySpeed = 3000; //wait 3000 seconds between changing slide
    // stop auto sliding
    $ionicSlideBoxDelegate.autoPlay(false);
    // later... start auto sliding
    $ionicSlideBoxDelegate.autoPlay(autoPlaySpeed);
    ```

  - `previous()` now returns the index of the previous slide and does
    not select. Change your code from this:

    ```js
    // select previous slide
    $ionicSlideBoxDelegate.previous();
    ```

    To this:

    ```js
    // select previous slide
    $ionicSlideBoxDelegate.select( $ionicSlideBoxDelegate.previous() );
    ```
  - `next()` now returns the index of the next slide and does
    not select. Change your code from this:

    ```js
    // select next slide
    $ionicSlideBoxDelegate.next();
    ```

    To this:

    ```js
    // select next slide
    $ionicSlideBoxDelegate.select( $ionicSlideBoxDelegate.next() );
    ```
@ajoslin ajoslin closed this as completed in 7ef9ad7 Oct 8, 2014
@marcsyp
Copy link
Author

marcsyp commented Oct 8, 2014

Spectacular. Looking forward to trying this out. Is it available only in the nightlies at this point?

@apavillet
Copy link

@marcsyp Just tried it and yes, it also breaks a lot of other things and docs is not up to date i think :)

@ajoslin
Copy link
Contributor

ajoslin commented Oct 8, 2014

Be sure to follow the migration guide, and use the nightly version of the docs for now.

On Oct 8, 2014, at 11:24, Adrien Pavillet [email protected] wrote:

@marcsyp Just tried it and yes, it also breaks a lot of other things and docs is not up to date i think :)


Reply to this email directly or view it on GitHub.

@apavillet
Copy link

@ajoslin Thanks where can i find the migration guide?

@ajoslin
Copy link
Contributor

ajoslin commented Oct 8, 2014

Here: 7ef9ad7

@ajoslin
Copy link
Contributor

ajoslin commented Oct 8, 2014

@marcsyp
Copy link
Author

marcsyp commented Oct 9, 2014

Well, I updated to the nightlies and refractor my code as per the changelog. The swipe sensitivity seems to be fixed. Yay.

However....

Scroll performance is really terrible inside the slide box. Like really terrible and not smooth at all. My code (see above) wouldn't scroll at all, so I wrapped the contents of the slide in an . Is that not the right thing to do?

Also troubling, the tap-hold directives are still not working well at all. In some cases, it seems worse than before.

Any thoughts? Should I open new issues?

@marcsyp
Copy link
Author

marcsyp commented Oct 9, 2014

In an ion-content

@ajoslin
Copy link
Contributor

ajoslin commented Oct 9, 2014

Marcysp, can you create a simple and concise codepen describing this problem in the latest version ? I haven't looked at the codepen you already posted; I want to be sure it's up to date and the use case is as small as possible.

Also, can you describe the exact platforms the problem occurs on and confirm the problems still happen on the same platforms?

If I'm going to look at this I need to be able to get at the root of the problem as quickly as possible. Hope you understand. Thank you.

@marcsyp
Copy link
Author

marcsyp commented Oct 9, 2014

I made a Cordova project with the tabs app base as the starter. Just added a few extra data items, put in a slide box, and changed the hrefs to on-taps. This is using the latest nightlies (downloaded today) and running on an Android 4.4.4 OS, Galaxy S5.

Not seeing the performance problems with this small project. On my full project, I get scrolling that stops dead in its tracks and is very choppy.

I am, however, still seeing the following:

  1. on-tap directives are very unreliable. They work maybe 1 out of 3 or 1 out of 5 times.
  2. The horizontal swipe is still a little too sensitive. When swiping my finger down in a natural hand holding position (to go up in a scroll view), I quite often get zoomed to the next page as if I performed a horizontal swipe from right to left (advancing the slidebox). You'll see this problem here, and in my full app it is particularly squirrelly because my interaction model involves firing specific events when swiping to the next slide... something you don't want to do by accident.

Here it is. Cordova 3.6.3, created with the latest Ionic CLI and built with Cordova CLI.

https://drive.google.com/file/d/0B1ClGdseCfJdM1I3TC1xSC1HXzQ/view?usp=sharing

@marcsyp
Copy link
Author

marcsyp commented Oct 9, 2014

Added a bit more of my project's detail to see if I could reproduce the performance problems. I start to get some slowdown when adding custom CSS but it's not as bad as in my full app. Not sure how to get to the bottom of that, please let me know if you have any pointers, I'm not proficient with profiling tools.

Here is the second version, with some extra CSS:

https://drive.google.com/file/d/0B1ClGdseCfJdYWwwSHlVRjlHRDQ/view?usp=sharing

Thanks.

ajoslin added a commit that referenced this issue Oct 9, 2014
@ajoslin
Copy link
Contributor

ajoslin commented Oct 9, 2014

@Marcysp I just pushed a commit making it easier to scroll vertically (it gives you a few more pixels of horizontal room when deciding you're vertically scrolling).

@ajoslin
Copy link
Contributor

ajoslin commented Oct 9, 2014

Your click problem is twofold:

  1. You're using <label> elements. The point of <label> elements is that they don't accept clicks, they pass the click to a nearby input. Use <div>s instead and your clicks work.
  2. Use ng-click instead of on-tap. I'm not sure why we included onTap at all.

Your on-hold problem, I'm not sure.

@marcsyp
Copy link
Author

marcsyp commented Oct 9, 2014

Great.

Any thoughts on the tap-hold (on-hold) and performance issues? I can't fully recreate the performance issues, though there are performance lags in the demo project that could be studied. The tap-hold issue should be pretty obvious.

Thanks,
Marc

@marcsyp
Copy link
Author

marcsyp commented Oct 9, 2014

Sorry, we wrote those last messages in parallel.

Anyway, the on-tap has been working fine, in the past and currently. It's the tap-hold that has been the problem. Anyway, I will change in case there is some interference.

The on-hold problem definitely surfaced in Android 4.4.4. I thought it was related to the swipe sensitivity, but perhaps it is independent.

Thanks,
Marc

@ajoslin
Copy link
Contributor

ajoslin commented Oct 9, 2014

OK. Could you create a simpler codepen and open a separate issue for the onHold? I don't think it has to do with the swipe.

@marcsyp
Copy link
Author

marcsyp commented Oct 9, 2014

Have opened a new issue:

#2373

Incidentally, I changed to ng-click and now I know why I had changed it to on-tap. On-tap has a threshold which prevents the click handler from engaging if the click is beyond a certain length. Either way, it has no effect on the on-hold issue.

ajoslin added a commit that referenced this issue Oct 10, 2014
Closes #2336. Closes #2317. Closes #2290. Closes #2228. Closes #2067.
Closes #1890. Closes #1865. Closes #1850. Closes #1755. Closes #1688.
Closes #1578. Closes #1501. Closes #1353. Closes #1342. Closes #782.
Closes #416. Closes #2288.

BREAKING CHANGE: The slideBox's API has undergone many changes.

- **`<ion-slide-box>`** attributes have changed (see
  [documentation](http://ionicframework.com/docs/api/directive/ionSlideBox)):

  * `active-slide` has changed to `selected`. Change your code from
  this:

    ```html
    <ion-slide-box active-slide="activeSlideIndex"></ion-slide-box>
    ```

    To this:

    ```html
    <ion-slide-box selected="activeSlideIndex"></ion-slide-box>
    ```

  * `does-continue` has changed to `loop`.  Change your code from this:

    ```html
    <ion-slide-box does-continue="shouldLoop"></ion-slide-box>
    ```

    To this:

    ```html
    <ion-slide-box loop="shouldLoop"></ion-slide-box>
    ```

  * `auto-play` and `slide-interval` have been merged into `auto-play`.
  Change your code from this:

    ```html
    <!-- autoPlay is on -->
    <ion-slide-box auto-play="true" slide-interval="1000">
    </ion-slide-box>
    <!-- autoPlay is off -->
    <ion-slide-box auto-play="false" slide-interval="1000">
    </ion-slide-box>
    ```

    To this:

    ```html
    <!-- autoPlay is on -->
    <ion-slide-box auto-play="1000"></ion-slide-box>
    <!-- autoPlay is off -->
    <ion-slide-box auto-play="false"></ion-slide-box>
    ```

  * `show-pager` and `pager-click` have been removed. Use
  a child `<ion-slide-pager>` element. See the [`ion-slide-pager`
  documentation](http://ionicframework.com/docs/api/directive/ionSlidePager).
  Change your code from this:

  ```html
  <!-- pager using default click action -->
  <ion-slide-box show-pager="true">
  </ion-slide-box>
  <!-- pager with custom click action -->
  <ion-slide-box show-pager="true" pager-click="doSomething(index)">
  </ion-slide-box>
  ```

  To this:

  ```html
  <ion-slide-box>
    <!-- pager using default click action -->
    <ion-slide-pager></ion-slide-pager>
  </ion-slide-box>
  <ion-slide-box>
    <!-- pager with custom click action -->
    <ion-slide-pager ng-click="doSomething(index)"></ion-slide-pager>
  </ion-slide-box>
  ```

- **`$ionicSlideBoxDelegate`** methods have changed (see
  [documentation](http://ionicframework.com/docs/api/service/$ionicSlideBoxDelegate)):

  - `update()` has been removed. slideBox updates on its own now.

  - `stop()` has been removed. See `autoPlay()` below.

  - `start()` hass been removed. See `autoPlay()` below.

  - `slide(newIndex[, speed])` has been renamed to `select(newIndex[,
    speed]);

  - `currentIndex()` has been renamed to `selected()`.

  - `slidesCount()` has been renamed to `count()`.

  - New method `$ionicSlideBoxDelegate.autoPlay()`. Change your code
    from this:

    ```js
    // stop auto sliding
    $ionicSlideBoxDelegate.stop();
    // later... start auto sliding
    $ionicSlideBoxDelegate.start();
    ```

    To this:

    ```js
    var autoPlaySpeed = 3000; //wait 3000 seconds between changing slide
    // stop auto sliding
    $ionicSlideBoxDelegate.autoPlay(false);
    // later... start auto sliding
    $ionicSlideBoxDelegate.autoPlay(autoPlaySpeed);
    ```

  - `previous()` now returns the index of the previous slide and does
    not select. Change your code from this:

    ```js
    // select previous slide
    $ionicSlideBoxDelegate.previous();
    ```

    To this:

    ```js
    // select previous slide
    $ionicSlideBoxDelegate.select( $ionicSlideBoxDelegate.previous() );
    ```
  - `next()` now returns the index of the next slide and does
    not select. Change your code from this:

    ```js
    // select next slide
    $ionicSlideBoxDelegate.next();
    ```

    To this:

    ```js
    // select next slide
    $ionicSlideBoxDelegate.select( $ionicSlideBoxDelegate.next() );
    ```
@PNSites
Copy link

PNSites commented Jan 11, 2017

@marcsyp Which of them solved your slides' sensitivity problem?
There are 26 changed files and, as I am new to Ionic, it is hard for me to really understand which one of them solves the sensitivity problem.

Thank you!

@ionitron-bot
Copy link

ionitron-bot bot commented Sep 5, 2018

Thanks for the issue! This issue is being locked to prevent comments that are not relevant to the original issue. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

@ionitron-bot ionitron-bot bot locked and limited conversation to collaborators Sep 5, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants