2015-01-05 24 views
9

iOS 8.1.X'deki UITextField UITextField, Helvetica Neue Light 17:iOS'taki UITextField 8.1, bazı fontları kullanırken düzenleme ve düzenleme modları arasında farklı dikey metin hizalamasına sahiptir.

gibi bazı fontları kullanırken düzenleme ve düzenleme modu arasında farklı dikey metin hizalamasına sahiptir

UITextField bug example

Ben örnek bir proje here var.

Özel bir metin alanı oluşturmama gerek duyduğum bir geçici çözüm var mı? Temel sorun, Dynamic Type kullanıldığında yazı tipinin çalışma zamanında değişebilmesidir.

Her neyse rdar://19374610 numaralı radarı açtım.

+0

Bu sorunla karşılaştığımı hatırlıyorum ve sanırım bazı durumlarda göz ardı edilen ve başkalarında yok sayılan dikey konumla ilgili yazı tipleriyle ilgili belirli bir özellik ile ilgili. Bu durumda düzenleme sırasında farklı bir davranışı vardır. Ne zaman hızlı bir kesmek olarak yaptım, düzenleme başladığında UITextField 1 veya 2 piksel aşağı konumlandırmak ve düzenleme bittiğinde yere geri oldu. – manecosta

+0

Bu yaklaşımla ilgili sorun, UITextField üzerinde herhangi bir kenarlığı veya arka planı kullanamayacağınızdır; bu, her şeyi yeniden konumlandırdığınızı açıkça belli edecek, yani kullandığınız yerel yuvarlak kenarlık gibi görünüyor. – manecosta

+0

Bu adam aynı sorunla karşı karşıyaydı ve o zamanki gibi aynı sonuca vardı. http://stackoverflow.com/questions/9674566/text-in-uitextfield-moves-up-after-editing-center-while-editing – manecosta

cevap

-1

Bu hata yazı tipine bağımlıdır, dolayısıyla bunu telafi etmek için atıf yapılan dizginin stilini ayarlayan bir çözümle gideceğim.

Helvetica Neue Işık ve büyüklüğü 17 ile ilk metin alanına bu sorunu gidermek için bir örnek:

görünüm denetleyicisi varsayalım ayarladığınız zaman önemli öğelerinden biri olan firstTextField

- (void)viewDidLoad { 
[super viewDidLoad]; 
// Do any additional setup after loading the view, typically from a nib. 
NSDictionary *style = @{ 
     NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Light" 
               size:17], 
     NSParagraphStyleAttributeName : [NSParagraphStyle defaultParagraphStyle], 
     NSBaselineOffsetAttributeName: @(0.4) 
}; 
_firstTextField.attributedText = [[NSAttributedString alloc] initWithString:_firstTextField.text 
                   attributes:style]; 

} 
-(void)textFieldDidBeginEditing:(UITextField *)textField { 
NSDictionary *style = @{ 
     NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Light" 
               size:17], 
     NSParagraphStyleAttributeName : [NSParagraphStyle defaultParagraphStyle], 
     NSBaselineOffsetAttributeName: @(0.0) 

}; 
[_firstTextField setTypingAttributes: style]; 
} 

delegesi olan textField öğesini düzenlerken düzenlediğiniz zamanki NSBaselineAlignment. Ayrıca yazı çift boyutu (bir textField yeterince büyük) olduğunda ve NSBaselineOffset atlama etkisi önlemek için hala aynı olduğunda ne olduğunu kontrol ettim.

+0

Bu hatanın yazı tipi bağımlı olduğunu görüyorum, sorun şu ki Dinamik Yazı kullandığım için yazı tipi çalışma zamanında değişebilir. Dolayısıyla bu çözüm, belirli vakalara yönelik çalışmalara rağmen, soruyu cevaplamıyor. Bunu daha açık hale getirmek için soruyu yeniden yazacağım. –

3

Sadece aynı sorun karşısında tökezledi ve biraz 'hata ayıklama' yapmaya karar verdi. Temel olarak çeşitli fontlar için değerler çizdim (kapak yüksekliği, nokta boyutu, tercih edilen yükseklik, kullanılabilir yükseklik, metnin taşındığı mesafe) ve bir desen fark ettim.

iki tamamen farklı şekillerde oluşturulur, çünkü metin yukarı hareket nedeni: olmayan düzenleme versiyonu (hatta kanca geçersiz kılabilirsiniz) -drawRect: kullanılarak hale getirilen, düzenleme versiyonu UIFieldEditor sözde tarafından oluşturulur. Bu, Retina cihazında olup olmadığına bakılmaksızın ceil metin yüksekliğine göre görüntülenir ve daha sonra ortalar. Retina cihazlarında, pikselleri hizalamak için her zaman ceil(scalar * scale)/scale'u kullanmalısınız. Bundan dolayı, iOS, gerekenden daha büyük bir metin yüksekliğini varsayar ve onu ortalamak için biraz daha ileriye taşır. Yeterli, statik metin ve UIFieldEditor render farklıdır.

Sorunu düzeltmek için UITextField alt sınıfını ve -editingRectForBounds: numaralı değerleri geçersiz kılın. Burada düzenleme olmayan rect ('metin rect') almak ve Apple'ın ileride gerçekleştireceği vardiyayı hesaba katmak isteyeceksiniz.

- (CGRect)editingRectForBounds:(CGRect)bounds 
{ 
    if (UIDevice.currentDevice.systemVersion.integerValue != 8) return [self textRectForBounds:bounds]; 

    CGFloat const scale = UIScreen.mainScreen.scale; 
    CGFloat const preferred = self.attributedText.size.height; 
    CGFloat const delta = ceil(preferred) - preferred; 
    CGFloat const adjustment = floor(delta * scale)/scale; 

    CGRect const textRect = [self textRectForBounds:bounds]; 
    CGRect const editingRect = CGRectOffset(textRect, 0.0, adjustment); 

    return editingRect; 
} 

Düzenleme: Sadece 8,0 dahil eski işletim sistemi sürümlerinde, kod test etti. IOS 7.x'te her şey iyi görünüyor, iOS 8.0 zaten hatayı içeriyor. Geleceği tahmin edemeyiz, bu yüzden şimdilik iOS 8x için düzeltmeyi de ekleyebilirim, Apple'ın sorunu iOS 9'da kendileri de düzeltmesidir.


Başka Düzenleme: Bu kod düzenleme metin onun statik meslektaşı ile aynı yerde görünmesini sağlar.Bunları ayrı ayrı kontrol etmek istiyorsanız (Apple'ın mantıklı olduğunu düşündüğünüzde, hem -textRectForBounds: hem de -editingRectForBounds: sundukları için) [self textRectForBounds:bounds]'u [super editingRectForBounds:bounds] ile değiştirmek isteyebilirsiniz. Bu düzeltmeyi swizzling kullanarak bir kategoride uygulamak istiyorsanız, super sürümünü kesinlikle kullanmalısınız.

+0

** Düzenleme: **, kenarlıklı metin alanları ve IB ile oluşturulanlar için düzeltme ekledi. –

+0

Bunu ios 8.x problemi olarak onaylayabilirim. IOS 9.0.2'de olmuyor. –

+1

@ Otávio Gerçekten öyle. Bu nedenle, eğer (UIDevice.currentDevice.systemVersion.integerValue! = 8) 'kontrol edin. –