We have a scrollview and elements inside the scrollview have tap event.
When user puts his finger on an item inside scrollview and scrolls a tiny bit and releases it, the tap event fires. This is not a normal behavior and does not happen in listviews.
<ScrollView orientation="vertical" class="scrollView" sdkToggleNavButton>
<StackLayout class="wrapper">
<StackLayout class="slide" (tap)="openMembership();"></StackLayout>
<StackLayout class="slide" (tap)="openMembership();"></StackLayout>
<StackLayout class="slide" (tap)="openMembership();"></StackLayout>
<StackLayout class="slide" (tap)="openMembership();"></StackLayout>
<StackLayout class="slide" (tap)="openMembership();"></StackLayout>
<StackLayout class="slide" (tap)="openMembership();"></StackLayout>
<StackLayout class="slide" (tap)="openMembership();"></StackLayout>
</StackLayout>
</ScrollView>
In the above example, the StackLayout with "slide" class's tap is fired while scrolling. (If the finger is moved more than like 15 pixels, it does not happen and it just happens in small scrolls)
I tested it in iOS only and I am not sure about android.
I was wondering what is the correct way to use taps inside scrollview to prevent this?
Related
I have a RadListView that displays a list of items. In each item template I have a (tap) event that fires when tapping on the item, to redirect to the item details screen. However, for some reason whenever I swipe the RadListView vertically to traverse the list, it fires the (tap) event wherever I start swiping from and incorrectly redirects to the item details screen instead of just moving up or down the list.
<RadListView
class="list transparent"
[class.visible]="!data.loading"
[visibility]="!data.loading ? 'visible' : 'collapse'"
[items]="data.items"
swipeActions="true"
(itemSwipeProgressStarted)="onSwipeCellStarted($event)">
<ng-template let-item="item">
<StackLayout class="item" orientation="horizontal" (tap)="view(item)">
<Image
[src]="item.photos?.length ? item.photos[0] : ''"
[visibility]="item.photos?.length ? 'visible' : 'collapse'">
</Image>
<StackLayout orientation="vertical">
<Label
class="title"
[text]="item.address">
</Label>
</StackLayout>
</StackLayout>
</ng-template>
<GridLayout *tkListItemSwipeTemplate columns="*, auto">
<StackLayout id="delete" col="1" (tap)="deleteRow($event)" class="delete">
<Label class="fas" [text]="IconsEnum.trashAlt"></Label>
</StackLayout>
</GridLayout>
</RadListView>
I tried getting rid of the (tap) event and instead using the following on the RadListView:
multipleSelection="false" selectionBehavior="Press" (itemSelected)="itemSelected($event)"
That resolved the issue with swiping, however it introduced a new issue where it would only select an item every two taps instead of every swipe.
What is the proper way to select an item from a RadListView?
Upgrading from #nativescript/ios 7.1.1 to 7.2.0 resolved this bug.
I have AbsoluteLayout in ScrollView with pager and custom components inside Pager. The code is working on Android, but on iOS is nothing shown. Does anyone have some solution?
<ScrollView>
<AbsoluteLayout>
<Pager row="1" #pager [selectedIndex]="currentPagerIndex" width="100%">
<ns-dashboard-profile height="100" *pagerItem></ns-dashboard-profile>
<ns-dashboard-home *pagerItem></ns-dashboard-home>
<ns-dashboard-devices *pagerItem></ns-dashboard-devices>
</Pager>
<FlexboxLayout class="navigation-wrapper" top="230">
<Label text="Profil" (tap)="goToPage('profile')" class="profile-tab"></Label>
<Label text="Početna" (tap)="goToPage('home')" class="home-tab"></Label>
<Label text="Moji uređaji" (tap)="goToPage('devices')" class="my-device-tab"></Label>
</FlexboxLayout>
</AbsoluteLayout>
ScrollView closing tag is not shown in the code snippet.
I'm creating a custom action bar and my idea is that the actionbar must be transparent (thats why I can't/don't want to use the native one) and behind the action bar there must be content (an image in this case).
I tried multiple ways and all of them with the same result, the iOS button become unclickable for no reason.
Ok, so I have an AbsoluteLayout inside I have GridLayout fixed on top as the custom actionbar and then a ScrollView with 100% width and height, inside the scrollview there's some content. The problem is as soon as I put a button inside the GridLayout this become unclickable only on iOS because in Android works just fine.
Let me show you my example with some code:
<Page actionBarHidden="true">
<AbsoluteLayout>
<GridLayout rows="50, *" backgroundColor="red" top="0" left="0" height="50" id="bar">
<Button text="click" #tap="goToDetailPage" id="buttondelsous"></Button>
</GridLayout>
<ScrollView backgroundColor="blue" width="100%" height="100%" top="0" id="content">
<WrapLayout>
<StackLayout>
<Label text="this is behind"></Label>
</StackLayout>
</WrapLayout>
</ScrollView>
</AbsoluteLayout>
</Page>
As for the styles forcing the custom actionbar being in front of the scrollview I have:
#bar {
z-index: 5;
width: 100%;
}
#content {
z-index: 2;
}
This looks like this on Android:
Same way on iOS but the button "Click" is not working, like if it was behind something..
Any idea on how to fix this or any other approach to get what I need? Remember behind the action I must be able to place content (like a background image that I don't want to place in the Page tag itself but in another layout)
Thanks!
A wise man once told me that Nativescript stacks elements in the order you list them. Try flipping around the order so the button is listed last in the template. I believe you won't even need the z-index line if you flip the order around.
should look like
<Page actionBarHidden="true">
<AbsoluteLayout>
<ScrollView backgroundColor="blue" width="100%" height="100%" top="0" id="content">
<WrapLayout>
<StackLayout>
<Label text="this is behind"></Label>
</StackLayout>
</WrapLayout>
</ScrollView>
<!-- I'm listed second so I will be on top even though I have row="0" -->
<GridLayout rows="50, *" backgroundColor="red" top="0" left="0" height="50" id="bar">
<Button text="click" #tap="goToDetailPage" id="buttondelsous"/>
</GridLayout>
</AbsoluteLayout>
</Page>
I'm trying to create in Nativescript(Testing it on Android) a view containing a Donut Chart and an Accordion-like list below it, and enable infinite scrolling, so that when i scroll down the chart will scroll up out of the view, leaving the whole screen available for the list.
The problem is that no matter what i try the accordion-list will either scroll out of the view, leaving the chart on top of it, basically appearing like it's hiding behind the chart, or the elements won't display correctly / at all.
This is how my layout is made so far
Index screen
<ScrollView heiht="100%>
<StackLayout>
<DonutChart [chartDataIterable]="chartData"></DonutChart>
<Accordion [items]="items"></Accordion>
</StackLayout>
</ScrollView>
Donut Chart Component
<GridLayout rows="auto">
<RadPieChart row="0" height="300" allowAnimation="true" (pointSelected)="changeDisplayValue($event)" (pointDeselected)="resetToTotal($event)">
<DonutSeries tkPieSeries seriesName="dataSeries" selectionMode="DataPoint" outerRadiusFactor="0.9" expandRadius="0.4"
outerRadiusFactor="0.7" innerRadiusFactor="0.7" [items]="chartDataObservable" valueProperty="value" legendLabel="type"></DonutSeries>
</RadPieChart>
<StackLayout row="0" horizontalAlignment="center" verticalAlignment="center">
<Label horizontalAlignment="center" [text]="currentType"></Label>
<Label horizontalAlignment="center" [text]="currentTypeAmount"></Label>
</StackLayout>
</GridLayout>
Accordion Component
<ListView [items]="items" height="100%">
<ng-template let-item="item">
<AccordionCell [item]="item"></AccordionCell>
</ng-template>
</ListView>
The GridLayout wrapping the chart is used to add some info at the center of the donut, and the accordion height 100% is set to prevent the list view from taking the height of a single cell.
I suspect that the issue is due to ListView integrating a ScrollView by default, thus prioritizing the scrolling in the ListView and never triggering the scrolling of the outer ScrollView since the content never exceeds the screen size.
Since there hasn't been an answer for a week now i'll share the workaround i came up with.
Instead of using a ScrollView to scroll through my chart and accordion(basically ListView) components, i've moved the Chart and positioned it as the first cell of the ListView, this way both scrolling and cell recycling work well. The only drawback is that a little extra cell management is needed in order to make sure that the chart stays on top, without losing the first entry of the list's data source.
accordion.component.ts
ngOnInit(): void {
this.observableItems = new ObservableArray(this.items);
this.observableItems.unshift({});
}
public templateSelector (item: any, index: number, items: ObservableArray<any>){
if(index === 0)
return "chart";
else if(item.date != items.getItem(index-1).date)
return "date";
else
return "default";
}
accordion.component.html
<RadListView [items]="observableItems" [itemTemplateSelector]="templateSelector" (itemLoading)="itemLoading($event)">
<ng-template tkListItemTemplate let-item="item" let-index="index">
<AccordionCell [item]="item" [index]="index" [itemLoadedEvent]="itemLoadedEvent.asObservable()"></AccordionCell>
</ng-template>
<ng-template tkTemplateKey="date" let-item="item" let-index="index">
<StackLayout>
<Label [text]="item?.date | date: 'dd/MM/yyyy'"></Label>
<AccordionCell [item]="item" [index]="index" [itemLoadedEvent]="itemLoadedEvent.asObservable()"></AccordionCell>
</StackLayout>
</ng-template>
<ng-template tkTemplateKey="chart">
<DonutChart [chartDataIterable]="chartDataIterable (chartSectionSelected)="chartSectionSelectedHandler($event)" (chartSectionDeselected)="chartSectionDeselectedHandler()"></DonutChart>
</ng-template>
I'm trying to build an scrollable list by using a StackLayout with an ngFor (and a ScrollView, of course).
This is my code:
<StackLayout class="home-panel" verticalAlignment="top">
<StackLayout orientation="horizontal">
<!--Suggest Append SuggetAppend -->
<RadAutoCompleteTextView #autocmp [items]="items" suggestMode="Suggest" displayMode="Plain" width="80%">
<SuggestionView tkAutoCompleteSuggestionView suggestionViewHeight="300">
<ng-template tkSuggestionItemTemplate let-item="item">
<StackLayout orientation="vertical" padding="10">
<Label [text]="item.text"></Label>
</StackLayout>
</ng-template>
</SuggestionView>
</RadAutoCompleteTextView>
<Button text="Add" (tap)="onAdd()" width="20%"></Button>
</StackLayout>
<ScrollView>
<StackLayout *ngFor="let item of this.shopList">
<Label text="{{item}}" (tap)="itemSelected(item)" fontSize="36"></Label>
</StackLayout>
</ScrollView>
</StackLayout>
The problem arises with the ScrollView at the end of the main StackLayout, which apparently shows only the last element in the shoppingList. The functionality I want to have is a text box on top (with an 'add' button on the same line), and a scrollable list filling the rest of the screen.
You have to wrap your StackLayout with the *ngFor into another Layout container, so the ScrollView can calculate the height.
...
<ScrollView>
<StackLayout>
<StackLayout *ngFor="let item of this.shopList">
<Label text="{{item}}" fontSize="36"></Label>
</StackLayout>
</StackLayout>
</ScrollView>
...