Hi all,
Im trying to figuire out I can trigger event of row appearing on CollectionView, previously I used ListView.ItemAppearing Event on listview but CollectionView does not have this event unfortunately so I need another way of detecting a row has appeared? I was using the Scrolled Event but it didnt quite achieve what I wanted since when the collectionview first loads data and displays then nothing triggers but only when I actually scroll.
Bassically I have a chat listview and when a row/message appears a http request send to mark the message as seen so I rely on a trigger when row appears not just scroll event.
Ive gottten this working on android butnot on iOS, below on my view (actually an expandableView) i add effect woth event Appeared
for view appearing:
<expandable:ExpandableView ExpandAnimationLength="125" Spacing="0"> <expandable:ExpandableView.Effects> <effects:ViewLifecycleEffect Appeared="viewLifecycleEffect_AppearedAsync" /> </expandable:ExpandableView.Effects> <expandable:ExpandableView.PrimaryView>
The effect in the shared project:
public class ViewLifecycleEffect : RoutingEffect { public const string EffectGroupName = "XFLifecycle"; public const string EffectName = "LifecycleEffect"; public event EventHandler<EventArgs>? Appeared; public event EventHandler<EventArgs>? Disappeared; public ViewLifecycleEffect() : base($"{EffectGroupName}.{EffectName}") { } public void RaiseAppeared(Element element) { Appeared?.Invoke(element, EventArgs.Empty); } public void RaiseDisappeared(Element element) => Disappeared?.Invoke(element, EventArgs.Empty); }
So finally in the iOS project I try to get notified when view is appearing/showing on screen/window but doesnt get called as views appear which should trigger per row as user scrolling:
public class IosLifecycleEffect : PlatformEffect { private const NSKeyValueObservingOptions _observingOptions = NSKeyValueObservingOptions.Initial | NSKeyValueObservingOptions.OldNew | NSKeyValueObservingOptions.Prior; private ViewLifecycleEffect _viewLifecycleEffect; private IDisposable _isLoadedObserverDisposable; protected override void OnAttached() { _viewLifecycleEffect = Element.Effects.OfType<ViewLifecycleEffect>().FirstOrDefault(); UIView nativeView = Control ?? Container; _isLoadedObserverDisposable = nativeView?.AddObserver("superview", _observingOptions, isViewLoadedObserver); CGRect viewBounds = nativeView.Bounds; CGRect windowBounds = UIScreen.MainScreen.Bounds; // Method below works out view in window but needs to be triggered as rows appear in which case wouldnt need to calculate but rather subscribe to some event like the `AddObserver` above if (windowBounds.Contains(nativeView.ConvertRectToView(viewBounds, nativeView.Window))) { _viewLifecycleEffect?.RaiseAppeared(Element); } } protected override void OnDetached() { _viewLifecycleEffect.RaiseDisappeared(Element); _isLoadedObserverDisposable.Dispose(); } private void isViewLoadedObserver(NSObservedChange nsObservedChange) { _viewLifecycleEffect?.RaiseAppeared(Element); } }
Maybe there is a better way then detecting on the View or perhaps on the CollectionView itself?