summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs')
-rw-r--r--Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs215
1 files changed, 215 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs b/Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs
new file mode 100644
index 00000000..7b544b25
--- /dev/null
+++ b/Xamarin.Forms.Platform.Android/AppCompat/FrameRenderer.cs
@@ -0,0 +1,215 @@
+using System;
+using System.ComponentModel;
+using Android.Content;
+using Android.Support.V4.View;
+using Android.Support.V7.Widget;
+using Android.Views;
+using AColor = Android.Graphics.Color;
+using AView = Android.Views.View;
+
+namespace Xamarin.Forms.Platform.Android.AppCompat
+{
+ public class FrameRenderer : CardView, IVisualElementRenderer, AView.IOnClickListener, AView.IOnTouchListener
+ {
+ readonly Lazy<GestureDetector> _gestureDetector;
+ readonly PanGestureHandler _panGestureHandler;
+ readonly PinchGestureHandler _pinchGestureHandler;
+ readonly Lazy<ScaleGestureDetector> _scaleDetector;
+ readonly TapGestureHandler _tapGestureHandler;
+
+ float _defaultElevation = -1f;
+
+ bool _disposed;
+ Frame _element;
+ InnerGestureListener _gestureListener;
+ VisualElementPackager _visualElementPackager;
+ VisualElementTracker _visualElementTracker;
+
+ public FrameRenderer() : base(Forms.Context)
+ {
+ _tapGestureHandler = new TapGestureHandler(() => Element);
+ _panGestureHandler = new PanGestureHandler(() => Element, Context.FromPixels);
+ _pinchGestureHandler = new PinchGestureHandler(() => Element);
+
+ _gestureDetector =
+ new Lazy<GestureDetector>(
+ () =>
+ new GestureDetector(
+ _gestureListener =
+ new InnerGestureListener(_tapGestureHandler.OnTap, _tapGestureHandler.TapGestureRecognizers, _panGestureHandler.OnPan, _panGestureHandler.OnPanStarted, _panGestureHandler.OnPanComplete)));
+
+ _scaleDetector =
+ new Lazy<ScaleGestureDetector>(
+ () => new ScaleGestureDetector(Context, new InnerScaleListener(_pinchGestureHandler.OnPinch, _pinchGestureHandler.OnPinchStarted, _pinchGestureHandler.OnPinchEnded), Handler));
+ }
+
+ protected CardView Control => this;
+
+ protected Frame Element
+ {
+ get { return _element; }
+ set
+ {
+ if (_element == value)
+ return;
+
+ Frame oldElement = _element;
+ _element = value;
+
+ OnElementChanged(new ElementChangedEventArgs<Frame>(oldElement, _element));
+
+ if (_element != null)
+ _element.SendViewInitialized(Control);
+ }
+ }
+
+ void IOnClickListener.OnClick(AView v)
+ {
+ _tapGestureHandler.OnSingleClick();
+ }
+
+ bool IOnTouchListener.OnTouch(AView v, MotionEvent e)
+ {
+ var handled = false;
+ if (_pinchGestureHandler.IsPinchSupported)
+ {
+ if (!_scaleDetector.IsValueCreated)
+ ScaleGestureDetectorCompat.SetQuickScaleEnabled(_scaleDetector.Value, true);
+ handled = _scaleDetector.Value.OnTouchEvent(e);
+ }
+ return _gestureDetector.Value.OnTouchEvent(e) || handled;
+ }
+
+ VisualElement IVisualElementRenderer.Element => Element;
+
+ public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
+
+ SizeRequest IVisualElementRenderer.GetDesiredSize(int widthConstraint, int heightConstraint)
+ {
+ Context context = Context;
+ return new SizeRequest(new Size(context.ToPixels(20), context.ToPixels(20)));
+ }
+
+ void IVisualElementRenderer.SetElement(VisualElement element)
+ {
+ var frame = element as Frame;
+ if (frame == null)
+ throw new ArgumentException("Element must be of type Frame");
+ Element = frame;
+
+ if (!string.IsNullOrEmpty(Element.AutomationId))
+ ContentDescription = Element.AutomationId;
+ }
+
+ VisualElementTracker IVisualElementRenderer.Tracker => _visualElementTracker;
+
+ void IVisualElementRenderer.UpdateLayout()
+ {
+ VisualElementTracker tracker = _visualElementTracker;
+ tracker?.UpdateLayout();
+ }
+
+ ViewGroup IVisualElementRenderer.ViewGroup => this;
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && !_disposed)
+ {
+ _disposed = true;
+
+ if (_gestureListener != null)
+ {
+ _gestureListener.Dispose();
+ _gestureListener = null;
+ }
+
+ if (_visualElementTracker != null)
+ {
+ _visualElementTracker.Dispose();
+ _visualElementTracker = null;
+ }
+
+ if (_visualElementPackager != null)
+ {
+ _visualElementPackager.Dispose();
+ _visualElementPackager = null;
+ }
+
+ if (Element != null)
+ Element.PropertyChanged -= OnElementPropertyChanged;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ protected virtual void OnElementChanged(ElementChangedEventArgs<Frame> e)
+ {
+ ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement));
+
+ if (e.OldElement != null)
+ e.OldElement.PropertyChanged -= OnElementPropertyChanged;
+ else
+ {
+ SetOnClickListener(this);
+ SetOnTouchListener(this);
+ }
+
+ if (e.NewElement != null)
+ {
+ if (_visualElementTracker == null)
+ {
+ _visualElementTracker = new VisualElementTracker(this);
+ _visualElementPackager = new VisualElementPackager(this);
+ _visualElementPackager.Load();
+ }
+
+ e.NewElement.PropertyChanged += OnElementPropertyChanged;
+ UpdateShadow();
+ UpdateBackgroundColor();
+ }
+ }
+
+ protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
+ {
+ if (Element == null)
+ return;
+
+ var children = Element.LogicalChildren;
+ for (var i = 0; i < children.Count; i++)
+ {
+ var visualElement = children[i] as VisualElement;
+ if (visualElement == null)
+ continue;
+ IVisualElementRenderer renderer = Android.Platform.GetRenderer(visualElement);
+ renderer?.UpdateLayout();
+ }
+ }
+
+ void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == Frame.HasShadowProperty.PropertyName)
+ UpdateShadow();
+ else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName)
+ UpdateBackgroundColor();
+ }
+
+ void UpdateBackgroundColor()
+ {
+ Color bgColor = Element.BackgroundColor;
+ SetCardBackgroundColor(bgColor.IsDefault ? AColor.White : bgColor.ToAndroid());
+ }
+
+ void UpdateShadow()
+ {
+ float elevation = _defaultElevation;
+
+ if (elevation == -1f)
+ _defaultElevation = elevation = CardElevation;
+
+ if (Element.HasShadow)
+ CardElevation = elevation;
+ else
+ CardElevation = 0f;
+ }
+ }
+} \ No newline at end of file