Nativescript-ui-feedback: [RadListView] The tap event will not be fired while swipeActions is true

Created on 20 Oct 2017  路  25Comments  路  Source: ProgressNS/nativescript-ui-feedback

The tap event for this child component will stop working while using swipe action functionality for the RadListView component.
This happens only on _Android_

  • Progress NativeScript UI version: 3.1.3
  • CLI: 3.2.1
  • Cross-platform modules: 3.2.0
  • Runtime(s): tns-android: 3.2.0

For example:
XML

<navigation:ExamplePage xmlns:navigation="navigation/example-page" loaded="onPageLoaded" xmlns:lv="nativescript-pro-ui/listview" xmlns="http://www.nativescript.org/tns.xsd">
    <GridLayout orientation="vertical" rows="auto, *">
        <lv:RadListView 
            id="listView" 
            items="{{ dataItems }}" 
            row="1" 
            selectionBehavior="None" 
            itemSwipeProgressEnded="onSwipeCellFinished"
            itemSwipeProgressStarted="onSwipeCellStarted" 
            itemSwipeProgressChanged="onCellSwiping" 
            swipeActions="true">
            <lv:RadListView.itemTemplate>
                <StackLayout tap="onTap" orientation="vertical" style="background-color: white;" paddingLeft="5">
                    <Label tap="onLabelTap" fontSize="20" text="{{ name }}" marginBottom="8"/>
                    <Label fontSize="14" text="{{ title }}" style="font-weight: bold;"/>
                    <Label fontSize="12" text="{{ text }}"/>
                </StackLayout>
            </lv:RadListView.itemTemplate>
            <!-- >> listview-swipe-actions-multiple-template-xml -->
            <lv:RadListView.itemSwipeTemplate>
                <GridLayout columns="auto, *, auto">
                    <GridLayout columns="*, *, *" col="0" id="left-stack">
                        <GridLayout col="0" style="background-color: #0099ff;" tap="onLeftSwipeClick" id="btnMark" padding="16" >
                            <Label text="mark" fontSize="15" verticalAlignment="center" horizontalAlignment="center"/>
                        </GridLayout>
                         <GridLayout col="1" style="background-color: #ffcc99;" tap="onLeftSwipeClick" id="btnArchive" padding="16">
                            <Label text="archive" fontSize="15" verticalAlignment="center" horizontalAlignment="center"/>
                        </GridLayout>
                         <GridLayout col="2" style="background-color:  #ff3300;" tap="onLeftSwipeClick" id="btnUnread" padding="16">
                            <Label text="unread" fontSize="15" verticalAlignment="center" horizontalAlignment="center"/>
                        </GridLayout>
                    </GridLayout>
                    <GridLayout columns="*, *, *" col="2" id="right-stack">
                        <GridLayout col="0" style="background-color: red;" tap="onRightSwipeClick" id="btnDelete" padding="16" >
                            <Label text="delete" fontSize="15" verticalAlignment="center" horizontalAlignment="center"/>
                        </GridLayout>
                        <GridLayout col="1" style="background-color: #ff66ff;" tap="onRightSwipeClick" id="btnRead" padding="16">
                            <Label text="read" fontSize="15" verticalAlignment="center" horizontalAlignment="center"/>
                        </GridLayout>
                        <GridLayout col="2" style="background-color: #9966ff;" tap="onRightSwipeClick" id="btnForward" padding="16">
                            <Label text="forward" fontSize="15" verticalAlignment="center" horizontalAlignment="center"/>
                        </GridLayout>
                    </GridLayout>
                </GridLayout>
            </lv:RadListView.itemSwipeTemplate>
            <!-- << listview-swipe-actions-multiple-template-xml -->
        </lv:RadListView>
    </GridLayout>
</navigation:ExamplePage>

TypeScript

import viewModel = require("./swipe-actions-model");
import listViewModule = require("nativescript-pro-ui/listview");
import viewModule = require('tns-core-modules/ui/core/view');
import frameModule = require("tns-core-modules/ui/frame");
import utilsModule = require("tns-core-modules/utils/utils");

var animationApplied = false;
var leftItem: viewModule.View;
var rightItem: viewModule.View;
var mainView: viewModule.View;

export function onPageLoaded(args) {
    var page = args.object;

    page.bindingContext = new viewModel.ViewModel();
}

// >> listview-swipe-action-multiple
export function onCellSwiping(args: listViewModule.SwipeActionsEventData) {
    var swipeLimits = args.data.swipeLimits;
    var swipeView = args.swipeView;
    mainView = args.mainView;
    leftItem = swipeView.getViewById<viewModule.View>('left-stack');
    rightItem = swipeView.getViewById<viewModule.View>('right-stack');

    if (args.data.x > 0) {
        var leftDimensions = viewModule.View.measureChild(
            <viewModule.View>leftItem.parent,
            leftItem,
            utilsModule.layout.makeMeasureSpec(Math.abs(args.data.x), utilsModule.layout.EXACTLY),
            utilsModule.layout.makeMeasureSpec(mainView.getMeasuredHeight(), utilsModule.layout.EXACTLY));
        viewModule.View.layoutChild(<viewModule.View>leftItem.parent, leftItem, 0, 0, leftDimensions.measuredWidth, leftDimensions.measuredHeight);
        hideOtherSwipeTemplateView("left");
    } else {
        var rightDimensions = viewModule.View.measureChild(
            <viewModule.View>rightItem.parent,
            rightItem,
            utilsModule.layout.makeMeasureSpec(Math.abs(args.data.x), utilsModule.layout.EXACTLY),
            utilsModule.layout.makeMeasureSpec(mainView.getMeasuredHeight(), utilsModule.layout.EXACTLY));

        viewModule.View.layoutChild(<viewModule.View>rightItem.parent, rightItem, mainView.getMeasuredWidth() - rightDimensions.measuredWidth, 0, mainView.getMeasuredWidth(), rightDimensions.measuredHeight);
        hideOtherSwipeTemplateView("right");
    }
}

function hideOtherSwipeTemplateView(currentSwipeView: string) {
    switch (currentSwipeView) {
        case "left":
            if (rightItem.getActualSize().width != 0) {
                viewModule.View.layoutChild(<viewModule.View>rightItem.parent, rightItem, mainView.getMeasuredWidth(), 0, mainView.getMeasuredWidth(), 0);
            }
            break;
        case "right":
            if (leftItem.getActualSize().width != 0) {
                viewModule.View.layoutChild(<viewModule.View>leftItem.parent, leftItem, 0, 0, 0, 0);
            }
            break;
        default:
            break;
    }
}
// << listview-swipe-action-multiple

// >> listview-swipe-action-multiple-limits
export function onSwipeCellStarted(args: listViewModule.SwipeActionsEventData) {
    var swipeLimits = args.data.swipeLimits;
    swipeLimits.threshold = args.mainView.getMeasuredWidth() * 0.2; // 20% of whole width
    swipeLimits.left = swipeLimits.right = args.mainView.getMeasuredWidth() * 0.65 // 65% of whole width
}
// << listview-swipe-action-multiple-limits

export function onSwipeCellFinished(args: listViewModule.SwipeActionsEventData) {
    if (args.data.x > 200) {
        console.log("Perform left action");
    } else if (args.data.x < -200) {
        console.log("Perform right action");
    }
    animationApplied = false;
}

export function onLeftSwipeClick(args: listViewModule.ListViewEventData) {
     var listView = <listViewModule.RadListView>frameModule.topmost().currentPage.getViewById("listView");
    console.log("Button clicked: " + args.object.id + " for item with index: " + listView.items.indexOf(args.object.bindingContext));
    listView.notifySwipeToExecuteFinished();
}

export function onRightSwipeClick(args) {
     var listView = <listViewModule.RadListView>frameModule.topmost().currentPage.getViewById("listView");
    console.log("Button clicked: " + args.object.id + " for item with index: " + listView.items.indexOf(args.object.bindingContext));
    listView.notifySwipeToExecuteFinished();
}

export function onTap(args){
    console.log("onTap SackLayout");

}

export function onLabelTap(args){
    console.log("on label tap")
}
backlog feature listview ready for release medium

Most helpful comment

I have found a solution that works on both platforms (iOS and Android):

On the RadListView container add the following event binder: (itemTap)="onTap($event)"
$event is a ListViewEventData
$event.index allows you to get the tapped index item.

All 25 comments

Hi,

I've just posted the same bug a few hours ago.
https://discourse.nativescript.org/t/radlistview-swipeactions-are-disabling-tap-action-in-mainview/3036

Weird that I didn't see this thread earlier.

I also got the same issue using [email protected] with angular

  • 1 from t.1146685

Changing the label from bug to feature as this is the expected event propagation on Android.

@NickIliev : do you have any update on this feature yet? This is very limitating. Thank you

I have found a solution that works on both platforms (iOS and Android):

On the RadListView container add the following event binder: (itemTap)="onTap($event)"
$event is a ListViewEventData
$event.index allows you to get the tapped index item.

@vincentpalita / @NickIliev

The itemTap event binder technique doesn't provide distinction between onTap() and onLabelTap().
Is there a workaround available where the event trigger can provide information on what sub-element of a RadList Item was actually tapped?

If not, can we have some priority on this particular feature.

+1

+2

I agree that this feature needs some priority. I was able to get around it by changing my label to a button but I would prefer a solution in which you can access which child element triggered the tap.

+3!

Any update on this?

+4 :(

+5

+6
no update on this one ?

+7 This is a significant issue for us that's really messing up our current app design.

+8

I just encountered this limitation as well :( @VladimirAmiorkov do you know of any workarounds here?

Hi all,
We are investigating the case and will comment on the issue when we have more info.
For now, I would suggest using the RadListView itemTap event as a temporary solution.

+9

+10

Using Nativescript Angular I ran across this issue and found that the tap event is recognized on a Button placed inside the RadListView but not on other layout elements like GridLayout.

So as a workaround I am using a styled button to capture the tap event the item and the index.
<Button row="3" col="2" text="Tap" (tap)="modifyModal(item, index)"></Button>

+11

The feature is implemented in [email protected]. Enjoy!

5.1.0 has introduced some new bugs with this new feature.

  1. When you're scrolling through a list supporting swipeActions, and quickly swipe to the side (while it's still scrolling), the swipe action events will not trigger afterwards. The swipe panel still slides to both sides, but the buttons do nothing (the tap event is ignored). The only way to get them working again is to click the item itself, reopen the slide and re-click the buttons.

If you allow the scroll animation to completely settle before trying to swipe, then everything works as expected, but our users aren't that patient.

  1. When hitting the above bug, the scrollEnded event no longer triggers (assume it gets blocked).

Both combined, these bugs cause mayhem for us. :-)
We spent the entire day debugging this.

We've confirmed that by rolling back to 5.0.1, everything works as expected.

Here's a playground that shows everything working; https://play.nativescript.org/?template=play-ng&id=ne9nN3&v=6 (Playground is running v5.0.1 still)
To see the bugs in action, download the Playground project, and update nativescript-ui-listview to 5.1.0.
Then do what I explained above. With the above playground project, we can replicate the problem with 100% consistency.

@zbranzov @tsonevn

Thanks.

Ps. Recommend anyone reading this to stay on 5.0.1 for now.

Hi @larssn,
Thank you for your report, we will soon release a fix. You can follow for status updates of related issue that you opened.

Not working for me, because I need all of the item data on tap, not just the index.
I will have to forget about swipe functionality of my list.

EDIT:
updating to: "nativescript-ui-listview": "5.1.1", solves it.

Was this page helpful?
0 / 5 - 0 ratings