We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date

Xamarin Forms SfListView ItemTapped event firing when actionable item is clicked within ListView cell on Android

Hi,

We have implemented our ListView to expand additional details when the ListView cell is clicked. The problem lies in that we also have multiple buttons etc.. in the ListView cell that we do NOT want trigger the collapse/expanded when clicked.

This seems to work fine with iOS as if another element that has an event handler is clicked, the ItemTapped event for the cell is not triggered. However on Android, the ItemTapped event is always fired, even if one of the buttons are clicked. Which means the cell is constantly collapsed/ expanded when we don't want it to be.. and many times the event on the button etc.. is not triggered.

Is there anyway, to ignored the ItemTapped event on Android if an element with its own event is clicked?

Regards,

-Jeff

20 Replies

DB Dinesh Babu Yadav Syncfusion Team August 21, 2017 09:17 AM UTC

Hi Jeff, 
 
Thank you for using Syncfusion Products. 
   
We have checked the reported query “Group header item gets expanded/collapsed and command gets triggered while tapping the item in Android platform” at our end and we would like to let you know that, In Android platform when background color is set for SfListView, touch click listener is not passed to the SfListView due to some limitations in Xamarin Forms Android and the gestures like tapping, double tapping etc.., cannot be detected. So, we have internally override the OnInterceptTouchEvent(Implement this method to intercept all touch screen motion events) in the Android renderer project to detect the gestures event when background color is set. The OnInterceptTouchEvent is a Boolean type override method, if return false, the touch is passed to its child (example button (clicked event or command), gesture recognizer element within the ItemTemplate) and if returns true(default value), touch interaction is not passed to its child and the touch interaction is not detected if background color is set for SfListView. 
 
However, you achieve the reported requirement “Expand/Collapse the groups without raising the button clicked event when an group header item is tapped” by a workaround using TapGestureRecognizer in your View’s GestureRecognizer (Example: Grid’s GestureRecognizer) with AllowGroupExpandCollapse as false as like below code snippet. So, if the button in the template is tapped, only the Clicked event gets triggered and similarly if the group header item is tapped, tap gesture’s tapped event will be triggered and in the tapped event, you can programmatically expand/collapse the tapped group item using ExpandGroup(GroupResult group) and CollapseGroup(GroupResult group) methods. 
 
Code Example[XAML]: 
<listView:SfListView.GroupHeaderTemplate> 
  <DataTemplate> 
    <Grid BackgroundColor="Teal"> 
      <Grid.GestureRecognizers> 
        <TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped"/> 
      </Grid.GestureRecognizers> 
      <Label Text="{Binding Key}" FontSize="22" FontAttributes="Bold" 
             VerticalOptions="Center" HorizontalOptions="Start" 
             Margin="20,0,0,0" /> 
      <Button Text="Click Me" TextColor="White" Grid.Column="1" 
              BackgroundColor="Teal" FontSize="Medium"  
              Clicked="Button_Clicked" HorizontalOptions="Start" 
              VerticalOptions="Center"/> 
    </Grid> 
  </DataTemplate> 
</listView:SfListView.GroupHeaderTemplate> 
 
Code Example[C#]: 
private void Button_Clicked(object sender, EventArgs e) 
{ 
  //Do your necessary actions here 
} 
 
private void TapGestureRecognizer_Tapped(object sender, EventArgs e) 
{ 
  var grid = sender as Grid; 
  var group = grid.BindingContext as GroupResult; 
  if (group.IsExpand) 
      listView.CollapseGroup(group); 
  else 
      listView.ExpandGroup(group); 
} 
 
For your reference, we have attached the sample and you can download it from the below link. 
 
   
Please let us know if you require further assistance. 
 
Regards, 
Dinesh Babu Yadav 



JB Jeff Bowman August 21, 2017 11:21 PM UTC

Hi Dinesh,

Thank you for your reply!

Although our issue is with the ListViewItems and not the group template, I believe what you are saying can probably be made for ListViewItems as well.

I also believe I am familiar with android defect you are talking about? Is this it? https://bugzilla.xamarin.com/show_bug.cgi?id=55912

If it is, the xamarin team have released a fix, that is current in one of their Beta builds. I am currently using the beta build, and this fix is in it, is there a way to override your renderer so that I can set this back to true?

Regards,

-Jeff




DB Dinesh Babu Yadav Syncfusion Team August 22, 2017 05:59 AM UTC

Hi Jeff, 
 
Thanks for the update. 
 
You can add the TapGestureRecoginzer to the ListView’s ItemTemplate too as similar to the GroupHeaderItems as provided workaround in previous update to resolve the issue at sample level. And the bug reported to Xamarin Team which you have provided has different scenario. Since, the issue occurs in SfListView is due to handling the onInterceptTouchEvent at our end which has been explained in previous update. 
 
Also, Could you please share that whether the reported issue has been resolved with the provided workaround at our end for both group header items and listview items?. If not, Could you please share some more details about your application scenario and exact requirement or issue? which would help us to analyze the requirement better and update you an appropriate solution. 
 
Please let us know if you require further assistance. 
 
Regards, 
Dinesh Babu Yadav 
 



JB Jeff Bowman August 24, 2017 11:47 PM UTC

Hi Dinesh,

This workaround does fix the issue where the ItemTapped even is firing when it shouldn't.. but by doing this another problems occurs:

In our ViewCell when have a 'Grid' that by default has 'IsVisible=False'. In our tapped handler, we are effectively adding some controls into this grid and then setting this Grid's IsVisible property to True.

For reference our ViewCell looks like the below:

ViewCell
--Grid
----Grid (Main content)
----Grid (The IsVisible=False one, should expand when ListViewItem is clicked)
----BoxView (Separator line)

When we were doing this on the ItemTapped event, everything worked as expected, the controls would be added, IsVisible is set to True, and the ListViewItem would be expanded to show the new controls.

After switching the event handler to occur on the gesture recognizer of the parent Grid in the ViewCell, the ListViewItem is no longer AutoFit when we add the controls/ set IsVisible=true (although I can see that stuff is added, because the box view disappears, like it is being pushed down below the visible clipping). Occasionally I will see that cell expands, but the content is blank, almost like the height was finally recalculated, but only after attempting to remove the added controls.

Note: we add/ remove controls to the grid in question because when we had them as part of the Grid in Xaml, it would cause a major memory leak and our app would run out of memory while scrolling in the ListView.

Any ideas how to get around this issue?

Regards,

-Jeff



DB Dinesh Babu Yadav Syncfusion Team August 28, 2017 04:00 AM UTC

Hi Jeff, 
 
Sorry for the inconvenience. 
 
We are validating the reported issue with high priority and looking to provide a workaround solution for your requirement at our end. We will update you the further details on August 28, 2017. 
 
Regards, 
Dinesh Babu Yadav 
 



JB Jeff Bowman August 28, 2017 04:26 PM UTC

Thank you Dinesh,

This issue is a 'showstopper' for us, so any help is greatly appretiated!

Regards,

-Jeff 



DB Dinesh Babu Yadav Syncfusion Team August 29, 2017 12:14 PM UTC

Hi Jeff,  
 
Apologies for the delay. 
 
The reported issues can be resolved by using different custom views bind to the ItemTemplate property by using DataTemplateSelector and add the tap gesture recognizer to each views as provided in previous update similar to GroupHeaderTemplate property. You need to use two views, one for defining the IsVisible as true and another for resetting the visibility to false. So, when an item is tapped, tap gesture event for the respective view will be triggered and change the property value which is used to select the template as like below code example. 
                                                           
Code Example[C#]: 
private void TapGestureRecognizer_Tapped(object sender, EventArgs e) 
{ 
  var grid = sender as Grid; 
  var listviewItem = grid.Parent as ListViewItem; 
  var listviewinfo = listviewItem.GetType().GetRuntimeProperties(). 
                     FirstOrDefault(x => x.Name =="ListViewItemInfo"). 
                     GetValue(listviewItem) as ListViewItemInfo; 
  var item = grid.BindingContext as ListViewBookInfo; 
  item.IsDetailsVisible = !item.IsDetailsVisible; 
  listviewinfo.ListView.RefreshView(); 
} 
 
Code Example[C#]: 
public class MyDataTemplateSelector : Xamarin.Forms.DataTemplateSelector 
{ 
  public MyDataTemplateSelector() 
  { 
            // Retain instances! 
    this.detailsViewDataTemplate = new DataTemplate(typeof(DetailsView)); 
    this.nondetailsViewDataTemplate = new DataTemplate(typeof(NonDetailsView)); 
  } 
 
  protected override DataTemplate OnSelectTemplate(object item,  
                                                   BindableObject container) 
  { 
    var bookinfo = item as ListViewBookInfo; 
    if (bookinfo == null) 
        return null; 
    return bookinfo.IsDetailsVisible ? this.detailsViewDataTemplate :this.nondetailsViewDataTemplate; 
  } 
 
  private readonly DataTemplate detailsViewDataTemplate; 
  private readonly DataTemplate nondetailsViewDataTemplate; 
} 
 
For your reference, we have modified the sample with the above code example and you can download it from the below link. 
 
 
 
Note: There is an problem in autofit while using single ItemTemplate and switching the visibility of the Grid within ItemTemplate. That is, measuring the size of the item doesn’t returns proper height since the visibility has been updated only on PCL and not on native element. So, you can use the above approach to achieve your requirement. 
 
Please let us know if you require further assistance. 
 
Regards, 
Dinesh Babu Yadav 
 
 



JB Jeff Bowman replied to Dinesh Babu Yadav September 1, 2017 03:29 PM UTC

Hi Jeff,  
 
Apologies for the delay. 
 
The reported issues can be resolved by using different custom views bind to the ItemTemplate property by using DataTemplateSelector and add the tap gesture recognizer to each views as provided in previous update similar to GroupHeaderTemplate property. You need to use two views, one for defining the IsVisible as true and another for resetting the visibility to false. So, when an item is tapped, tap gesture event for the respective view will be triggered and change the property value which is used to select the template as like below code example. 
                                                           
Code Example[C#]: 
private void TapGestureRecognizer_Tapped(object sender, EventArgs e) 
{ 
  var grid = sender as Grid; 
  var listviewItem = grid.Parent as ListViewItem; 
  var listviewinfo = listviewItem.GetType().GetRuntimeProperties(). 
                     FirstOrDefault(x => x.Name =="ListViewItemInfo"). 
                     GetValue(listviewItem) as ListViewItemInfo; 
  var item = grid.BindingContext as ListViewBookInfo; 
  item.IsDetailsVisible = !item.IsDetailsVisible; 
  listviewinfo.ListView.RefreshView(); 
} 
 
Code Example[C#]: 
public class MyDataTemplateSelector : Xamarin.Forms.DataTemplateSelector 
{ 
  public MyDataTemplateSelector() 
  { 
            // Retain instances! 
    this.detailsViewDataTemplate = new DataTemplate(typeof(DetailsView)); 
    this.nondetailsViewDataTemplate = new DataTemplate(typeof(NonDetailsView)); 
  } 
 
  protected override DataTemplate OnSelectTemplate(object item,  
                                                   BindableObject container) 
  { 
    var bookinfo = item as ListViewBookInfo; 
    if (bookinfo == null) 
        return null; 
    return bookinfo.IsDetailsVisible ? this.detailsViewDataTemplate :this.nondetailsViewDataTemplate; 
  } 
 
  private readonly DataTemplate detailsViewDataTemplate; 
  private readonly DataTemplate nondetailsViewDataTemplate; 
} 
 
For your reference, we have modified the sample with the above code example and you can download it from the below link. 
 
 
 
Note: There is an problem in autofit while using single ItemTemplate and switching the visibility of the Grid within ItemTemplate. That is, measuring the size of the item doesn’t returns proper height since the visibility has been updated only on PCL and not on native element. So, you can use the above approach to achieve your requirement. 
 
Please let us know if you require further assistance. 
 
Regards, 
Dinesh Babu Yadav 
 
 


Hi Dinesh,

Doing it this way seemed to do the trick! We are noticing that occasional though that the listview is a little jumpy (its intermittent, but all of a sudden the top of the listview is empty, and I need to scroll to make it appear again). I am wondering if it has to do with constantly refreshing the list view.

In any case, thank you so much for your support! It seems to finally be usable :).

Best Regards,

-Jeff



DB Dinesh Babu Yadav Syncfusion Team September 4, 2017 11:21 AM UTC

Hi Jeff, 
 
Thanks for the update. 
 
We have checked the reported issue “Items are not layout properly after refreshing the view” in the given sample with the latest SfListView version(v 15.3.0.29) in all platforms such as Android, iOS and UWP. But we are unable to reproduce the issue at our end when the template is changing at runtime by using RefreshView method. So, Could you please share that whether the issue reproduces in the given sample with any different scenarios and if possible please modify the given sample and revert us with the replication procedure so that we could able to analyze the issue better and update you an appropriate solution.  
 
Regards, 
Dinesh Babu Yadav 



JR Jassim Rahma December 6, 2017 10:47 PM UTC

What about below example:

I have an ItemTemplate with a Grid..

How can I get the Tapped item in this case? I need to get the category_id for it?


<SF:SfBusyIndicator x:Name="loadingCategory" IsBusy="true" AnimationType="Gear" ViewBoxWidth="150" ViewBoxHeight="150" />
<SFListView:SfListView x:Name="listViewCategory" SelectionGesture="Tap" SelectionMode="Single" ItemTapped="OnCategoryTapped" Orientation="Horizontal" IsScrollBarVisible="False" ItemSpacing="5,0,0,0" ItemSize="150">
<SFListView:SfListView.ItemTemplate>
<DataTemplate>
    <Grid Padding="5">
    <Grid.RowDefinitions>
    <RowDefinition Height="0.4*" />
    <RowDefinition Height="0.6*" />
    </Grid.RowDefinitions>
    <Image x:Name="CategoryImage" Source="{Binding category_image}" WidthRequest="200" HeightRequest="2300" Grid.Row="0" />
    <Label Grid.Row="1" Text="{Binding category_name}" TextColor="Teal" FontSize="15"/>
    </Grid>
</DataTemplate>
</SFListView:SfListView.ItemTemplate>
</SFListView:SfListView>



MK Muthu Kumaran Gnanavinayagam Syncfusion Team December 7, 2017 12:45 PM UTC

Hi Jassim, 
 
We have checked your requirement “Need to get the tapped item data in ItemTapped event of SfListView” from our side. You can get the ItemData of the underlying collection from the ItemTappedEventArgs in the SfListView’s ItemTapped event as like below code example. 
 
Code Example[C#]: 
private void OnCategoryTapped(object sender, Syncfusion.ListView.XForms.ItemTappedEventArgs e) 
{ 
  DisplayAlert("Alert", "Selected Book number: " + (e.ItemData as categoryModel).category_id, "OK"); 
} 
 
For your reference, we have attached the sample link below. 
 
 
Please let us know if you require further assistance. 
 
Regards, 
G.Muthu Kumaran. 



JR Jassim Rahma December 8, 2017 11:20 PM UTC

not working in my project,

I am not getting the DisplayAlert shown and no error at all.

Here is my XAML:

<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="Zeera.ZeeraCategory"
    xmlns:SF="clr-namespace:Syncfusion.SfBusyIndicator.XForms;assembly=Syncfusion.SfBusyIndicator.XForms"
    xmlns:SFListView="clr-namespace:Syncfusion.ListView.XForms;assembly=Syncfusion.SfListView.XForms"
    Title="Category">
    <StackLayout>
        <SF:SfBusyIndicator x:Name="loadingCategory" TextColor="#c3b366" IsBusy="true" AnimationType="Gear" ViewBoxWidth="150" ViewBoxHeight="150" />
        <SFListView:SfListView x:Name="listViewCategory" SelectionGesture="Tap" SelectionMode="Single" ItemTapped="OnCategoryTapped" Orientation="Horizontal" IsScrollBarVisible="False" ItemSpacing="5,0,0,0" ItemSize="150">
        <SFListView:SfListView.ItemTemplate>
        <DataTemplate>
            <Grid Padding="5">
            <Grid.RowDefinitions>
            <RowDefinition Height="0.4*" />
            <RowDefinition Height="0.6*" />
            </Grid.RowDefinitions>
            <Image x:Name="CategoryImage" Source="{Binding category_image}" WidthRequest="200" HeightRequest="2300" Grid.Row="0" />
            <Label Grid.Row="1" Text="{Binding category_name}" TextColor="Teal" FontSize="15"/>
            </Grid>
        </DataTemplate>
        </SFListView:SfListView.ItemTemplate>
        </SFListView:SfListView>
        <StackLayout VerticalOptions="FillAndExpand" Spacing="0" Padding="5">
          <Label x:Name="lblCategoryName" IsVisible="false" Text="Choose the Category" FontSize="Large" HorizontalOptions="Center" HorizontalTextAlignment="Center" />
          <SF:SfBusyIndicator x:Name="loadingItems" TextColor="#c3b366" IsBusy="false" AnimationType="Gear" ViewBoxWidth="150" ViewBoxHeight="150" />
          <ListView x:Name="listViewItems" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" HasUnevenRows="true" ItemTapped="OnItemTapped" IsVisible="false">
            <ListView.ItemTemplate>
              <DataTemplate>
                <ViewCell>
                    <StackLayout Orientation="Vertical" Padding="5">
                        <Image Margin="10" Aspect="AspectFill" HorizontalOptions="FillAndExpand" Source="{Binding item_image}" />
                        <StackLayout Orientation="Horizontal" Padding="5">
                            <Label Text="{Binding item_name}" HorizontalOptions="FillAndExpand" FontSize="Large" />
                            <Label Text="{Binding item_price}" FontSize="Medium" TextColor="Blue" HorizontalOptions="End" />
                        </StackLayout>
                    </StackLayout>
                </ViewCell>
              </DataTemplate>
            </ListView.ItemTemplate>
          </ListView>
        </StackLayout>
    </StackLayout>
</ContentPage>

and my CS is here:

void OnCategoryTapped(object sender, Syncfusion.ListView.XForms.ItemTappedEventArgs e)
{
    DisplayAlert("Alert""Selected Book number: " + (e.ItemData as CategoryDetails).category_id"OK");
}




MK Muthu Kumaran Gnanavinayagam Syncfusion Team December 11, 2017 05:19 AM UTC

Hi Jassim, 
 
We have checked the reported query “SfListView’s ItemTapped event does not trigger while tapping an item” from our side. We have referred the attached code example and found that the ItemTapped event is hooked properly. But we suspect that the reported issue occurs due to SfListView assemblies not referred properly in your renderer projects. Can you please check whether all the assemblies needed for proper functioning of SfListView has been added as reference in your sample? You can refer the below documentation to know about the list of assemblies needed for SfListView control. 
 
 
Please let us know if you require further assistance. 
 
Regards, 
G.Muthu Kumaran. 



JB Jeff Bowman replied to Jeff Bowman April 10, 2018 12:11 AM UTC

Hi Jeff,  
 
Apologies for the delay. 
 
The reported issues can be resolved by using different custom views bind to the ItemTemplate property by using DataTemplateSelector and add the tap gesture recognizer to each views as provided in previous update similar to GroupHeaderTemplate property. You need to use two views, one for defining the IsVisible as true and another for resetting the visibility to false. So, when an item is tapped, tap gesture event for the respective view will be triggered and change the property value which is used to select the template as like below code example. 
                                                           
Code Example[C#]: 
private void TapGestureRecognizer_Tapped(object sender, EventArgs e) 
{ 
  var grid = sender as Grid; 
  var listviewItem = grid.Parent as ListViewItem; 
  var listviewinfo = listviewItem.GetType().GetRuntimeProperties(). 
                     FirstOrDefault(x => x.Name =="ListViewItemInfo"). 
                     GetValue(listviewItem) as ListViewItemInfo; 
  var item = grid.BindingContext as ListViewBookInfo; 
  item.IsDetailsVisible = !item.IsDetailsVisible; 
  listviewinfo.ListView.RefreshView(); 
} 
 
Code Example[C#]: 
public class MyDataTemplateSelector : Xamarin.Forms.DataTemplateSelector 
{ 
  public MyDataTemplateSelector() 
  { 
            // Retain instances! 
    this.detailsViewDataTemplate = new DataTemplate(typeof(DetailsView)); 
    this.nondetailsViewDataTemplate = new DataTemplate(typeof(NonDetailsView)); 
  } 
 
  protected override DataTemplate OnSelectTemplate(object item,  
                                                   BindableObject container) 
  { 
    var bookinfo = item as ListViewBookInfo; 
    if (bookinfo == null) 
        return null; 
    return bookinfo.IsDetailsVisible ? this.detailsViewDataTemplate :this.nondetailsViewDataTemplate; 
  } 
 
  private readonly DataTemplate detailsViewDataTemplate; 
  private readonly DataTemplate nondetailsViewDataTemplate; 
} 
 
For your reference, we have modified the sample with the above code example and you can download it from the below link. 
 
 
 
Note: There is an problem in autofit while using single ItemTemplate and switching the visibility of the Grid within ItemTemplate. That is, measuring the size of the item doesn’t returns proper height since the visibility has been updated only on PCL and not on native element. So, you can use the above approach to achieve your requirement. 
 
Please let us know if you require further assistance. 
 
Regards, 
Dinesh Babu Yadav 
 
 


Hi Dinesh,

Doing it this way seemed to do the trick! We are noticing that occasional though that the listview is a little jumpy (its intermittent, but all of a sudden the top of the listview is empty, and I need to scroll to make it appear again). I am wondering if it has to do with constantly refreshing the list view.

In any case, thank you so much for your support! It seems to finally be usable :).

Best Regards,

-Jeff


Bringing this back from the dead to try and find a fix for the jumping problem as it is really affecting usability. A user will click on an item to expand it.. and then all of a sudden the list view jumps up or down a bunch of items, and the item the user clicks is no longer visible, and it requires them to scroll up or down to find it.

What I kind of determined is that the switching of the data template causes some measurements etc.. and the first time it renders the second template on any given list view item, it jumps.

Steps to reproduce: 

1. Create a SfListView with 2 data templates, one data template should be at least 50% larger vertically than the other
2. Populate list view with enough items to fill page (lets say 3 pages to be safe).
3. Scroll down to an item on the 2nd page and click a list view item to 'expand' it. 
4. Observe: The first time a list view object is clicked, it seems to jump the List view around.

Is there any way around this?

Regards,

-Jeff


RS Rawoof Sharief Muthuja Sherif Syncfusion Team April 10, 2018 07:21 AM UTC

Hi Jeff,  
  
Sorry for the inconvenience.    
    
We have already confirmed that the issue with “SfListView scrolls up when expand the group” is a defect and we have logged a defect report. The fix for this issue is available in our 2018 Vol 1 SP 2 release. We will appreciate your patience until then.   
  
Regards,    
Rawoof M


RP Robert Pitard April 10, 2018 02:46 PM UTC

RE: The fix for this issue is available in our 2018 Vol 1 SP 2 release.

1. Please advise as to when this release is slated for.
2. Please include the probability, in percentage form, as to how confident you are that this will be fully resolved.

RGP


JB Jeff Bowman April 10, 2018 08:45 PM UTC

Thank You Rawoof,

I just want to confirm, that this doesn't only happen with List View Groups, for us it is happening with just the normal list view item (we don't actually user groups as they are in your documentation). We are swapping out the DataTemplate on the ListViewItem.

Regards,

-Jeff


RS Rawoof Sharief Muthuja Sherif Syncfusion Team April 11, 2018 04:07 PM UTC

Hi Jeff, 
 
Sorry for the inconvenience. 
 
We have checked the reported issue at our end and would like to let you know that while the item size for each item is changed, the total extent gets changed so, the view gets relayout. We have logged a defect report for this and it will be included in our upcoming 2018 Volume 1 SP 2 release. We will let you know once the issue has been resolved and included in the release. We will appreciate your patience until then. 
 
Regards, 
Rawoof M.   



JB Jeff Bowman April 11, 2018 04:18 PM UTC

Thank you Rawoof,

What is the expected date for this release?

Regards,

-Jeff


RS Rawoof Sharief Muthuja Sherif Syncfusion Team April 13, 2018 04:50 AM UTC

Hi Jeff,   
   
We have planned to roll out our 2018 Vol 1 SP 2 release by the end of this month and we will let you know once the release has been rolled out. We will appreciate your patience until then.  
  
Regards,    
Rawoof M    


Loader.
Up arrow icon