首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

iOS drawRect 繪圖變黑塊問題:坐標系統與邊界檢查

     編輯:程式設計綜合問答

問題現象

在 drawRect: 中繪製貝塞爾路徑、設置填充顏色、圖片圖案,結果顯示為黑色矩形,而非預期圖形。

核心原因

  1. 繪圖超出 View Bounds:代碼中使用硬編碼座標 CGRectMake(280.0, 3.0, 30, 30),若 View 寬度小於 310pt,繪圖區域超出邊界,被裁剪或異常渲染。
  2. 未根據 View 尺寸動態計算座標:drawRect: 的參數 rect 即當前需繪製區域 (通常等於 self.bounds),所有繪圖座標應相對於此區域計算。
  3. 圖片圖案相位設置可能導致異常:CGContextSetPatternPhase 配合硬編碼座標易產生不可預期結果。

修正代碼

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    
    // 1. 顏色定義
    UIColor *fillColor = [UIColor colorWithRed:0.102 green:0.737 blue:0.612 alpha:1];
    UIColor *strokeColor = [UIColor colorWithRed:0.925 green:0.941 blue:0.945 alpha:0.004]; // 極低透明度,幾乎透明
    
    // 2. 圖片圖案 (確保圖片存在)
    UIImage *image = [UIImage imageNamed:@"image"];
    if (!image) {
        NSLog(@"圖片 'image' 未找到,使用純色填充");
        // 降級處理
    }
    UIColor *patternColor = image ? [UIColor colorWithPatternImage:image] : fillColor;
    
    // 3. 動態計算繪圖區域 (相對於 rect/bounds)
    CGFloat buttonSize = 30.0;
    CGFloat margin = 10.0;
    CGFloat x = rect.size.width - buttonSize - margin; // 右側邊距
    CGFloat y = margin; // 頂部邊距
    CGRect buttonRect = CGRectMake(x, y, buttonSize, buttonSize);
    
    // 4. 繪製主按鈕背景
    UIBezierPath *buttonPath = [UIBezierPath bezierPathWithRect:buttonRect];
    [fillColor setFill];
    [buttonPath fill];
    [strokeColor setStroke];
    buttonPath.lineWidth = 1;
    [buttonPath stroke];
    
    // 5. 繪製圖片圖案覆蓋層 (同樣區域)
    if (image) {
        UIBezierPath *patternPath = [UIBezierPath bezierPathWithRect:buttonRect];
        CGContextSaveGState(context);
        // 圖案相位可根據需求設置,通常用 (0,0) 或按鈕原點
        CGContextSetPatternPhase(context, CGSizeMake(buttonRect.origin.x, buttonRect.origin.y));
        [patternColor setFill];
        [patternPath fill];
        CGContextRestoreGState(context);
        [strokeColor setStroke];
        [patternPath stroke];
    }
}

關鍵修正點

原代碼問題修正方案
硬編碼 CGRectMake(280, 3, 30, 30)動態計算:x = rect.size.width - size - margin
未檢查圖片是否存在添加 if (!image) 降級處理
Stroke 顏色 alpha=0.004 (幾乎透明)確認是否為預期,建議 alpha=1.0 可見邊框
Pattern Phase 硬編碼 (86, 33)相對於繪圖區域原點設置

調試技巧

  • 在 drawRect: 開頭打印 NSLog(@"drawRect: %@", NSStringFromCGRect(rect)) 確認實際繪製區域大小。
  • 使用 UIColor.redColor.setFill; UIRectFill(rect); 先填充整個區域驗證 View 可見範圍。
  • 啟用「Color Offscreen-Rendered Yellow」 (Xcode -> Debug -> View Debugging) 檢測離屏渲染。

最佳實踐

  • **所有座標相對於 rect (即 bounds) 計算**,不依賴固定像素值。
  • 使用 Auto Layout 约束確定 View 尺寸,繪圖代碼自適應。
  • 圖片資源納入 Asset Catalog,確保 @2x/@3x 正確加載。
  • 複雜繪圖考慮拆分為子 View 或使用 CAShapeLayer、CAGradientLayer 等 Core Animation 圖層,性能更優且易維護。

遵循「座標相對化、資源驗證、邊界感知」三原則,可避免 90% 的 drawRect: 異常渲染問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved