SfListView should allow disable scrolling.

I'm working on a Xamarin Forms application that I need to make reaction view like Facebook (Like, Love, Haha...) and I'm implementing this control in a SfListView.

The problem of this control is when the user is holding the touch in that control, we have to disable the ListView for preventing further scrolling (otherwise it will be weird when user choose which reaction).

Normally, if we just use the ScrollView, we can make a custom renderer to disable the scrolling without disable the entire interaction to the children.

But in SfListView, we can't put our custom renderer with an extra property to decide whether we should disable the control or not.

So the idea is the SfListView need to allow us to pass our "CustomExtendedScrollView" to replace "ExtendedScrollView" (which is the SfListView is using), and implement our own custom renderer for it. Or it could be great if this control could provide something like IsScrollingEnabled (not the current IsScrollingEnabled, the current IsScrollingEnabled does not do anything when the view is rendered)


8 Replies 1 reply marked as answer

LN Lakshmi Natarajan Syncfusion Team July 5, 2021 09:16 AM UTC

Hi Vu Hoang Huy, 
 
Thank you for using Syncfusion products. 
 
We have checked the reported query “SfListView should allow disable scrolling” from our side. We would like to inform you that the IsScrollingEnabled property used to load the SfListView with full height.  
 
Please refer to our user guidance document regarding the same, 
 
You can achieve your requirement using any of the following ways, 
 
#1 You can disable the ListView’s scrolling by setting the ExtendedScrollView.IsEnabled as false. And load the SfListView inside ScrollView to perform scrolling. In this case, you can customize the Scrolling behavior of the ScrollView using CustomRenderer based on your requirement. 
 
Please refer to the following code snippets for more reference, 
public class Behavior : Behavior<ContentPage> 
{ 
    SfListView ListView; 
 
    protected override void OnAttachedTo(ContentPage bindable) 
    { 
        ListView = bindable.FindByName<SfListView>("listView"); 
        ListView.IsScrollingEnabled = false; 
        ListView.Loaded += ListView_Loaded; 
        base.OnAttachedTo(bindable); 
    } 
 
    private void ListView_Loaded(object sender, ListViewLoadedEventArgs e) 
    { 
        var scrollview = ListView.GetScrollView(); 
        scrollview.IsEnabled = false; 
    } 
} 
 
Load the ListView inside ScrollView and write renderer for the ScrollView. 
<ScrollView> 
    <StackLayout> 
        <syncfusion:SfListView x:Name="listView" 
                                ItemSize="60" 
                                ItemsSource="{Binding ContactsInfo}"  
                                Margin="20"> 
            <syncfusion:SfListView.ItemTemplate > 
                <DataTemplate> 
                    ... 
                </DataTemplate> 
            </syncfusion:SfListView.ItemTemplate> 
        </syncfusion:SfListView> 
    </StackLayout> 
</ScrollView> 
 
#2 Or, you can get the ExtendedScrollViewRenderer by using the dependency services. And you can customize the ExtendedScrollViewRenderer for each platform based on your requirement. 
 
Please refer to the following code snippets to get the ExtendedScrollViewRenderer for all platforms.  
 
#if Android 
using Xamarin.Forms.Platform.Android; 
#elif __IOS__ 
using Xamarin.Forms.Platform.iOS; 
#else 
using Xamarin.Forms.Platform.UWP; 
#endif 
using ListViewXamarin.Droid; 
using Syncfusion.ListView.XForms; 
using Syncfusion.ListView.XForms.Control.Helpers; 
using Xamarin.Forms; 
 
[assembly: Dependency(typeof(ListViewDependencyService))] 
namespace ListViewXamarin.Droid 
{ 
    public class ListViewDependencyService : IDependencyServiceListView 
    { 
        ExtendedScrollView ExtendedScrollView; 
 
        public void DisableScrollView(SfListView ListView) 
        { 
            ExtendedScrollView = ListView.GetScrollView(); 
            var extendedScrollViewRenderer = Platform.GetRenderer(ExtendedScrollView); 
            (extendedScrollViewRenderer.Element as ExtendedScrollView).IsEnabled = false; 
        } 
    } 
} 
 
Invoke the DisableScrollView method using the Dependency service. 
public interface IDependencyServiceListView 
{ 
    void DisableScrollView(SfListView ListView); 
} 
 
private void ListView_Loaded(object sender, ListViewLoadedEventArgs e) 
{ 
    DependencyService.Get<IDependencyServiceListView>().DisableScrollView(ListView); 
} 
 
We have prepared a sample to disable the SfListView’s scrolling and attached in the following link, 
 
Please let us know if you need further assistance. 
 
Lakshmi Natarajan 
 



VH Vu Hoang Huy July 5, 2021 09:30 AM UTC

Hi Lakshmi.

Thanks for the answer.

But i'm having questions for both approach.


For the #1:

Will the virtualization still working if we render the view as full height and put it inside a ScrollView? If it's not working, then it's not different then a Bindable StackLayout.

For the #2:

We're getting instance of a Renderer, not making a custom Renderer like we want. Because we need to override some methods for both iOS and Android for the ScrollView to meet our needs. Disable the ScrollView in this case will also disable all interactions in the children views inside the ScrollView, which is something we don't want.



VH Vu Hoang Huy July 5, 2021 11:04 AM UTC

Hi Lakshmi,

I'm able to solve it now. By creating a custom renderer for ExtendedScrollView and doing like in your second approach. Thanks for the support :)



LN Lakshmi Natarajan Syncfusion Team July 5, 2021 01:30 PM UTC

Hi Vu Hoang Huy, 
 
Thank you for the update. 
 
No 
Query 
Response 
1 
Will the virtualization still working if we render the view as full height and put it inside a ScrollView? If it's not working, then it's not different then a Bindable StackLayout. 
Yes, your understanding was correct. Virtualization will not work if we use IsScrollingEnabled as False in SfListView.  
2 
We're getting instance of a Renderer, not making a custom Renderer like we want. Because we need to override some methods for both iOS and Android for the ScrollView to meet our needs. Disable the ScrollView in this case will also disable all interactions in the children views inside the ScrollView, which is something we don't want. 
When using IsEnabled as False for an element, then the element will not receive focus or emit input events. But it will not affect passing touch interactions to the child elements. Hence, the SfListView will get the touch interaction even if we disable the ScrollView. 
 
 
Also, we are glad that the requirement had been met at your side. Please let us know if you need further assistance. As always we are happy to help you out. 
 
Lakshmi Natarajan 
  
 



VH Vu Hoang Huy replied to Lakshmi Natarajan July 5, 2021 01:39 PM UTC

HI Lakshmi,

I tried the #2 solution but it's not working for iOS :), when disable the ScrollView (which mean UserInteractionEnabled), iOS will disable all the children views inside the ScrollView as well, so my control is disabled as well.

So making a Custom renderer for a the ScrollView is the only solution in this case. Problem is the ScrollView is nested inside the SfListView and the current implementation not allow us to override it.

Maybe making an abstraction like this will help to solve our situation in the SfListView, so we could override SfListView to provide our custom scrollView and still keeping the virtualization

protected virtual ExtendedScrollView ProvideScrollView(); 



LN Lakshmi Natarajan Syncfusion Team July 6, 2021 01:55 PM UTC

Hi Vu Hoang Huy, 
 
Sorry for the inconvenience caused. 
 
We would like to inform you that you can overcome the reported scenario by disabling native view scrolling in the renderer. Please refer to the following code snippets to achieve your requirement for each platforms using the second approach, 
 
#if Android 
using Xamarin.Forms.Platform.Android; 
#elif __IOS__ 
using UIKit; 
using Xamarin.Forms.Platform.iOS; 
#else 
using Xamarin.Forms.Platform.UWP; 
using Windows.UI.Xaml.Controls; 
#endif 
using ListViewXamarin.Droid; 
using Syncfusion.ListView.XForms; 
using Syncfusion.ListView.XForms.Control.Helpers; 
using Xamarin.Forms; 
 
[assembly: Dependency(typeof(ListViewDependencyService))] 
namespace ListViewXamarin.Droid 
{ 
    public class ListViewDependencyService : IDependencyServiceListView 
    { 
        ExtendedScrollView ExtendedScrollView; 
 
        public void DisableScrollView(SfListView ListView) 
        { 
            ExtendedScrollView = ListView.GetScrollView(); 
            var extendedScrollViewRenderer = Platform.GetRenderer(ExtendedScrollView); 
#if __IOS__ 
            (extendedScrollViewRenderer.NativeView as UIScrollView).ScrollEnabled = false; 
#elif Android 
            extendedScrollViewRenderer.View.NestedScrollingEnabled = false; 
#else 
            var nativeView = extendedScrollViewRenderer.GetNativeElement(); 
            extendedScrollViewRenderer.Element.IsTabStop = false; 
            (nativeView as ScrollViewer).VerticalScrollMode = Windows.UI.Xaml.Controls.ScrollMode.Disabled; 
#endif 
        } 
    } 
} 
 
We have attached the tested sample in the following link, 
 
Please let us know if this helps. 
 
Regards, 
Lakshmi Natarajan 


Marked as answer

VH Vu Hoang Huy July 13, 2022 12:11 PM UTC

Hi,


I'm having another problem with this ExtendedScrollViewRenderer.


In our project, we have a feature that when user long click into an item, we wills how a "reaction" small popup then user can continue moving their finger to pick what kind of reaction they want, like: "Like, Surprise ...."


The problem with SfListView is that when I call ScrollEnabled = false, in the ExtendedScrollViewRenderer, it will prevent receiving touching event and there is no way that I can't override this behavior at the moment. The reason that I need to continue receiving touch event because the user need to keep their finger on the screen and moving around when ScrollEnabled = false, but now the view can't no longer receive touch event because of this. So after the ScrollEnabled = false, the ScrollView is completely disabled, which is not the expected behavior. This method is causing the issue in the ExtendedScrollViewRenderer

GestureRecognizerShouldBegin

Can you guys expose a method that I can set the or override the ExtendedScrollViewRenderer myself?


EDIT: Sorry, I don't think it's because of GestureRecognizerShouldBegin, but there is a reason that the UIScrollView is blocking all interaction when ScrollEnabled = false



LN Lakshmi Natarajan Syncfusion Team July 14, 2022 02:31 PM UTC

Hi Vu,


We have checked our sample attached in this update, and we are unable to replicate the reported scenario on our end. The SfListview.ItemHolding event works fine as expected. Please check our sample and let us know if you are still facing the same issue or not.


If not, please modify our sample based on your scenario and revert to us. It will be helpful for us to check on it and provide you with the solution as soon as possible.


Regards,

Lakshmi Natarajan


Loader.
Up arrow icon