2012-04-23 14 views
16

मैं कैसे NSString drawInRect साथ घुमाया पाठ आकर्षित करने के लिए पर इस जवाब मिल गया के साथ पाठ घुमाया :, लेकिन मुझे यकीन है कि यह कैसे काम करता है, क्योंकि यह केवल एक तरह से मेरे लिए काम करता नहीं हूँ: https://discussions.apple.com/thread/1779814?start=0&tstart=0आहरण NSString drawInRect

मेरे कोड दिखता है जैसे:

  CGContextSaveGState(context); 
      CGContextDrawLinearGradient(context, gradient, CGPointMake(0, centY - halfWidth), CGPointMake(0, centY + halfWidth), 0); 

      // Add text     
      CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor); 
      NSString *str = @"some test string"; 

      CGAffineTransform transform1 = CGAffineTransformMakeRotation(M_PI/4); 

      CGContextConcatCTM(context, transform1); 
      CGContextTranslateCTM(context, 0, 0); 
      UIFont *font = [UIFont systemFontOfSize:16.0]; 

      [str drawInRect:CGRectMake(0, 0, 200, 100) withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UIBaselineAdjustmentNone]; 

तो जब मैं इसका उपयोग करता हूं, तो मुझे एक्स-अक्ष के नीचे 45 डिग्री खींचा जाने वाला टेक्स्ट दिखाई देता है। मैं अपने लाइनग्राइडेंट के साथ लंबवत पाठ को आकर्षित करना चाहता हूं। तो मैंने सोचा कि मैं 90 डिग्री के लिए एमएफआई/2 का उपयोग करके ऐसा कर सकता हूं। हालांकि मुझे अपना पाठ नहीं दिख रहा है। मैंने घूर्णन के लिए अलग-अलग परिवर्तनों की कोशिश की है, और केवल कुछ ही एमएफआई/4 और एमएफआई/8 की तरह काम करते हैं। मुझे लगता है कि अगर मैंने -एम_PI/4 का उपयोग किया है तो इसमें एक्स-अक्ष से 45 डिग्री टेक्स्ट होगा और एमएफआई/2 एक्स-अक्ष के नीचे 90 डिग्री होगा। लेकिन दोनों कुछ भी नहीं बदलते हैं।

कोई विचार? धन्यवाद।

उत्तर

12

मुझे लगता है कि क्या हो रहा है यह है कि आप टेक्स्ट को दृश्य के बाहर किसी स्थान पर घुमा रहे हैं क्योंकि यह संदर्भ को मूल पर पिवोटिंग द्वारा घुमाता है।

आपके घूर्णन के बाद आपको संदर्भ को वापस देखने के लिए एक अनुवाद करने की आवश्यकता है। नीचे दिए गए उदाहरण में, मैं संदर्भ को घुमावदार 90 डिग्री घुमाता हूं। फिर मैं संदर्भ की टीएक्स को ऊंचाई की दूरी का अनुवाद करता हूं।

- (void)drawRect:(CGRect)rect 
{ 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGContextSaveGState(context); 

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    // Create the gradient 
    CGColorRef startColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0].CGColor; 
    CGColorRef endColor = [UIColor colorWithRed:200.0/255.0 green:200.0/255.0 blue:200.0/255.0 alpha:1.0].CGColor; 
    NSArray *colors = [NSArray arrayWithObjects:(id)startColor, (id)endColor, nil]; 
    CGFloat locations[] = { 0.0, 1.0 }; 
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef) colors, locations); 
    CGContextDrawLinearGradient(context, gradient, CGPointMake(rect.origin.x + rect.size.width/2, rect.origin.y), CGPointMake(rect.origin.x + rect.size.width/2, rect.origin.y + rect.size.height), 0); 

    // Create text    
    CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor); 
    NSString *string = @"some test string"; 
    UIFont *font = [UIFont systemFontOfSize:16.0]; 

    // Rotate the context 90 degrees (convert to radians) 
    CGAffineTransform transform1 = CGAffineTransformMakeRotation(-M_PI_2); 
    CGContextConcatCTM(context, transform1); 

    // Move the context back into the view 
    CGContextTranslateCTM(context, -rect.size.height, 0); 

    // Draw the string 
    [string drawInRect:rect withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:UITextAlignmentLeft]; 

    // Clean up 
    CGGradientRelease(gradient); 
    CGColorSpaceRelease(colorSpace); 

    CGContextRestoreGState(context); 
} 

ध्यान दें कि आप भी कैसे स्ट्रिंग रेंडर किया जाएगा के आकार है, जो पाठ के संरेखण के लिए गणना करने में मदद कर सकते हैं मिल सकता है।

CGSize stringSize = [string sizeWithFont:font]; 
+0

बहुत बहुत धन्यवाद। लेकिन अगर मैं -एम_PI_2 को M_PI_2 में बदलता हूं। यह स्ट्रिंग गायब हो जाएगी। क्यूं कर? – Jacky

+1

मुझे यह मिला, अगर बदल गया- M_PI_2 से M_PI_2, तो उसे CGContextTranslateCTM (संदर्भ, -rect.size.height, 0) को बदलने की भी आवश्यकता है; CGContextTranslateCTM (संदर्भ, 0, -rect.size.height) के लिए; – Jacky

15

मैं इस समस्या को अगली तरीके से हल करता हूं।

1), NSString

@interface NSString (NMSchemeItemDraw) 
-(void) drawWithBasePoint:(CGPoint)basePoint 
        andAngle:(CGFloat)angle 
        andFont:(UIFont*)font; 
@end 

इस श्रेणी में दिए गए केंद्रीय बिंदु के साथ पाठ आकर्षित करेगा पर श्रेणी घोषित एक पंक्ति में और दिए गए फ़ॉन्ट और कोण के साथ।

2) इस श्रेणी के कार्यान्वयन की तरह दिखता है:

@implementation NSString (NMSchemeItemDraw) 

    -(void) drawWithBasePoint:(CGPoint)basePoint 
        andAngle:(CGFloat)angle 
         andFont:(UIFont *)font{ 
    CGSize textSize = [self sizeWithFont:font]; 

    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGAffineTransform t = CGAffineTransformMakeTranslation(basePoint.x, basePoint.y); 
    CGAffineTransform r = CGAffineTransformMakeRotation(angle); 


    CGContextConcatCTM(context, t); 
    CGContextConcatCTM(context, r); 

    [self drawAtPoint:CGPointMake(-1 * textSize.width/2, -1 * textSize.height/2) 
       withFont:font]; 

    CGContextConcatCTM(context, CGAffineTransformInvert(r)); 
    CGContextConcatCTM(context, CGAffineTransformInvert(t)); 
    } 
@end 

3) अब मैं अपने [UIView drawRect:] विधि में इसका इस्तेमाल कर सकते हैं। उदाहरण के लिए, एक अगले रास्ते में:

-(void)drawRect:(CGRect)rect{ 
NSString* example = @"Title"; 
[example drawWithBasePoint:CGPointMake(0.0f, 0.0f) 
        andAngle:M_PI 
        andFont:[UIFont boldSystemFontOfSize:16.0]]; 
} 
+0

अच्छा समाधान ... कुछ पैरामीटर में पास करना बहुत आसान है और फ़ंक्शन को अन्य सभी को संभालने दें – jsetting32

+0

बहुत ही सुरुचिपूर्ण! sizeWithFont और drawAtPoint: अभी फ़ॉन्ट को बहिष्कृत नहीं किया गया है। अपने CGSize टेक्स्ट आकार को बदलें ... इस कोड के साथ कोड की रेखा: NSDictionary * विशेषताएँ = @ {NSFontAttributeName: निर्दिष्टFont}; CGSize textSize = [self sizeWithAttributes: विशेषताएँ]; विज्ञापित के रूप में काम करता है। DrawAtPoint विधि कॉल को भी अपडेट करने की आवश्यकता है। 'WithAttributes: विशेषताएँ' के साथ बस 'withFont: font' को प्रतिस्थापित करें। इस स्वच्छ समाधान के लिए फिर से धन्यवाद। – Scooter

+0

बहुत बढ़िया जवाब !!! –

5

स्विफ्ट में KoNew के समाधान:

extension NSString { 

    func drawWithBasePoint(basePoint:CGPoint, angle:CGFloat, font:UIFont) { 

     var attrs: NSDictionary = [ 
      NSFontAttributeName: font 
     ] 

     var textSize:CGSize = self.sizeWithAttributes(attrs as [NSObject : AnyObject]) 

     // sizeWithAttributes is only effective with single line NSString text 
     // use boundingRectWithSize for multi line text 

     var context: CGContextRef = UIGraphicsGetCurrentContext() 

     var t:CGAffineTransform = CGAffineTransformMakeTranslation(basePoint.x, basePoint.y) 
     var r:CGAffineTransform = CGAffineTransformMakeRotation(angle) 


     CGContextConcatCTM(context, t) 
     CGContextConcatCTM(context, r) 


     self.drawAtPoint(CGPointMake(-1 * textSize.width/2, -1 * textSize.height/2), withAttributes: attrs as [NSObject : AnyObject]) 


     CGContextConcatCTM(context, CGAffineTransformInvert(r)) 
     CGContextConcatCTM(context, CGAffineTransformInvert(t)) 


    } 


} 

का उपयोग करें: इस पोस्ट के लिए

let fieldFont = UIFont(name: "Helvetica Neue", size: 14) 

myNSString.drawWithBasePoint(CGPointMake(bounds.width/2, bounds.height/2), angle: CGFloat(-M_PI_2), font: fieldFont!) 
0

धन्यवाद, और Chris's answer, और Arkadiusz's answer at another post

अंत में, मैं UILabel सबक्लास द्वारा MyVerticalLabel नामक इस समस्या को हल करता हूं, और इसे लंबवत पाठ खींचता हूं।

@implementation MyVerticalLabel 

// Only override drawRect: if you perform custom drawing. 
// An empty implementation adversely affects performance during animation. 
- (void)drawRect:(CGRect)rect { 
    // Drawing code 

    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGAffineTransform transform = CGAffineTransformMakeRotation(-M_PI_2); 
    CGContextConcatCTM(context, transform); 
    CGContextTranslateCTM(context, -rect.size.height, 0); 

    // The drawing rect should be applied with transform to. 
    CGRect newRect = CGRectApplyAffineTransform(rect, transform); 
    newRect.origin = CGPointZero; 

    NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy]; 
    textStyle.lineBreakMode = self.lineBreakMode; 
    textStyle.alignment = self.textAlignment; 

    // Apply current label attributes for drawing function. 
    NSDictionary *attributeDict = 
    @{ 
     NSFontAttributeName : self.font, 
     NSForegroundColorAttributeName : self.textColor, 
     NSParagraphStyleAttributeName : textStyle, 
     }; 
    [self.text drawInRect:newRect withAttributes:attributeDict]; 
} 

@end 
5

यहां KoNEW के उत्तर का एक अद्यतन और सरलीकृत संस्करण है। यह एक बोनस के रूप में ग्राफिक्स संदर्भ की स्थिति को बरकरार रखता है। स्ट्रिंग एक्सटेंशन के बजाय यह एक साधारण कार्य भी है।

func drawRotatedText(_ text: String, at p: CGPoint, angle: CGFloat, font: UIFont, color: UIColor) { 
    // Draw text centered on the point, rotated by an angle in degrees moving clockwise. 
    let attrs = [NSFontAttributeName: font, NSForegroundColorAttributeName: color] 
    let textSize = text.size(attributes: attrs) 
    let c = UIGraphicsGetCurrentContext()! 
    c.saveGState() 
    // Translate the origin to the drawing location and rotate the coordinate system. 
    c.translateBy(x: p.x, y: p.y) 
    c.rotate(by: angle * .pi/180) 
    // Draw the text centered at the point. 
    text.draw(at: CGPoint(x: -textSize.width/2, y: -textSize.height/2), withAttributes: attrs) 
    // Restore the original coordinate system. 
    c.restoreGState() 
}