• 自定义View相关


    实现自定义View的关键是重载UIView的drawRect: 方法,因为主要是通过重载这个方法,来改变view的外观。

    例如:

    - (void)drawRect:(CGRect)rect 
    {
    // 绘图
    CGRect bounds = [self bounds];
    // Where is its center?
    CGPoint center;
    center.x = bounds.origin.x + bounds.size.width / 2.0;
    center.y = bounds.origin.y + bounds.size.height / 2.0;
    // From the center how far out to a corner?
    float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;
    // Get the context being drawn upon
    CGContextRef context = UIGraphicsGetCurrentContext();
    // All lines will be drawn 10 points wide
    CGContextSetLineWidth(context, 10);
    // Set the stroke color to light gray
    [[UIColor lightGrayColor] setStroke];
    // Draw concentric circles from the outside in
    for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20)
    {
    CGContextAddArc(context, center.x, center.y,
    currentRadius, 0.0, M_PI * 2.0, YES);
    CGContextStrokePath(context);
    }

        // 绘文字
    NSString *text = @"Hello,World!";
    // Get a font to draw it in
    UIFont *font = [UIFont boldSystemFontOfSize:28];
    // Where am I going to draw it?
    CGRect textRect;
    textRect.size = [text sizeWithFont:font];
    textRect.origin.x = center.x - textRect.size.width / 2.0;
    textRect.origin.y = center.y - textRect.size.height / 2.0;
    // Set the fill color of the current context to black
    [[UIColor blackColor] setFill];
    // Set the shadow to be offset 4 points right, 3 points down,
    // dark gray and with a blur radius of 2 points
    CGSize offset = CGSizeMake(4, 3);
    CGColorRef color = [[UIColor darkGrayColor] CGColor];
    CGContextSetShadowWithColor(context, offset, 2.0, color);
    // Draw the string
    [text drawInRect:textRect
    withFont:font];
    }


    再说明一下重绘,重绘操作仍然在drawRect方法中完成,但是苹果不建议直接调用drawRect方法,当然如果你强直直接调用此方法,当然是没有效果的。

    苹果要求我们调用UIView类中的setNeedsDisplay方法,则程序会自动调用drawRect方法进行重绘。(调用setNeedsDisplay会自动调用drawRect)
    在UIView中,重写drawRect: (CGRect) aRect方法,可以自己定义想要画的图案.且此方法一般情况下只会画一次.也就是说这个drawRect方法一般情况下只会被掉用一次. 当某些情况下想要手动重画这个View,只需要掉用[self setNeedsDisplay]方法即可.

    drawRect调是在Controller->loadView, Controller->viewDidLoad 两方法之后调用的.所以不用担心在控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量值).

    1.如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。
    2.该方法在调用sizeThatFits后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
    3.通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
    4.直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0.
    以上1,2推荐;而3,4不提倡
    1、若使用UIView绘图,只能在drawRect:方法中获取相应的contextRef并绘图。如果在其他方法中获取将获取到一个invalidate的ref并且不能用于画图。drawRect:方法不能手动显示调用,必须通过调用setNeedsDisplay 或者 setNeedsDisplayInRect ,让系统自动调该方法。
    2、若使用calayer绘图,只能在drawInContext: 中(类似于drawRect)绘制,或者在delegate中的相应方法绘制。同样也是调用setNeedDisplay等间接调用以上方法。
    3、若要实时画图,不能使用gestureRecognizer,只能使用touchbegan等方法来掉用setNeedsDisplay实时刷新屏幕

    附高人对UIView的drawRect: 和 - (void)setNeedsDisplay 的一些理解

    在UIView中,

    
    

    1、自定义画图,类似android的onDraw()

    
    

    - (void)drawRect:(CGRect)rect;

     is invoked automaticall,never call it directly!!

    2、刷新视图,类似android的invalidate()

    
    

    - (void)setNeedsDisplay;

    
    

    When a view needs to be redrawn,use: 

    
    

    3、在非主线程中调用,需使用如下方法:

    
    

          - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait
          - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait

    
    

    4、setNeedsDisplay是不阻塞的,
         需要自己制造阻塞,
         setNeedsDisplay我理解就是告诉系统,等会帮哥把这块重新画一下。
         系统就知道了,等系统有空了,他就一起画了,
         如果想立即画出来,可能要用setNeedsLayout,
         或者不用drawInRect系列的方式,直接改view.image或者文字,加动画等方式实现吧。

    
    

    5、setNeedsDisplay和layoutSubViews

    
    

         首先两个方法都是异步执行的。而setNeedsDisplay会调用自动调用drawRect方法,这样可以拿到UIGraphicsGetCurrentContext,就可以画画了。而setNeedsLayout会默认调  用layoutSubViews,就可以处理子视图中的一些数据。
    综上所诉,setNeedsDisplay方便绘图,而layoutSubViews方便出来数据。

     
    复制代码
     
  • 相关阅读:
    Spring Cloud微服务安全实战_5-4_认证服务器使用spring session
    Spring Cloud微服务安全实战_5-3_基于session的SSO
    Spring Cloud微服务安全实战_5-2_实现授权码认证流程&实现SSO初步
    Spring Cloud微服务安全实战_5-1_单点登录基本架构
    Linux启动Spring boot项目命令
    Spring Cloud微服务安全实战_4-10_用spring-cloud-zuul-ratelimit做限流
    Spring Cloud微服务安全实战_4-9_用zuul网关解耦安全逻辑和业务逻辑
    Spring Cloud微服务安全实战_4-8_网关安全_01
    Spring Cloud微服务安全实战_4-7_token&client信息持久化到数据库
    几个好用Maven 镜像仓库地址
  • 原文地址:https://www.cnblogs.com/ranger-jlu/p/3957096.html
Copyright © 2020-2023  润新知