UIKit.UIView Class
Base class used for components that want to render themselves and respond to events.

See Also: UIView Members

Syntax

[Foundation.Register("UIView", true)]
public class UIView : UIResponder, Foundation.INSCoding, IUIAccessibilityIdentification, IUICoordinateSpace, IUIDynamicItem, IUITraitEnvironment, IEnumerable, IDisposable

Remarks

The UIView class is a rectangular area on the screen that is responsible for displaying content and handling user interactions with that content. It can also contain other views, allowing you to create complex interactive controls. UIView can thus be used as either a standalone control, or a full screen of content built from many other independent UIViews.

Views have three major responsibilities:

Event Handling

UIViews can handle touch events in two ways. You can use the high-level gesture recognizer API to detect and handle gestures, or you can roll your own event handling by using the low-level interface that provides detailed touch events as they happen: every time a finger touches the screen or is lifted as well as motion of those fingers. Both are covered below

When your UIView wants to respond to user input by updating its display, it should call the UIView.SetNeedsDisplay or UIView.SetNeedsDisplayInRect(System.Drawing.CoreGraphics.CGRect) which will queue a call to your UIView.Draw(System.Drawing.CoreGraphics.CGRect) method where you would re-render your control with the new state.

Event delivery can be turned off either by setting the UIView.UserInteractionEnabled to false or you can disable them temporarily at the application level by calling UIApplication.BeginIgnoringInteractionEvents. In both cases, events destined for the view are dropped and are not delivered to the views.

Events are disabled while animation are playing back. You can change this behavior when using explicit animations by using the UIKit.UIViewAnimationOptions's AllowUserInteraction flag in your animation.

Event Handling with Gesture Recognizers

Interacting with touch interfaces has lead to a series of common gesture idioms that are used everywhere. Gestures like swiping, panning, long-presses, pinching rotating and tapping. iOS makes the process of detecting these common gesture idioms very easy by providing Gesture Recognizers. These are objects that inherit from the UIGestureRecognizer class and can detect various standard gesture idioms. The built-in recognizers include:

In addition, you can create your own custom gesture recognizer by subclassing UIKit.UIGestureRecognizer.

To use the recognizer, you need to create an instance of the specific kind of recognizer that you need, optionally set some parameters and then you add it to the view by calling AddGestureRecognizer. It is possible to attach multiple gesture recognizers to a single view.

For example, the following code create a gesture recognizer that detects a panning gesture and assigns it to myView:

C# Example

var recognizer = new UIPanGestureRecognizer ((g) => {
  Console.WriteLine ("Panning detected");
  Console.WriteLine ("Gesture recognizer state: {0}", g.State);
});

myView.AddGestureRecognizer (recognizer);
        

The parameter passed to your lambda (in this case the "g" parameter) is an instance of the gesture recognizer that detected the gesture. You can query the parameters of the recognized query by looking at the properties in the recognizer, the UIGestureRecognizer.State property contains the recognizer state.

Event Handling with method Overrides

Although Gesture Recognizers provide a high-level and convenient way of capturing many touch events, they do not cover every possibility. For those cases, developers should subclass UIView and override one or more of the following methods inherited from UIResponder:

UIViews by default only handle a single touch event at once. If you want your view to handle multiple touches, you must set the UIView.MultipleTouchEnabled to true.

iOS creates a T:UIKit.UIEvent object any time a finger touches the screen, moves or is removed from the screen. The UIKit.UIEvent encapsulates all of the touches that are taking place on the screen at this point, even those that do not belong to this view. In addition to the UIKit.UIEvent, there is an Foundation.NSSet containing UIKit.UITouch objects that represent the state of each finger on the screen for this particular view.

If your application handles touches directly, you might want to override the UIView.GestureRecognizerShouldBegin(UIGestureRecognizer) method to control whether an associated UIKit.UIGestureRecognizer should execute or not.

Creating Views

UIViews are typically created by invoking the constructor that takes a frame as its parameter (the frame is of type System.Drawing.RectangleF), for example:

C# Example

var myView = new UIView (new RectangleF (0, 0, 100, 100));

Most subclasses of UIView will provide a constructor that takes the initial frame, just like UIView. For more information on how to do this for your own subclasses, see the section below on subclassing UIView.

You will want to configure your view at this point. One of the most important properties to configure is the UIView.AutoresizingMask which determines how the view will be resized if you invoke UIView.SetNeedsLayout() or if the geometry of the view container changes (for example, in response to a device rotation).

Once you have created a view, you will add it to a container view. For your main screen this could be a UIWindow or it could be the UIViewController.View property of your current UIKit.UIViewController, this is done using one of the following methods:

Although you can use the above APIs to add subviews to any UIView, Apple advises developers against extending existing high-level views by adding subviews to them behind their back. Instead developers should use the public API those high-level views expose.

Bounds and Sizes

Each view is created with an initial UIView.Frame. The Frame is a System.Drawing.RectangleF structure that represents both the size and the initial position for the view. The coordinates for the Frame are used to specify the position relative to its superview.

You can resize and move views around using the frame. Every time you set the frame the view will layout its subviews. If you are purely moving the view, using frame can cause performance issues, as it relays out the view and all its subviews.

The UIView.Bounds is the usable frame of the view. Unlike the UIView.Frame, the UIView.Bounds do not use the container's coordinate space, but instead represent the size in the view's own coordinate space. By default the UIView.Bounds location is (0,0).

When you update the UIView.Bounds property, it will modify the UIView.Frame based on the value of the UIView.Center. You can also change the position of your view by updating the UIView.Center property.

When the UIView.Bound property is changed, the size of the view is affected relative to the UIView.Center property.

Animation

There are two styles of animations supported by UIViews, implicit animations and explicit animations.

Implicit animations happen automatically when you modify the UIView.Frame, UIView.Bounds, UIView.Center, UIView.Transform, UIView.Alpha, UIView.BackgroundColor or UIView.ContentStretch properties in a view. The system will automatically animate the change using the system defaults. When you modify any of these animatable properties in the view, iOS automatically creates an animation transaction which starts as soon as control returns to the main loop.

For example, the following code will animate a view's UIView.Bounds and UIView.Center

C# Example

view.Bounds = new RectangleF (0, 0, 100, 100);
view.Center = new PointF (200, 200);

Alternatively, you can create animations explicitly by calling the UIView.BeginAnimations(string) method, configuring the animation, making the changes to the animatable properties and then completing the transaction by calling UIView.CommitAnimations().

Once you call UIView.BeginAnimations(string), you can call these methods to configure the animation:

The following example shows how to use these methods in a transaction:

C# Example

UIView.BeginAnimations (null);
UIView.SetAnimationDuration (5);
UIView.SetAnimationCurve (UIViewAnimationCurve.EaseOut);
view.Bounds = new RectangleF (0, 0, 100, 100);
view.Position = new PointF (200, 200);
UIView.CommitAnimations ();

An alternative to create the transactions and set the configuration options is to use the new UIView.Animate collection of methods that allow you to specify in a single call the delay, the duration, the animation block and an action to be invoked when the animation completes:

C# Example

UIView.Animate (duration, delay, UIViewAnimationOption.Autoreverse,
  delegate {
      view.Bounds = new RectangleF (0, 0, 100, 100);
      view.Position = new PointF (200, 200);
   },
   delegate {
       Console.WriteLine ("Animation completed");
   }
);
          

The above is the basic set of animations supported by UIViews. If you want finer control over animations you can resort to animations done directly using CoreAnimation. CoreAnimation allows you to animate layers and properties of your C# objects.

Threading

UIView methods are not thread safe, so you should avoid configuring or invoking any of the UIView static methods from any thread that is not the main thread. Newer versions of MonoTouch catch these mistakes in Debug builds by throwing an exception. See the UIApplication.CheckForIllegalCrossThreadCalls for more information.

If you want to perform some work in a background thread that must update any of the UIView properties or you want to invoke any of the UIView static methods, you should use either the Foundation.NSObject.BeginInvokeOnMainThread() or Foundation.NSObject.InvokeOnMainThread() methods. Both methods take a C# delegate or lambda that is invoked on the main thread.

The Foundation.NSObject.InvokeOnMainThread() method will invoke the specified delegate method synchronously on the main thread. The Foundation.NSObject.BeginInvokeOnMainThread() will queue the action to be executed on the main thread.

Example:

C# Example

//
// This performs an expensive computation in the background, and then
// updates the main UI when done.
//
void DoSomeWork (UIView view)
{
  double sum = 0;
  for (int i = 0; i < Int32.MaxValue; i++)
      sum += i * i;

  // Now invoke the update on the main UI.
  view.BeginInvokeOnMainThread (delegate {
      view.BackgroundColor = UIColor.Green;
      statusLabel.Text = "Sum is: " + sum;
  });
}
          

The following example shows a helper method that can be used to run the provided action on the main thread. It optimizes for the case where you are calling this from the main thread already, and avoids a trip to the main loop pump:

C# Example

static NSObject Invoker = new NSObject();
public static void EnsureInvokedOnMainThread (Action action)
{
    if (NSThread.Current.IsMainThread) {
        action ();
        return;
    }
    Invoker.BeginInvokeOnMainThread (() => action());
}
        

How to Subclass UIView

Developers will often subclass UIView to provide their own custom views to use. This section discusses the different classes of members that developers would overwrite to create their custom classes.

Initialization

Your subclass of UIView should chain into either the UIView constructor that is initialized with an initial frame (UIView(System.Drawing.RectangleF)). You would typically do this like this:

C# Example

public class MyView : UIView {
    public MyView (RectangleF frame) : base (frame)
    {
        // Your initialization code goes here
    }
}
          

If your object will be deserialized from an archive produced by the UI designer, you would need to chain to the UIView(Foundation.NSCoder) constructor and also flag the constructor as being the one implementing the selector "initWithCoder:", like this:

C# Example

public class MyView : UIView {
    [Export ("initWithCoder:")]
    public MyView (NSCoder coder) : base (coder)
    {
        // Your initialization code goes here
    }
}
          

By default UIViews will use a CoreAnimation.CALayer instance for their backing store. The section on "Changing the CALayer" below has both information on how to make this change and a sample.

If your view will contains any other subviews, you should initialize those values in your constructor.

Custom Drawing

To implement custom drawing code in a view, you can subclass the UIView and override the UIView.Draw(System.Drawing.CoreGraphics.CGRect) method. The drawing code placed in the Draw method can use CoreGraphics to draw with. The steps to draw with Core Graphics are:

For example, the following code shows an implementation of an overridden Draw method that draws a triangle:

C# Example

public override void Draw (RectangleF rect)
{
    base.Draw (rect);

    var context = UIGraphics.GetCurrentContext ();

    context.SetLineWidth(4);
    UIColor.Red.SetFill ();
    UIColor.Blue.SetStroke ();

    var path = new CGPath ();

    path.AddLines(new PointF[]{
        new PointF(100,200),
        new PointF(160,100), 
        new PointF(220,200)
    });

    path.CloseSubpath();

    context.AddPath(path);		
    context.DrawPath(CGPathDrawingMode.FillStroke);
}
          

The UIView.Draw method should never be called directly. It is called by iOS during run loop processing. The first time through the run loop, it is called. After that, it will be called on demand whenever the view has been marked as needing display by calling UIView.SetNeedsDisplay or UIView.SetNeedsDisplayInRect(System.Drawing.CoreGraphics.CGRect).

Core Graphics uses device independent points rather than pixels. This allows drawing code to scale between different resolutions. For example, on a Retina display, 1 point is equivalent to 2 pixels, while on non-Retina displays, 1 point corresponds to 1 pixel.

Printing

UIViews can be printed. The default behavior is for the contents of the UIView as rendered by the UIView.Draw(System.Drawing.CoreGraphics.CGRect) method to be printed.

If you need to provide a different rendering for the view when printed, you should override the UIView.DrawRect(System.Drawing.CoreGraphics.CGRect, UIKit.UIView.UIViewPrintFormatter) method.

Constraints

If you want your view subclass to use the new constraint-based layout system introduced with iOS 6.0, your subclass needs to respond to the requiresConstraintBasedLayout selector, like this:

C# Example

class MyView : UIView {
    [Export ("requiresConstraintBasedLayout")]
    bool UseNewLayout ()
    {
        return true;
    }
}
          

If your view will use constraints among its own subviews to lay them out, you should override the P:UIKit.UIView.UpdateConstraints which is called before the constraints-based layout is performed.

Constraints-based layout is performed on the alignment rectangle instead of the view's UIView.Frame. The alignment rectangle by default is computed as the UIView.Frame modified by the UIView.AlignmentRectInsets. You can change that behavior and provide your own alignment rectangle by overriding the UIView.AlignmentRectForFrame(System.Drawing.CoreGraphics.CGRect) and UIView.FrameForAlignmentRect(System.Drawing.CoreGraphics.CGRect) methods.

Layout

The default layout system for UIViews is very simple. UIViews are created with an initial UIView.Frame and an UIView.AutoresizingMask that determines how the view will be resized in response to changes in the container's boundaries.

You should set the default UIView.AutoresizingMask property after initialization.

If your view will be a container for other views, you should configure their UIView.AutoresizingMask property. If the layout behavior provided is not sufficient, you should override the UIView.LayoutSubviews() method. This method is responsible for updating the UIView.Frame property of each of the subviews.

If the state of your view changes in response to some API calls, instead of changing the layout manually in response to the change, you should invoke the UIView.SetNeedsLayout() method which will flag the view for a layout. The layout event will then be processed the next time the main loop runs. By using this approach, you can coalesce multiple changes to the layout in a single pass.

UIViews can implement the UIView.SizeThatFits(System.Drawing.CoreGraphics.CGSize) method to report back what is their desired size based on the contents of the view.

You can override the UIView.SubviewAdded(UIView) and the UIView.WillRemoveSubview(UIView) to track when subviews are added or removed to your UIView.

You can override the UIView.WillMoveToWindow(UIWindow) and the UIView.MovedToWindow() to track when your view is moved from one UIKit.UIWindow to another.

You can override the UIView.WillMoveToSuperview(UIView) and the UIView.MovedToSuperview() to track when your view is added or removed from a superview.

Constraints Based Layout

Starting with iOS 6.0 there is a new layout system available to developers, the constraints-based layout system. This system differs from the traditional layout system in that it uses rules (constraints) that describe the relationships between subviews that should be preserved. When views change in size (for example a label is updated) or the size of the container changes (for example, after a rotation), the new positions and sizes for the subviews are computed based on these constraints.

To opt into this system, a subclass of UIView should expose a static method that is exported as "requiresConstraintBasedLayout" and returns true, like this:

C# Example

class MyView : UIView {
    [Export ("requiresConstraintBasedLayout")]
    static bool RequiresConstraintBasedLayout ()
    {
        return true;
    }
}
          

Event Handling

If you are using gesture recognizers, you can add those directly to your constructor at initialization time.

For the low-level touch event handling, you should override the UIResponder.TouchesBegan(Foundation.NSSet, UIEvent), UIResponder.TouchesMoved(Foundation.NSSet, UIEvent), UIResponder.TouchesEnded(Foundation.NSSet, UIEvent) and UIResponder.TouchesCancelled(Foundation.NSSet, UIEvent) methods.

You do not need to call the base methods for any of the above methods if you are overriding UIView directly. But you might want to call base if you are deriving from another UIView subclass.

You can control whether a gesture recognizer is activated by overriding the UIView.GestureRecognizerShouldBegin(UIGestureRecognizer) method.

Views and CALayers

Each UIView is backed by a CoreAnimation Layer (CoreAnimation.CALayer). A CALayer represents the GPU-backed bitmap that is used to render your view into the screen. When you paint into a UIView, you are actually painting into the CALayer.

While the appearance of a UIView can be controlled by setting its UIView.Frame, UIView.Alpha, UIView.BackgroundColor, or by overriding its UIView.Draw method, all those properties and functions are in fact modifying the CoreAnimation.CALayer owned by the view.

The UIView.Layer property is a reference to the CALayer owned by the view. You can change the appearance of the view by modifying the properties of that layer.

For example, you can add rounded corners to the UIView by modifying the CoreAnimation.CALayer.CornerRadius of its layer:

C# Example

view.Layer.CornerRadius = 4;
        

You can add drop shadows by modifying a variety of properties:

C# Example

view.Layer.ShadowColor = new CGColor (1, 0, 0);
view.Layer.ShadowOpacity = 1.0f;
view.Layer.ShadowOffset = new SizeF (0, 4);
        

You can even apply a 3D transformation to the layer:

C# Example

view.Layer.Transform = CATransform3D.MakeRotation ((float)(Math.PI / 2), 1, 1, 1);
        

Note that this transformation is a full 3D transform, with a perspective element, that is more versatile than UIView's 2D Transform property. If you apply 3D transforms, you should no longer use the Frame property

Changing the CALayer

The UIView.Layer owned by a view is automatically created and assigned to the view by UIKit and it defaults to be a CoreAnimation.CALayer instance. You can control the type of layer that is created for a view by responding to the "layerClass" selector in a static method.

Here is an example of a UIView subclass that uses a custom CoreAnimation.CALayer to do its drawing. This layer, and therefore the view, always displays the color blue:

C# Example

public class BlueView : UIView
{
    [Export ("layerClass")]
    public static Class GetLayerClass ()
    {
        return new Class (typeof (BlueLayer));
    }

    public override void Draw (RectangleF rect)
    {
        // Do nothing, the Layer will do all the drawing
    }
}

public class BlueLayer : CALayer
{
    public override void DrawInContext (CGContext ctx)
    {
        ctx.SetFillColor (0, 0, 1, 1);
        ctx.FillRect (Bounds);
    }
}
          

In this example, a new UIView class called "BlueView" is created. It exports a static method called "GetLayerClass" that tells UIKit the type of layer that this view wishes to own. In this example, the BlueView wishes to own a BlueLayer.

It is now up to the BlueLayer to provide the visual representation of the view. It does this by executing CoreGraphics drawing code in its CoreAnimation.CALayer.DrawInContext(CoreGraphics.CGContext) method. This method is very similar to a UIView's Draw method but is used to fill the layer.

Even though the BlueLayer will do all drawing for the BlueView, the view must still override its Draw method. This override should do nothing and is just a signal to UIKit that the Layer will do all the work.

Motion Effects

Motion Effects are a family of effects that can be applied to UIViews in response to external events, typically the device tilt.

You can tie to motion effects the same properties that are animatable already. UIKit ships with UIKit.UIInterpolatingMotionEffect which allows you to controls a single property in response to a device tilt.

One you create an effect, you can attach it to a view by calling the UIView.AddMotionEffect method and remove it by calling UIView.RemoveMotionEffect method. The UIView.MotionEffects property can also be used to query or set a number of motion effects at once.

You can also create your own motion effects by subclassing the UIKit.UIMotionEffect.

Tint Color

Starting with iOS 7, the UIView.TintColor property will now propagate to subviews. This allows applications to set a global tint color, and the color will be passed down to subviews for views that matter. Some UIViews will respond specially based on the TintColor. You should also set the UIView.TintAdjustmentMode to control the desaturation when some views are no longer active.

View Hierarchies

iOS user interfaces are built from UIKit.UIView hierarchies. Parent-child relationships determine not only the visual aspects of the UI, but determine how the application responds to touch events and orientation changes.

View relationships may be built programmatically or via XIB files. UIKit.UIViews may have many UIView.Subviews but only one UIView.Superview.

The most common way to add subviews is to use UIView.AddSubview, which appends the child view to the list of UIView.Subviews. More precise control of ordering during insertion may be done with the UIView.InsertSubview, UIView.InsertSubviewAbove, and UIView.InsertSubviewBelow methods.

The ordering of UIView.Subviews may be manipulated with the UIView.BringSubviewToFront, UIView.SendSubviewToBack, and UIView.ExchangeSubview methods.

Related content

Requirements

Namespace: UIKit
Assembly: Xamarin.iOS (in Xamarin.iOS.dll)
Assembly Versions: 0.0.0.0