切換APP字號(hào)

修改字體.jpg

  一個(gè)APP開(kāi)發(fā)都尾聲時(shí)候,老板一句說(shuō)這字體好小,做一個(gè)切換字體的功能吧!例如QQ微信那樣的。我當(dāng)時(shí)就想這應(yīng)該是用個(gè)全局宏定義,就可以吧!最后發(fā)現(xiàn),我的工程項(xiàng)目是用storyboard來(lái)創(chuàng)建的,所以沒(méi)有例如手寫代碼有一個(gè)宏定義的字體定義。全工程都由Xib創(chuàng)建,IB上修改和設(shè)置字體。瞬間懵逼了。

不過(guò)如果使用宏定義,我猜想也是不可以的,因?yàn)槟阈薷牧撕?,?yè)面的字體也不會(huì)因?yàn)楹甑母淖兌プ兓?。修改了宏并不?huì)去觸發(fā)頁(yè)面刷新,需要用全局定義宏,可能需要一個(gè)觸發(fā)頁(yè)面刷新的方法。也就需要用到通知或者別的。

runTime控制字體

我在網(wǎng)上百度了許久,也去翻墻使用google來(lái)搜索一些外文網(wǎng)頁(yè)。只有看到一些類似的,主題更換資料。有一個(gè)博主有寫了一個(gè)方法,使用runTime(運(yùn)行時(shí))來(lái)控制APP程序中的字體變化。寫一個(gè)UILabel的分類,在分類用使用+ (void)load { }使用class_getInstanceMethod(Class cls, SEL name)方法獲取自定義方法和系統(tǒng)方法,在使用method_exchangeImplementations(Method m1, Method m2)方法替換系統(tǒng)的方法。
以下是這方法的代碼:

+ (void)load {
    Method imp = class_getInstanceMethod([self class], @selector(initWithCoder:));
    Method myImp = class_getInstanceMethod([self class], @selector(myInitWithCoder:));
    method_exchangeImplementations(imp, myImp);
}

- (id)myInitWithCoder:(NSCoder*)aDecode {
    [self myInitWithCoder:aDecode];
    if (self) {
        //使用UD獲取本地保存的字體大小
        NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
        NSNumber *num = [userDefault objectForKey:@"Font"];
        CGFloat fontSize = self.font.pointSize;
        self.font = [UIFont systemFontOfSize:fontSize + [num floatValue]];
    }
    return self;
}

只要寫好這個(gè)分類,只需要丟入工程內(nèi)就可以直接實(shí)現(xiàn)APP的字體變化,方便快捷。不過(guò)這方法有個(gè)弊端,就是修改字體后,需要重新啟動(dòng)APP,才能實(shí)現(xiàn)。本人對(duì)于APP的內(nèi)存管理知識(shí)不是很全面,大概理解是當(dāng)APP頁(yè)面將要出現(xiàn)的時(shí)候都會(huì)運(yùn)行+ (void)load { }方法,不過(guò)當(dāng)頁(yè)面已經(jīng)出現(xiàn)內(nèi)存已經(jīng)存在時(shí)候就不會(huì)運(yùn)行+ (void)load { }方法(也可以自己去百度下這方法)如果有大神懂這里面的原由,可以方便告知我下。

控制器基類-遍歷

之后我使用基類UIViewController 讓每個(gè)基于控制器頁(yè)面都繼承于這個(gè)類,就是所謂的基類。然后再這基類中接收一個(gè)通知KVO,觸發(fā)方法來(lái)循環(huán)遍歷頁(yè)面中所有view.subviews判斷是否為UIButton和UILabel。以下為代碼:

@interface BaseViewController ()

@end

@implementation BaseViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tongzhi:) name:@"tongzhi" object:nil];
}

- (void)tongzhi:(NSNotification *)text{
    NSLog(@"%@",text.userInfo[@"font"]);
    NSLog(@"-----接收到通知------");
    NSNumber *num = text.userInfo[@"font"];
    [self setFont:[num floatValue] forView:self.view];
}

- (void)setFont:(CGFloat)fontSize forView:(UIView*)view{
    if ([view isKindOfClass:[UILabel class]]) {
        UILabel *lbl = (UILabel *)view;
        CGFloat font = lbl.font.pointSize;
        lbl.font = [UIFont systemFontOfSize:font + fontSize];
    }
    if ([view isKindOfClass:[UIButton class]]) {
        UIButton *btn = (UIButton *)view;
        CGFloat font = btn.titleLabel.font.pointSize;
        btn.titleLabel.font = [UIFont systemFontOfSize:font + fontSize];
    }
    
    for (UIView *sview in view.subviews) {
        [self setFont:fontSize forView:sview];
    }
}

- (void)dealloc {
   [[NSNotificationCenter defaultCenter] removeObserver:self name:@"tongzhi" object:nil];
}

此方法可以實(shí)現(xiàn)字體的改變,不過(guò)略微復(fù)雜,因?yàn)槭敲總€(gè)子類都循環(huán)遍歷,可能會(huì)有系統(tǒng)運(yùn)行速度過(guò)慢等問(wèn)題。還有因?yàn)槲业氖枪こ倘渴褂?storyboard 來(lái)搭建的頁(yè)面,其中我也使用了UITableViewController,雖然UITableViewController也是繼承于UIViewController,就可能需要使用多繼承,Objective-C又不支持多繼承,需要用協(xié)議來(lái)實(shí)現(xiàn),感覺(jué)有些麻煩,也許是因?yàn)楸救酥R(shí)不夠。所以沒(méi)有繼續(xù)下去

設(shè)計(jì)思路:控件基類-通知-基類獲取通知

第三種,也是我現(xiàn)在使用的一種。這種方法就比前面說(shuō)的簡(jiǎn)單,并且不會(huì)出現(xiàn)問(wèn)題。這是求教了我以前的老大,也根據(jù)網(wǎng)上一些類似的功能,主題切換,來(lái)實(shí)現(xiàn)的。
首先,我創(chuàng)建一個(gè)繼承于UILabel的基類,在這基類中添加通知KVO,監(jiān)聽(tīng)字體。
核心代碼:

@interface BaseLabel ()

@property (assign, nonatomic) CGFloat fontSize;

@end

@implementation BaseLabel

- (id)init {
    self = [super init];
    if (self != nil) {
        NSLog(@"我出現(xiàn)了 init ");
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self != nil) {
        NSLog(@"我出現(xiàn)了 initWithCoder");
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    NSNumber *num = [userDefault objectForKey:@"Font"];
    CGFloat font = self.font.pointSize;
    self.font = [UIFont systemFontOfSize:font + [num floatValue]];
     
    self.fontSize = font; 
    [[NSNotificationCenter defaultCenter]  addObserver:self selector:@selector(fontNotification:) name:@"tongzhi" object:nil]; 
    NSLog(@"我出現(xiàn)了 awakeFromNib   %f",self.fontSize);
}

#pragma mark - NSNotification Actions
- (void)fontNotification:(NSNotification *)notification {
    NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
    NSNumber *num = [userDefault objectForKey:@"Font"]; 
    self.font = [UIFont systemFontOfSize:self.fontSize + [num floatValue]];
}

#pragma mark - Memery Manager
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"tongzhi" object:nil];
}

只需要將工程中的UILabel基于此類就可以,直接實(shí)現(xiàn)字體的變化。使用一些空間約束來(lái)調(diào)整因?yàn)樽煮w變化的原因而照成的控件變化問(wèn)題。(例如tableViewCell高度的變化,需要重新計(jì)算??梢灾苯邮褂肔abel的基類中的通知放到控制器上,來(lái)監(jiān)聽(tīng)變化,實(shí)現(xiàn)cell高度的動(dòng)態(tài)變化)

UIButton也可以使用此方法來(lái)控制字體的變化。

最后注意一點(diǎn),我們修改APP字體的時(shí)候,我們需要保存在標(biāo)準(zhǔn)字號(hào)和修改后字體之間的差值,我設(shè)置了一個(gè)標(biāo)準(zhǔn)字號(hào)14,因?yàn)锳PP中有這不同的Label字體。

這是工程在GitHub上的地址:changeLabelFont

大神請(qǐng)輕虐0_0!!!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,316評(píng)論 25 708
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,610評(píng)論 4 61
  • 每天都很嘈雜, 不是不可開(kāi)交,就是渾渾噩噩。抽空拿出筆來(lái),較喜歡的建筑畫在紙上,算是將一天的心情收分在此。今天再見(jiàn)...
    濱海泛舟2013閱讀 255評(píng)論 0 3
  • 每個(gè)人心中都有屬于自己的王瀝川,看完《瀝川往事》,心中只有一個(gè)念頭就是遇見(jiàn)王瀝川,再見(jiàn)王瀝川,吻別王瀝川,就像...
    蘇夏suxia閱讀 368評(píng)論 0 0
  • 老師,作業(yè)我把對(duì)對(duì)子重新修改了下! 為奴十二載,侍君三二事。 這個(gè)殺手不太冷,一壺濁酒已深暖。 彗星來(lái)的那一夜,臘...
    潛水的魚兒閱讀 280評(píng)論 2 0

友情鏈接更多精彩內(nèi)容