The goal was to derive from a UIImageView and trigger an Activate event when a specified slider image got within range of the right end of the control. I found this was fairly straightforward to implement using a pan gesture. Below is the class I came up with and the associated images that were used:
Image
Slider
public class UISlideToActivateImageView : UIImageView { #region Fields and Properties public event EventHandler<EventArgs> Activate; protected const float DEFAULT_ACTIVATION_RANGE = 20; public float ActivationRange { get; set; } public static Selector PanSelector { get { return new Selector("HandlePan"); } } private UIImageView _sliderView = null; public UIImage Slider { get { return _sliderView.Image; } set { if (value != null) { if (_sliderView != null) { _sliderView.RemoveFromSuperview(); } _sliderView = new UIImageView( new RectangleF(new PointF(0, 0), value.Size)); _sliderView.Image = value; AddSubview(_sliderView); } } } protected PointF InitialLocation { get; set; } #endregion #region Constructors public UISlideToActivateImageView(PointF location, UIImage image) : base(image) { ActivationRange = DEFAULT_ACTIVATION_RANGE; Frame = new RectangleF(location, image.Size); RegisterPanGesture(); } public UISlideToActivateImageView(PointF location, UIImage image, UIImage slider) : base(image) { ActivationRange = DEFAULT_ACTIVATION_RANGE; Frame = new RectangleF(location, image.Size); Slider = slider; RegisterPanGesture(); } #endregion #region Events, Overrides and Delegates [Export("HandlePan")] public void HandlePan(UIPanGestureRecognizer panGesture) { const double EndedAnimationDuration = 0.2d; PointF newLocation; float adjX; if (panGesture != null) { newLocation = panGesture.LocationInView(this); switch (panGesture.State) { case UIGestureRecognizerState.Began: //User first taps the slider if ((newLocation.X <= (Frame.X + Slider.Size.Width)) && (newLocation.X >= 0)) { InitialLocation = newLocation; } break; case UIGestureRecognizerState.Changed: //Moved their finger - make slider follow horizontal movements adjX = Frame.X + (newLocation.X - InitialLocation.X); if ((InitialLocation != PointF.Empty) && (adjX >= 0) && (adjX <= (Frame.Width - Slider.Size.Width))) { UIView.Animate(0d, delegate() { _sliderView.Frame = new RectangleF(new PointF(adjX, 0), _sliderView.Frame.Size); }); //If the Slider comes within ActivationRange of end of this //control, fire the Activate event if ((Activate != null) && (adjX >= (Frame.Width - Slider.Size.Width - ActivationRange))) { //Moved the slider all the way across the image view Activate(this, EventArgs.Empty); } } break; case UIGestureRecognizerState.Cancelled: case UIGestureRecognizerState.Failed: case UIGestureRecognizerState.Ended: //Lifted up finger - return slider to original position InitialLocation = PointF.Empty; UIView.Animate(EndedAnimationDuration, delegate() { _sliderView.Frame = new RectangleF(new PointF(0, 0), _sliderView.Frame.Size); }); break; } } } //Delegate for allowing the pan gesture recognizer to receive touch. public class ReceiveTouchGestureRecognizerDelegate : UIGestureRecognizerDelegate { public override bool ShouldReceiveTouch ( UIGestureRecognizer recognizer, UITouch touch) { return true; } } #endregion #region Helper Methods protected void RegisterPanGesture() { UserInteractionEnabled = true; UIPanGestureRecognizer pan = new UIPanGestureRecognizer(); pan.AddTarget(this, PanSelector); pan.Delegate = new ReceiveTouchGestureRecognizerDelegate(); AddGestureRecognizer(pan); } #endregion }To use this control it's simply a matter of assigning images (Image and Slider properties) and adding the class as a sub-view:
UISlideToActivateImageView slideToActivate = new UISlideToActivateImageView(new PointF(31, 214), UIImage.FromFile("slidetoactivate.png"), UIImage.FromFile("slider.png")); slideToActivate.Activate += delegate(object sender, EventArgs e) { UIAlertView alert = new UIAlertView("Congratulations!", "You've engaged the UISlideToActivateImageView!", null, "Okay"); alert.Show(); }; View.AddSubview(slideToActivate);