分析微信(iOS 版)定製導航欄按鈕的思路

mnoteapp發表於2018-05-28

微信介面以最簡潔著稱,介面上看不到花哨的設計。 本文分析一下微信是如何定製導航欄的,雖然看起來像原生導航欄,實際上並不是。

image
image

image

image

從檢視結構看到:左右兩邊的按鈕是 MMBarButton(高度固定為 44),中間的標題欄是 MMTitleView(寬1,高44)。 MMBarButton 的 superView 是一個 UIView,很明顯看出微信應該是這樣定製按鈕的(虛擬碼):

MMBarButton *button = [[MMBarButton alloc] init];
UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 44)];
    [contentView addSubview:button];
MMUIBarButtonItem *item = [[MMUIBarButtonItem alloc] initWithCustomView:contentView];
複製程式碼

再分析標題欄,MMTitleView 的寬高固定是 1x44,是一個 titleView,顯示標題文字的是 UILabel。 微信在這裡使用了一個技巧:titleView 寬度比較小的時候,系統會把它放在居中的位置,只用設定 UILabel 的 center 等於 superView ,那麼標題文字就可以居中顯示了。不過,微信的計算似乎有問題,仔細看微信的標題欄,都是向左偏移了 1 個螢幕單位,並不是居中的(事後我分析了微博的標題欄,方法和微信大同小異,但是微博的計算方法才是正確的,標題欄文字做到了完全居中顯示)。 微信的標題欄文字實現如下(虛擬碼):

_titleView = [[MMTitleView alloc] init];
self.navigationItem.titleView = _titleView;
複製程式碼

在 MMTitleView 裡對標題文字居中調整(虛擬碼):

- (void)centerInView {
    [_titleLabel sizeToFit];
    CGSize size = _titleLabel.frame.size;
    CGRect frame = CGRectMake(0, 0, size.width, size.height);
    CGFloat x = (1 - CGRectGetWidth(frame)) * 0.5;
    CGFloat y = (44 - CGRectGetHeight(frame)) * 0.5;
    frame.origin = CGPointMake(x, y);
    _titleLabel.frame = frame;
}
複製程式碼

以上就是通過介面分析得到的導航欄按鈕定製的一個思路,簡單實用,佩服微信團隊的思維能力。 (完)

IMG_2865

相關文章