Я работаю над приложением, которое требует отображения арабского текста, используя собственный арабский шрифт. Проблема в том, что мне не повезло в отображении арабского текста с использованием пользовательских арабских шрифтов. Я попытался отобразить текст в UILabel, UITextField, UITextView, UIWebView, FontLabel (по Zynga) и используя CoreText.
Здесь вы можете найти примеры проектов:
Пример приложения с использованием UILabel, UITextField, UITextView и CoreText
Пример приложения с использованием UIWebView (HTML)
Пример приложения с использованием UIWebView (HTML): вам нужно будет установить шрифты в примерном проекте. Затем вы можете сравнить результаты и увидеть проблему, запустив приложение в симуляторе (или iPad) и откройте файл Sample.html в браузере (Safari).
Я опубликовал некоторые подробности на форуме разработчиков Apple, но я всегда обнаружил, что stackoverflow будет намного активнее, чем официальный форум разработчиков Apple. Вот ссылка на этот пост:
Использование пользовательского арабского шрифта в iOS
What am i doing wrong?
Примечание. Шрифты загружаются в систему правильно, и я могу успешно применять пользовательские шрифты к регулярному (английскому) тексту.
ps Есть несколько сообщений о stackoverflow, которые говорят об этом предмете, но ни одна из них не помогла, поэтому я отправляю новый вопрос.
Обновить:
Начиная с iOS 7, вам не нужно использовать Core Text для создания пользовательского арабского шрифта. Вы можете использовать UILabel
и / или UITextView
с NSAttributedString
. Результаты те же, что и вы, используя Core-Text. Однако, в зависимости от ваших требований, использование Core Text по-прежнему может быть лучшим вариантом.
Обновить:
Я сообщил об этом как об ошибке для Apple, но я не уверен, когда они добавят поддержку арабских шрифтов. В настоящее время нет простого способа сделать это. Я закончил использовать системный шрифт по умолчанию, что не очень хорошо.
Исходное сообщение
Мне удалось создать приложение Quran, которое использует пользовательский арабский шрифт. Я использовал известные арабские шрифты с базой Core Text
для получения желаемых результатов. Вы можете увидеть результаты, которые я получил в конце, проверив приложение Quran Presenter для iPad , которое доступно в App Store.
Вот пример кода, который поможет вам:
- (CTFontRef)newCustomFontWithName:(NSString *)aFontName ofType:(NSString *)type attributes:(NSDictionary *)attributes { NSString *fontPath = [[NSBundle mainBundle] pathForResource:aFontName ofType:type]; NSData *data = [[NSData alloc] initWithContentsOfFile:fontPath]; CGDataProviderRef fontProvider = CGDataProviderCreateWithCFData((CFDataRef)data); [data release]; CGFontRef cgFont = CGFontCreateWithDataProvider(fontProvider); CGDataProviderRelease(fontProvider); CTFontDescriptorRef fontDescriptor = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)attributes); CTFontRef font = CTFontCreateWithGraphicsFont(cgFont, 0, NULL, fontDescriptor); CFRelease(fontDescriptor); CGFontRelease(cgFont); return font; } - (CATextLayer *)customCATextLayer { NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithFloat:24.f], (NSString *)kCTFontSizeAttribute, [NSNumber numberWithInt:1], (NSString *)kCTLigatureAttributeName, nil]; CTFontRef font = [self newCustomFontWithName:@"PDMS_Saleem_QuranFont-signed" ofType:@"ttf" attributes:attributes]; CATextLayer *normalTextLayer = [[CATextLayer alloc] init]; normalTextLayer.font = font; normalTextLayer.string = NSLocalizedString(@"Sample", nil); normalTextLayer.wrapped = YES; normalTextLayer.foregroundColor = [[UIColor blackColor] CGColor]; normalTextLayer.fontSize = 24.f; normalTextLayer.alignmentMode = kCAAlignmentCenter; normalTextLayer.frame = CGRectMake(0.f, 10.f, 320.f, 32.f); CFRelease(font); return [normalTextLayer autorelease]; } - (void)viewDidLoad { [super viewDidLoad]; CATextLayer *normalTextLayer = [self customCATextLayer]; [self.customView.layer addSublayer:normalTextLayer]; }
Обратите внимание, что я использую CATextLayer
и CTFontRef
. С этим подходом существует несколько проблем. 1. Вам придется жить с проблемами в выбранном «обычном арабском шрифте». 2. Вам придется использовать арабский текст, который использует расширенные символы, поддерживаемые шрифтом.
НТН.
Эти classы будут выполнять эту работу:
https://github.com/Accorpa/Arabic-Converter-From-and-To-Arabic-Presentation-Forms-B
Скачайте их, и я уверен, что ответит на ваш вопрос, потому что раньше у меня была такая же проблема!
Пример кода:
ArabicConverter *converter = [[ArabicConverter alloc] init]; NSString* convertedString = [converter convertArabic:@"منذ دقيقة"]; infoText.font = [UIFont fontWithName:@"YOUARABICFONT" size:16]; infoText.text = convertedString;
Теперь infoText отобразит шрифт правильно 🙂
Я начал изучать развитие iOS еще в середине 2012 года, и я искал всюду в Интернете, чтобы найти правильное решение для пользовательских персидских шрифтов в iPhone и никогда не мог найти подходящего решения. Была Core Text
библиотека Core Text
я пробовал один раз, и она не всегда срабатывала, особенно для того, чтобы добавить дополнительный subview
чтобы добавить текст в свой собственный шрифт. Я попробовал Arabic Converter
на Arabic Converter
некоторое время назад, и это сработало хорошо, но с новым Xcode он вообще не вносил изменений в текст, кроме как в веб-представлениях, и это только сработало!
Итак … В любом случае, я рад, что Apple разрабатывает проблемы для поддержки большего количества языков. Теперь вот очень простое решение, которое отлично работает:
info.plist
вашего проекта, Add row
, Fonts provided by application
в новой строке, UITextView *persianText; persianText.text = @"در جستجوی قهرمان نباشید \nبلکه خود قهرمان شوید"; persianText.font = [UIFont fontWithName:@"IranNastaliq" size: 12.0];
Annnd …! Постройте и запустите … Tadaaa! Оно работает!
Если вы ориентируетесь на iOS 6, вы можете использовать NSAttributedString
чтобы добиться этого намного проще:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:info.text attributes:@{ NSFontAttributeName : [UIFont fontWithName:@"Scheherazade" size:32], NSLigatureAttributeName: @2}]; cell.textLabel.attributedText = attributedString;
Обратитесь к моему ответу здесь, чтобы обсудить некоторые другие вопросы, обычно относящиеся к арабским шрифтам, таким как межстрочный интервал и лигатуры.
Для UIWebview: в основном принятый ответ не относится к делу UIWebView
. Итак, вот как я решил эту проблему.
first: Используя hpple , HTML-парсер obj-c, я прошел через html и в основном отменил текст и NSMutableString
его в NSMutableString
следующим образом:
// contentText is the HTML text. The format is just text in tags NSData *contentData = [contentText dataUsingEncoding:NSUTF8StringEncoding]; TFHpple *htmlParser = [TFHpple hppleWithHTMLData:contentData]; NSString *htmlXpathQueryString = @"//p"; NSArray *newsNodes = [htmlParser searchWithXPathQuery:htmlXpathQueryString]; NSMutableArray *newsParagraphs = [@[] mutableCopy]; NSMutableString *newsContent = [@"" mutableCopy]; for (TFHppleElement *element in newsNodes) { NSString *paragraphText = [[element firstChild] content]; [newsParagraphs addObject:paragraphText]; [newsContent appendFormat:@"%@\n",paragraphText]; } // explained below (bodyView is a CTContainerView object) self.bodyView.contentStr = newsContent; self.bodyView.callback = ^(CGSize size) { [self adjustScrollViewSize:size]; }; [self.bodyView buildFrames]; - (void)adjustScrollViewSize:(CGSize)contentSize { CGRect overallSize = CGRectUnion(imageView.frame, titleText.frame); CGRect bodyViewFr = self.bodyView.frame; CGRect bodyViewWrapperFr = CGRectMake(bodyViewFr.origin.x, bodyViewFr.origin.y, contentSize.width, contentSize.height+30); overallSize = CGRectUnion(overallSize, bodyViewWrapperFr); self.scrollView.contentSize = overallSize.size; }
Затем я использовал Core Text, чтобы отобразить текст в веб-виде, следуя инструкциям в этом уроке. Вот и другие файлы:
CTContainerView.h
#import typedef void (^CompletionBlock)(CGSize size); @interface CTContainerView : UIView @property (nonatomic, strong) NSString *contentStr; @property (nonatomic, strong) CompletionBlock callback; - (void)buildFrames; @end
CTContainerView.m
#import #import "CTContainerView.h" #import "CTView.h" const float kMargin = 10; @implementation CTContainerView { NSAttributedString* attString; } // get the required size for the final view to render // the complete text of the body.. then pass it on // to CTContentView - (void)buildFrames { // first build the attributedString with all its properties NSString *fontName = @"29LTBukra"; // THE ARABIC FONT NAME!!!! CTFontRef fontRef = CTFontCreateWithName((CFStringRef)fontName, 12.0f, NULL); NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init]; [paragraphStyle setLineSpacing:6]; NSDictionary *attrs = [NSDictionary dictionaryWithObjectsAndKeys:(__bridge id)fontRef, kCTFontAttributeName, paragraphStyle, NSParagraphStyleAttributeName, nil]; attString = [[NSAttributedString alloc] initWithString:self.contentStr attributes:attrs]; // get the required final view size given attString CGRect selfFr = self.frame; CGRect textFr = CGRectInset(selfFr, kMargin, kMargin); CGSize requiredSize = [self getRequiredViewSizeInViewWithSize:textFr.size]; requiredSize.height = requiredSize.height + 100; CGRect requiredFrame = CGRectMake(self.bounds.origin.x, self.bounds.origin.y, requiredSize.width, requiredSize.height); // construct a CTFrameRef based on the 1. attStr and 2. calculated fr above CGMutablePathRef path = CGPathCreateMutable(); //1 CGPathAddRect(path, NULL, requiredFrame); CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attString); //3 CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attString length]), path, NULL); // adjust size of container selfFr.size = requiredSize; self.frame = selfFr; // create an empty CTContentView CTView *ctView = [[CTView alloc] initWithFrame: CGRectMake(5, 0, requiredSize.width, requiredSize.height)]; [ctView setBackgroundColor:[UIColor whiteColor]]; [ctView setCtFrame:(__bridge id)(frame)]; [self addSubview:ctView]; CFRelease(path); // call callback self.callback(requiredSize); } - (CGSize)getRequiredViewSizeInViewWithSize:(CGSize)viewSize { CGRect paragraphRect = [attString boundingRectWithSize:CGSizeMake(viewSize.width, CGFLOAT_MAX) options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading) context:nil]; return paragraphRect.size; }
CTContentView.h
#import @interface CTView : UIView @property (nonatomic, strong) id ctFrame; @end
CTContentView.m
#import #import "CTView.h" @implementation CTView @synthesize ctFrame; -(void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); // Flip the coordinate system CGContextSetTextMatrix(context, CGAffineTransformIdentity); CGContextTranslateCTM(context, 0, self.bounds.size.height); CGContextScaleCTM(context, 1.0, -1.0); CTFrameDraw((CTFrameRef)ctFrame, context); } @end