1

I already have a custom renderer for scrollview that will create fading edges on Xamarin.android. So my problem now is that my renderer on iOS is not working. Here is what I have:

    using System;
using CoreAnimation;
using CoreGraphics;
using Foundation;
using Omregistrering.CustomControls;
using Omregistrering.iOS.Renderers;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(FadeScrollView), typeof(FadeScrollViewRenderer))]
namespace Omregistrering.iOS.Renderers
{
   public class FadeScrollViewRenderer : ScrollViewRenderer
   {
       private CAGradientLayer gradientLayer;
       private Double FadePercentage = 0.2;
       private CGColor OpaqueColor = UIColor.Black.CGColor;
       protected override void OnElementChanged(VisualElementChangedEventArgs e)
       {
           base.OnElementChanged(e);
           //UpdateScrollView();
       }
       public override void ScrollRectToVisible(CGRect rect, bool animated)
       {
           base.ScrollRectToVisible(rect, animated);
       }
       private void UpdateScrollView()
       {
           // test with Bounces
           ContentInset = new UIKit.UIEdgeInsets(0, 0, 0, 0);
           if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
               ContentInsetAdjustmentBehavior = UIKit.UIScrollViewContentInsetAdjustmentBehavior.Never;
           Bounces = false;
           ScrollIndicatorInsets = new UIKit.UIEdgeInsets(0, 0, 0, 0);
       }
       private CGColor topOpacity()
       {
           var scrollViewHeight = Frame.Size.Height;
           var scrollContentSizeHeight = ContentSize.Height;
           var scrollOffset = ContentOffset.Y;
           nfloat alpha = (scrollViewHeight >= scrollContentSizeHeight || scrollOffset <= 0) ? 1 : 0;
           var color = new UIColor(white: 0, alpha: alpha);
           return color.CGColor;
       }
       private CGColor bottomOpacity()
       {
           var scrollViewHeight = Frame.Size.Height;
           var scrollContentSizeHeight = ContentSize.Height;
           var scrollOffset = ContentOffset.Y;
           nfloat alpha = (scrollViewHeight >= scrollContentSizeHeight || scrollOffset + scrollViewHeight >= scrollContentSizeHeight) ? 1 : 0;
           var color = new UIColor(white: 0, alpha: alpha);
           return color.CGColor;
       }
       public override void Draw(CGRect rect)
       {
           base.Draw(rect);
           gradientLayer = new CAGradientLayer();
           gradientLayer.Frame = rect;
           var maskLayer = new CALayer();
           gradientLayer.Colors = new CGColor[] { topOpacity(), OpaqueColor, OpaqueColor, bottomOpacity() };
           gradientLayer.Locations = new NSNumber[] { 0, (NSNumber)FadePercentage, (NSNumber)(1 - FadePercentage), 1 };
           maskLayer.AddSublayer(gradientLayer);
           this.Layer.Mask = maskLayer;
       }
   }
}

And the result is this: enter image description here

The renderer is fading at the bottom edge but is not updated in any way.The ideer is of course to have fading edges also when scrolling up and down.

Here a screenshot from android were we are in the middle of a scroll and both edges are fading, giving the illusion of more content. enter image description here Anyone who have a solution or has done this on Xamarin.ios Thanks

  • Hi , could you show a screenshot of Android , then I will know the want effect clearly . – Junior Jiang Sep 19 '19 at 06:23
  • Good point. I have updated my question with screenshot on the android part. Fading edge give the illusion of more content. – Anders Blomqvist Sep 19 '19 at 07:22
  • Thanks for updating question. Do you want to keep the blur at the top and bottom? – Junior Jiang Sep 19 '19 at 09:07
  • Blur should only occur when scroll position is not at the end positions. Meaning scroll at top position should have no blur at the top but blur at the bottom if scrollview will not fit screen (content continue below screen). The opposite at the bottom. The screenshot (android) added show the middle position, where we have content above and below the screen. – Anders Blomqvist Sep 19 '19 at 09:41
  • Okey , got it . If have solution will share here . – Junior Jiang Sep 19 '19 at 09:54
  • @AndersBlomqvist Hi, I have same issue. Did you find the solution to this ? – Dhruv Gohil Jul 13 '20 at 08:43

1 Answers1

-1

I don't think you need renderers here. You could use two png with gradient toward transparent, for each edge. Then with ScrollView.Scrolled event, you can know if you reached the top or the bottom of the scroll view. Doing so, you can set the opacity of the 2 images according to the distance from the edge.

In the following example, we'll consider only bottom:

private void OnScrolled(object sender, ScrolledEventArgs e)
{
    MyScrollView scrollView = sender as MyScrollView;
    double scrollingSpace = scrollView.ContentSize.Height - scrollView.Height;

    MyBottomImage.Opacity = 1 - e.ScrollY/scrollingSpace;
}

I hope you get the idea :)

Roubachof
  • 3,351
  • 3
  • 23
  • 34