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)
|
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;
}
} |
|
<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> |
|
#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;
}
}
} |
|
public interface IDependencyServiceListView
{
void DisableScrollView(SfListView ListView);
}
private void ListView_Loaded(object sender, ListViewLoadedEventArgs e)
{
DependencyService.Get<IDependencyServiceListView>().DisableScrollView(ListView);
} |
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.
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 :)
|
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. |
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();
|
#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
}
}
} |
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
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