13

ここにある OSX Mavericks ロゴのように、テキストが形状から切り取られ、ビューの背後の背景が透けて見えるように、UIView のサブクラスにテキストを描画したいと考えています。

私はどちらかというと中級/初級の上級 iOS 開発者なので、おかしな解決策を私にぶつけてください。これを行うには、オーバーライドdrawRectする必要があると思います。

みんなありがとう!

編集:

私の最初の試みは、テキスト[UIColor clearColor]のアルファ コンポーネントを 0 に設定しただけで機能しなかったテキストを作成していたことに言及する必要があります。

4

4 に答える 4

18

免責事項: 私はテストせずにこれを書いているので、ここで間違っている場合はご容赦ください。

次の 2 つの手順で必要なものを達成する必要があります。

  1. CATextLayerビューのサイズで を作成し、をbackgroundColor完全に透明にforegroundColorして不透明に設定します ([UIColor colorWithWhite:0 alpha:1]と を使用) [UIColor colorWithWhite:0 alpha:0]。次に、プロパティをレンダリングする文字列に設定しstringます。fontfontSize

  2. ビューのレイヤーのマスクをこのレイヤーに設定します: myView.layer.mask = textLayer. QuartzCoreビューの にアクセスするには、インポートする必要がCALayerあります。

最初のステップで不透明色と透明色を切り替えた可能性があることに注意してください。

編集:確かに、ノアは正しかった。これを克服するために、kCGBlendModeDestinationOutブレンド モードで CoreGraphics を使用しました。

まず、実際に機能することを示すサンプル ビュー:

@implementation TestView

- (id)initWithFrame:(CGRect)frame {
  if (self = [super initWithFrame:frame]) {
    self.backgroundColor = [UIColor clearColor];
  }
  return self;
}

- (void)drawRect:(CGRect)rect {
  [[UIColor redColor] setFill];
  UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:10];
  [path fill];

  CGContextRef context = UIGraphicsGetCurrentContext();
  CGContextSaveGState(context); {
    CGContextSetBlendMode(context, kCGBlendModeDestinationOut);
    [@"Hello!" drawAtPoint:CGPointZero withFont:[UIFont systemFontOfSize:24]];
  } CGContextRestoreGState(context);
}

@end

TestViewこれをView Controllerに追加すると、描画された場所の背後にあるビューが表示さHello!れます。

なぜこれが機能するのですか:

ブレンド モードは として定義されています。これは、先ほど提案したレイヤーとはR = D*(1 - Sa)反対のアルファ値が必要であることを意味します。maskしたがって、不透明な色で描画するだけで、事前にビューに描画したものから差し引かれます。

于 2013-07-23T18:15:16.723 に答える
1

驚くべきことに、実際に自分でそれを行う方法を見つけましたが、@StatusReportの答えは完全に有効であり、現在の状態で機能します。

これが私がそれをした方法です:

-(void)drawRect:(CGRect)rect{
    CGContextRef context = UIGraphicsGetCurrentContext();
    [[UIColor darkGrayColor]setFill]; //this becomes the color of the alpha mask
    CGContextFillRect(context, rect);
    CGContextSaveState(context);
    [[UIColor whiteColor]setFill];
    //Have to flip the context since core graphics is done in cartesian coordinates
    CGContextTranslateCTM(context, 0, rect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    [textToDraw drawInRect:rect withFont:[UIFont fontWithName:@"HelveticaNeue-Thin" size:40];
    CGContextRestoreGState(context);
    CGImageRef alphaMask = CGBitmapContextCreateImage(context);
    [[UIColor whiteColor]setFill];
    CGContextFillRect(context, rect);
    CGContextSaveGState(context);
    CGContentClipToMask(context, rect, alphaMask);
    [backgroundImage drawInRect:rect];
    CGContextRestoreGState(context);
    CGImageRelease(alphaMask);
}

- (void)setTextToDraw:(NSString*)text{
    if(text != textToDraw){
        textToDraw = text;
        [self setNeedsDisplay];
    }
}

@synthesize宣言がtextToDrawあるので、セッターをオーバーライドして を呼び出すことができます[self setNeedsDisplay]。それが完全に必要かどうかはわかりません。

これにはいくつかのタイプミスがあると確信していますが、スペルチェックされたバージョンは問題なく動作することを保証できます。

于 2013-07-24T14:30:40.917 に答える
1

StatusReport の受け入れられた回答は美しく書かれており、この質問に対する Swift の回答をまだ見つけていないため、Swift バージョンのテンプレートとして彼の回答を使用すると考えました。ビューのパラメーターとして文字列を入力できるようにすることで、ビューに少し拡張性を追加して、ビューのすべてのプロパティ (角の半径、色など) を使用してビューを完全に作成できることを人々に思い出させました。拡張可能。

制約を適用する可能性が最も高いため、フレームは初期化子でゼロに設定されます。制約を使用していない場合は、これを省略してください。

スイフト5

class CustomView: UIView {
    var title: String
    
    init(title: String) {
        self.title = title
        super.init(frame: CGRect.zero)
        config()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    private func config() {
        backgroundColor = UIColor.clear
    }
    
    override func draw(_ rect: CGRect) { // do not call super
        UIColor.red.setFill()
        let path = UIBezierPath(roundedRect: bounds, cornerRadius: 10)
        path.fill()
        weak var context = UIGraphicsGetCurrentContext() // Apple wants this to be weak
        context?.saveGState()
        context?.setBlendMode(CGBlendMode.destinationOut)
        title.draw(at: CGPoint.zero, withAttributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 24)])
        context?.restoreGState()
    }
}

let customView = CustomView(title: "great success")
于 2018-11-01T19:43:08.127 に答える