圖層與文字的完美設(shè)計

圖層與文字的完美設(shè)計1.png

我們先來一個簡單的卡拉OK效果練練手吧

卡拉OK效果.gif

這個非常容易,設(shè)置定時器計算進(jìn)度progress。重寫UILabel的drawRect:,通過progress計算顏色區(qū)域,然后填充顏色就行,不過要注意一下填充方式。

// 這里計算字體大小與frame需要做一些優(yōu)化。因為該方式調(diào)用非常多
- (void)setProgress:(CGFloat)progress{
    _progress = progress;
    if (_progress == 0) {
        [self setFont:[UIFont systemFontOfSize:14]];
    } else {
        [self setFont:[UIFont boldSystemFontOfSize:16]];
    }
    [self sizeToFit]; 
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];
    
    CGFloat width = self.frame.size.width * self.progress;
    CGRect colorRect = CGRectMake(0, 0, width, self.frame.size.height);
    
    if (self.color) {
        [self.color setFill];
    } else {
        [[UIColor redColor] setFill];
    }
    
    UIRectFill(fillRect);
}

目前得到的效果是一下形式的:

卡拉OK效果-1.gif

因為填充方式不對,這里需要使用另一個函數(shù)UIRectFillUsingBlendMode

    // UIRectFill(fillRect);
    UIRectFillUsingBlendMode(colorRect, kCGBlendModeSourceIn);

現(xiàn)在了解到填充方式有兩種:直接所有覆蓋和有內(nèi)容顯示的位置覆蓋。通過UIRectFillUsingBlendMode還可以設(shè)置很多種填充方式。

再來一個比較漂亮的UISearchBar

UISearchBar.png
自定義UISearchBar.png

也是比較簡單,直接上代碼了:

// 初始化方法中用到。initWithCoder:、initWithFrame:
- (void)setup {
    // 設(shè)置背景圖是為了去掉上下黑線
    self.backgroundImage = [[UIImage alloc] init];
    // 設(shè)置SearchBar的顏色主題為白色
    self.barTintColor = [UIColor whiteColor];
    // 修正光標(biāo)顏色
    self.tintColor = [UIColor colorWithRGB:Color_Green_V];
    // 設(shè)置搜索Icon
    [self setImage:[UIImage imageNamed:@"Search_Icon"] forSearchBarIcon:UISearchBarIconSearch state:UIControlStateNormal];
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    // 設(shè)置圓角和邊框顏色
    UITextField *searchField = [self valueForKey:@"searchField"];
    if (searchField) {
        [searchField setBackgroundColor:[UIColor whiteColor]];
        searchField.font = [UIFont systemFontOfSize:Font_Normal];
        searchField.layer.cornerRadius = searchField.height * 0.5;
        searchField.layer.borderColor = [UIColor colorWithRGB:Color_Green_V].CGColor;
        searchField.layer.borderWidth = 1;
        searchField.layer.masksToBounds = YES;
    }
}

現(xiàn)在我們開始實現(xiàn)一下今天的目標(biāo)效果

顏色與文字的完美設(shè)計1.png

在此之前要用到漸變效果


漸變效果.png
    UIView *backView = [UIView new];
    backView.frame = CGRectMake(0, -20, ScreenW, 64);
    CAGradientLayer *gradientLayer = [[CAGradientLayer alloc] init];
    gradientLayer.frame = CGRectMake(0, 0, ScreenW, 64);
    gradientLayer.colors = @[(__bridge id)[UIColor colorWithHex:0xe8292a alpha:0.76].CGColor,(__bridge id)[UIColor colorWithHex:0x60d653 alpha:0.28].CGColor];
    gradientLayer.startPoint = CGPointMake(0, 0);
    gradientLayer.endPoint = CGPointMake(0, 1.0);
    [backView.layer addSublayer:gradientLayer];

雖然知道要用到漸變,但是怎么實現(xiàn)目標(biāo)效果中指定路徑還有文字的顏色漸變呢?
1、創(chuàng)建一個label,并設(shè)置layer.cornerRadius、layer.borderColorlayer.borderWidth
2、大家應(yīng)該都知道CALayer中有個mask屬性,并且他也是一個CALayer對象。那么我們是否可以通過上邊的label的layer設(shè)置成一個layer的mask呢?而漸變圖層CAGradientLayer繼承自CALayer,當(dāng)然也有mask屬性,如果它的mask賦值為label.layer是不是能實現(xiàn)我們想要的效果了?開始行動,試一哈

    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(30, 130, 250, 50)];
    view.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:view];
    
    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 200, 30)];
    label.text = @"哈哈哈哈哈哈哈哈";
    label.textAlignment = NSTextAlignmentCenter;
//    label.textColor = [UIColor clearColor];
    
    label.layer.cornerRadius = 15;
    label.layer.borderColor = [UIColor blackColor].CGColor;
    label.layer.borderWidth = 1;
    
    [view addSubview:label];
    
    CAGradientLayer *gradientLayer = [CAGradientLayer layer];
    gradientLayer.frame = label.frame;
    
    gradientLayer.colors = @[(__bridge id)[UIColor colorWithHex:0xe8292a alpha:0.76].CGColor,(__bridge id)[UIColor colorWithHex:0x60d653 alpha:0.28].CGColor];
    gradientLayer.startPoint = CGPointMake(0, 0);
    gradientLayer.endPoint = CGPointMake(1.0, 1.0);
    
    [view.layer addSublayer:gradientLayer];
    gradientLayer.mask = label.layer;
    
    // 父層改了,坐標(biāo)系需要重新設(shè)置
    label.frame = gradientLayer.bounds;

呵呵,很高興就這么完成了。
上邊代碼需要注意和了解的是:
1,mask圖層,根據(jù)透明度進(jìn)行裁剪,只保留非透明部分,顯示底部內(nèi)容。所以label的文字顏色與邊框顏色不能為空。
2,因為label的layer設(shè)置為別的圖層的mask時,frame機(jī)制改變了,所以坐標(biāo)系需要重新設(shè)置。

另外可能還想讓這個漸變的顏色一直變化,還可以加一個定時器。

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.5 repeats:YES block:^(NSTimer * _Nonnull timer) {
        gradientLayer.colors = @[(__bridge id)[UIColor randomColor].CGColor, (__bridge id)[UIColor randomColor].CGColor,(__bridge id)[UIColor randomColor].CGColor];
    }];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
圖層與文字的完美設(shè)計2.gif

現(xiàn)在我們將上邊的label,換成button,希望點擊文字時有響應(yīng)。代碼就不寫了,結(jié)果是沒有任何響應(yīng)。Debug view hierarchy之后,發(fā)現(xiàn)button控件是不存在的?;氐揭郧暗拇a,發(fā)現(xiàn)label也同樣是不存在的。
注意:一旦把控件層設(shè)置為mask層,控件層就不能顯示了,會直接從父層中移除,然后作為漸變層的mask層,且控件層的父層會指向漸變層。
那么怎么讓其有點擊事件呢?將上邊代碼的父控件view的類型改為UIButton即可。??????

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

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

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