《MonoTouch开发实践指南》一3.5 实现自定义UIView

简介: 本节书摘来自华章出版社《MonoTouch开发实践指南》一 书中的第3章,第3.5节,作者:(美)Michael Bluestein,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

3.5 实现自定义UIView

对于SecondView类,首先要将它设置为UIView的子类,同时添加MonoTouch.UIkit命名空间。要绘制视图,可以调用DrawRect方法。为了给视图添加自定义绘图代码,需要重写DrawRect方法。每一个iOS应用程序都有一个主循环。当给DrawRect添加代码时,它在下一次循环时才会调用。不能在程序中直接调用DrawRect方法,它只能由系统在需要的时候调用。当视图第一次加载的时候,会执行绘图代码,所以不需要额外的步骤去调用DrawRect。当视图在初始绘制后,如果要强制重画,可以调用视图的SetNeedDisplay方法,这样视图就可以在事件循环过程中进行重画。
在执行自定义绘图时,可通过视图的图形上下文(graphics context)进行绘制操作。图形上下文是用户绘图用的抽象画布(如屏幕),可在上面使用任何可用的画图工具(如颜色笔、几何形状等)进行画图。代码清单3-6列出了部分SecondView类用于绘制一个正方形的代码。
注意 视图的绘图工作实际通过层技术实现,这将在第6章进行详细讲述。
代码清单3-6 自定义绘图UIView

using System;
using MonoTouch.UIKit;
using MonoTouch.CoreGraphics;
using System.Drawing;

namespace LMT33
{
    public class SecondView : UIView
    {
        CGPath _path;

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

            // Get graphics context
            CGContext gctx = UIGraphics.GetCurrentContext ();

            // Set up drawing attributes
            gctx.SetLineWidth (2);
            UIColor.Gray.SetFill ();
            UIColor.Black.SetStroke ();

            // Create geometry
            _path = new CGPath ();

            _path.AddLines (new PointF[] {
                new PointF (110, 100),
                new PointF (210, 100),
                new PointF (210, 200),
                new PointF (110, 200) });

            _path.CloseSubpath ();

            // Add geometry to graphics context and draw it
            gctx.AddPath (_path);
            gctx.DrawPath (CGPathDrawingMode.FillStroke);
        }
    }
}

代码清单3-6中的绘图代码使用了核心图形(Core Graphics)功能,这会在第6章讲述。也可以在UIView实现中直接使用UIKit类。例如,在UIView内使用UILabel显示视图的标题,并通过提供标题(title)属性让控制器设置标题,代码如下:

...
string _title;
UILabel _titleLabel;

public string Title {
    get { return _title; }
    set {
          _title = value;
          _titleLabel.Text = _title;
    }
}

public SecondView ()
{
    _titleLabel = new UILabel ();
}

...

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

    _titleLabel.Frame = new RectangleF(5,5,Bounds.Width-10, 25);
    this.AddSubview (_titleLabel);
}

注意 如果不使用UILabel,而是使用核心图形(Core Graphics)功能直接绘制标题的字符串,那么需要在设置标题时调用SetNeedDisplay方法。尽管在初始化时看不到标题,但调用者会改变视图的标题。当更改标题时,调用SetNeedsDisplay方法可以重画视图。当更改标题时,UILabel会在内部调用SetNeedsDisplay方法。
代码中添加了一个包含标题的UILabel作为子视图。视图是按层次结构排列。当添加一个子视图到一个视图时,无论是在视图内部实现(如当前示例的UILabel),还是在外部通过控制器或IB的视图类实现,按照z次序放置子视图都会位于其父视图的上方。如果现在运行应用程序并选择第二个标签,将会看到绘制有标题和正方形的屏幕(如图3-11所示)。
在该示例中,标签使用了Frame属性和父视图的Bounds对象来设置其大小和位置。Frame属性将视图的大小设置为一个矩形,它的位置则由父视图坐标系中的点决定,而边界则由视图自己坐标系的大小和位置决定。通常情况下,Frame属性用来设置视图实例的大小和位置,而不是在一个实际的视图实现中作为边界使用。例如,在该示例中使用UILabel的实例,而不是SecondView的实现。在该示例中,父视图就是secondView。设置UILabel的Frame属性,定义矩形的大小和位置是以父视图的原点为测量点的。iOS坐标系的原点在左上角,往右就是+x,往下就是+y。
注意 在设置视图的Frame属性时,它实际上并不存储在视图内,而是用来从内部获得其他值,如边界。同样,这将在第6章中讲述。
视图要做的另外一件事情就是捕捉事件,如触碰事件。如果检查代码清单3-7中的UIView的类层次结构,就会看到它派生于UIResponder,除此之外,还定义了几个虚函数用来处理触碰事件。为了演示这一点,现在在视图中添加一个简单的命中测试以检测用户是否触碰了正方形。
代码清单3-7 UIResponder使用虚函数处理触碰事件

public class UIResponder : NSObject
{
    ...
    public virtual void TouchesBegan (NSSet touches, UIEvent evt);
    public virtual void TouchesMoved (NSSet touches, UIEvent evt);
    public virtual void TouchesEnded (NSSet touches, UIEvent evt);
    public virtual void TouchesCancelled (NSSet touches, UIEvent evt);
    ...
}

要判断是否触碰了正方形,需要重写UIView子类的TouchesBegan方法,详细代码请看代码清单3-8。为了简单起见,这里只处理单一的触碰。触碰点封装在UITouch类中。要找到视图的实际触碰点,可以调用UITouch对象的LocationInView方法,它将返回视图坐标系内的点。
代码清单3-8 在UIView子类中处理触碰事件

public override void TouchesBegan (NSSet touches, UIEvent evt)
{
    base.TouchesBegan (touches, evt);

    UITouch touch = touches.AnyObject as UITouch;

    if (touch != null) {
        PointF pt = touch.LocationInView (this);

        if (_path.ContainsPoint (pt, true)) {
            Title = "You touched the square";
        } else {
            Title = "You didn't touch the square";
        }
    }
}

之前使用核心图形的路径功能来绘制正方形。在路径中有个ContainsPoint函数可以用来执行命中测试,将UITouch返回的点传递到该函数,它告知点是在路径组成的正方形内还是在正方形外。然后就可以通过标题将结果输出给用户(如图3-12所示)。

screenshot

相关文章
|
8月前
|
前端开发 IDE JavaScript
 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之RichText组件
 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之RichText组件
380 4
|
XML 编解码 编译器
Unity跨平台UI解决方案:可能是最全的FairyGUI系列教程-第八天
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
1744 0
|
5月前
|
容器 iOS开发 Linux
震惊!Uno Platform 响应式 UI 构建秘籍大公开!从布局容器到自适应设计,带你轻松打造跨平台完美界面
【8月更文挑战第31天】Uno Platform 是一款强大的跨平台应用开发框架,支持 Web、桌面(Windows、macOS、Linux)及移动(iOS、Android)等平台,仅需单一代码库。本文分享了四个构建响应式用户界面的最佳实践:利用布局容器(如 Grid)适配不同屏幕尺寸;采用自适应布局调整 UI;使用媒体查询定制样式;遵循响应式设计原则确保 UI 元素自适应调整。通过这些方法,开发者可以为用户提供一致且优秀的多设备体验。
210 0
|
8月前
|
搜索推荐 iOS开发 开发者
利用SwiftUI构建动态用户界面:iOS开发新篇章
【4月更文挑战第10天】在移动应用的世界中,流畅的用户体验和引人注目的界面设计是至关重要的。随着SwiftUI的推出,iOS开发者被赋予了创造高度动态且响应式界面的能力。本文将深入探讨如何利用SwiftUI的强大特性来实现一个动态用户界面,包括其声明性语法、状态绑定以及视图更新机制。我们将通过一个天气应用案例,了解如何有效地运用这些工具来提升应用的交互性和视觉吸引力。
|
API 图形学 Android开发
Unity跨平台UI解决方案:可能是最全的FairyGUI系列教程-第七天
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
1060 0
|
图形学 开发者 iOS开发
iOS开发CoreGraphics核心图形框架之二——深入理解图形上下文(一)
iOS开发CoreGraphics核心图形框架之二——深入理解图形上下文
421 0
iOS开发CoreGraphics核心图形框架之二——深入理解图形上下文(一)
|
API 数据安全/隐私保护 iOS开发
iOS开发CoreGraphics核心图形框架之二——深入理解图形上下文(二)
iOS开发CoreGraphics核心图形框架之二——深入理解图形上下文
401 0
|
存储 传感器 API
C#使用Xamarin开发可移植移动应用终章(11.获取设备信息与常用组件,开源一个可开发模版.)
原文:C#使用Xamarin开发可移植移动应用终章(11.获取设备信息与常用组件,开源一个可开发模版.) 前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.
1729 0
|
C# Android开发 iOS开发
C#使用Xamarin开发可移植移动应用进阶篇(6.使用渲染器针对单个平台自定义控件..很很很很重要..),附源码
原文:C#使用Xamarin开发可移植移动应用进阶篇(6.使用渲染器针对单个平台自定义控件..很很很很重要..),附源码 前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.
1307 0

热门文章

最新文章

下一篇
开通oss服务