15

Tôi đã lùng sục Internet trong một thời gian để biết thông tin về cách người ta có thể thay đổi khoảng cách chữ/kerning của một phông chữ trong UIKit.Có thể thay đổi khoảng cách chữ/kerning của một phông chữ với Cocoa Touch không?

Nỗi sợ của tôi là, giống như sử dụng phông chữ tùy chỉnh của riêng bạn, bạn chỉ đơn giản là không thể. Đó sẽ là tin tức khủng khiếp.

Tôi biết Apple đang bảo vệ chúng tôi khỏi thiết kế kém với những ràng buộc này, nhưng chúng cũng ngăn cản chúng tôi triển khai thiết kế thực sự tuyệt vời.

Mọi người khuyên tôi nên làm gì?

  1. Sử dụng phông chữ có độ chuẩn chuẩn, mọi người có thể sẽ không nhận thấy sự khác biệt.

  2. Tìm lớp bị tấn công của ai đó để có giao diện người dùng xứng đáng sau khi chia tay với tiền mặt khó kiếm được của họ.

  3. Sử dụng phương pháp mà tôi đã bỏ qua bằng cách nào đó và làm điều đó với UIKit, cam kết lòng biết ơn vĩnh cửu của tôi với người truyền đạt kiến ​​thức ẩn giấu này.

+0

Thực tế có rất nhiều phương pháp để tải phông chữ trên iPhone (mặc dù không có phương pháp API công khai nào thực sự hiển thị UIFont): http://stackoverflow.com/questions/360751/can-i-embed-a -ustom-font-in-an-iphone-application – rpetrich

+0

Tôi ước Apple sẽ theo kịp với CSS. –

Trả lời

3

Bạn có thể thực hiện những gì bạn cần bằng cách sử dụng Quartz 2D. Cụ thể, thuộc tính CGContextSetCharacterSpacing có thể kiểm soát khoảng cách giữa các chữ cái. Tôi không chắc chắn về kerning mặc dù.

Quartz 2D Programming Guide: Text

3

Tôi đã mở rộng UILabel để thay đổi khoảng cách ký tự. Điều này sẽ làm việc ra khỏi hộp và kéo phông chữ, văn bản, màu sắc vv từ chính UILabel (mã hóa thích hợp!).

Bạn có thể thấy tôi vẽ văn bản hai lần, trước tiên với màu sắc rõ ràng. Điều này là để tự động căn giữa văn bản trong nhãn. Trong khi điều này có thể không hiệu quả - không phải là nó tốt đẹp để được tự động làm trung tâm?

Tận hưởng!

@interface RALabel : UILabel { 
} 
@end 

@implementation RALabel 

- (void) drawRect:(CGRect)rect 
{ 

    // Drawing code 

    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSelectFont (context, [self.font.fontName cStringUsingEncoding:NSASCIIStringEncoding], self.font.pointSize, kCGEncodingMacRoman); 
    CGContextSetCharacterSpacing(context, 1); 
    CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]); 
    CGAffineTransform myTextTransform = CGAffineTransformScale(CGAffineTransformIdentity, 1.f, -1.f); 
    CGContextSetTextMatrix (context, myTextTransform); 

    // draw 1 but invisbly to get the string length. 
    CGPoint p =CGContextGetTextPosition(context); 
    float centeredY = (self.font.pointSize + (self.frame.size.height- self.font.pointSize)/2)-2; 
    CGContextShowTextAtPoint(context, 0, centeredY, [self.text cStringUsingEncoding:NSASCIIStringEncoding], [self.text length]); 
    CGPoint v =CGContextGetTextPosition(context); 

    // calculate width and draw second one. 
    float width = v.x - p.x; 
    float centeredX =(self.frame.size.width- width)/2; 
    CGContextSetFillColorWithColor(context, [self.textColor CGColor]); 
    CGContextShowTextAtPoint(context, centeredX, centeredY, [self.text cStringUsingEncoding:NSASCIIStringEncoding], [self.text length]); 

} 
4

Tôi đã đến đây từ Google cố gắng làm tương tự với UITextField. Tôi đã thực hiện một cái gì đó mà sẽ làm việc chung cho UILabel dưới đây.

@interface AdjustableUILable : UILabel { 
    CGFloat characterSpacing; 
} 

@property CGFloat characterSpacing; 

@end 


@implementation AdjustableUILable 

@synthesize characterSpacing; 

- (void)drawTextInRect:(CGRect)rect 
{  
    if (characterSpacing) 
    { 
     // Drawing code 
     CGContextRef context = UIGraphicsGetCurrentContext(); 
     CGFloat size = self.font.pointSize; 

     CGContextSelectFont (context, [self.font.fontName UTF8String], size, kCGEncodingMacRoman); 
     CGContextSetCharacterSpacing (context, characterSpacing); 
     CGContextSetTextDrawingMode (context, kCGTextFill); 

     // Rotate text to not be upside down 
     CGAffineTransform xform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0); 
     CGContextSetTextMatrix(context, xform); 
     const char *cStr = [self.text UTF8String]; 
     CGContextShowTextAtPoint (context, rect.origin.x, rect.origin.y + size, cStr, strlen(cStr)); 
    } 
    else 
    { 
     // no character spacing provided so do normal drawing 
     [super drawTextInRect:rect]; 
    } 
} 

@end 

Sau đó, để sử dụng nó, chỉ cần thiết lập các nhãn trong viewDidLoad hoặc một cái gì đó

- (void)viewDidLoad 
{ 
     myLabel.characterSpacing = 2; // point size 
} 

Tôi đã thử nó với UITextField, nhưng tiếc là nó chỉ hỗ trợ thêm khoảng cách nhân vật sau khi người dùng đã thay đổi nội dung lĩnh vực này. -drawTextInRect chỉ được gọi sau phương thức ủy nhiệm -textFieldShouldEndEditing. Từ các diễn đàn khác, một số người cho rằng điều này là do UITextField cần phải biết kết xuất phông chữ để hiển thị con trỏ. Không bao giờ tìm thấy giải pháp cho đoạn đó ...

4

Câu trả lời được chấp nhận mất rất nhiều định dạng và câu trả lời của người dùng363349 chủ yếu làm việc cho tôi nhưng căn chỉnh văn bản không hoạt động. Tôi đã sửa đổi mã để sửa lỗi đó:

- (void) drawRect:(CGRect)rect 
{ 
    // Drawing code 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSelectFont (context, [self.font.fontName cStringUsingEncoding:NSASCIIStringEncoding], self.font.pointSize, kCGEncodingMacRoman); 
    CGContextSetCharacterSpacing(context, characterSpacing); 
    CGContextSetFillColorWithColor(context, [[UIColor clearColor] CGColor]); 
    CGAffineTransform myTextTransform = CGAffineTransformScale(CGAffineTransformIdentity, 1.f, -1.f); 

    CGContextSetTextMatrix (context, myTextTransform); 

    // draw 1 but invisbly to get the string length. 
    CGPoint p =CGContextGetTextPosition(context); 
    float centeredY = (self.font.pointSize + (self.frame.size.height- self.font.pointSize)/2)-2; 
    CGContextShowTextAtPoint(context, 0, centeredY, [self.text cStringUsingEncoding:NSASCIIStringEncoding], [self.text length]); 
    CGPoint v =CGContextGetTextPosition(context); 

    // calculate width and draw second one. 
    float width = v.x - p.x; 
    float destX = 0; 

    // calculate X position based on alignment 
    if([self textAlignment] == UITextAlignmentLeft){ 
     destX = 0; 
    }else if([self textAlignment] == UITextAlignmentCenter){ 
     destX = (self.frame.size.width- width)/2; 
    }else if([self textAlignment] == UITextAlignmentRight){ 
     destX = self.frame.size.width - width; 
    } 
    CGContextSetFillColorWithColor(context, [self.textColor CGColor]); 
    CGContextShowTextAtPoint(context, destX, centeredY, [self.text cStringUsingEncoding:NSASCIIStringEncoding], [self.text length]); 
} 
+0

Đẹp, giữ cho căn chỉnh là một bổ sung tuyệt vời! –

1

Vấn đề chính của các phương thức CGContextShowText - chúng chỉ là các chuỗi ASCII. Để hiển thị chuỗi UTF, bạn cần ánh xạ các ký hiệu chuỗi của bạn với các hình tượng và hiển thị các hình tượng.

CGContextRef context = UIGraphicsGetCurrentContext(); 
    CGContextSelectFont (context, [self.font.fontName cStringUsingEncoding:NSASCIIStringEncoding], self.font.pointSize, kCGEncodingMacRoman); 
    CGContextSetCharacterSpacing(context, characterSpacing); 
    CGContextSetFillColorWithColor(context, [self.textColor CGColor]); 
    CGAffineTransform myTextTransform = CGAffineTransformScale(CGAffineTransformIdentity, 1.f, -1.f); 
    CGContextSetTextMatrix (context, myTextTransform); 

    CGGlyph glyphs[self.text.length]; 
    CTFontRef fontRef = CTFontCreateWithName((CFStringRef)self.font.fontName, self.font.pointSize, NULL); 
    CTFontGetGlyphsForCharacters(fontRef, (const unichar*)[self.text cStringUsingEncoding:NSUnicodeStringEncoding], glyphs, self.text.length); 
    float centeredY = (self.font.pointSize + (self.frame.size.height- self.font.pointSize)/2)-2; 
    CGContextShowGlyphsAtPoint(context, rect.origin.x, centeredY, (const CGGlyph *)glyphs, self.text.length); 
Các vấn đề liên quan