2013年5月29日 星期三

UILabel with StrikeThrough

要蠻幹的方法有很多, 直接用一個UIImageView 蓋在UILabel前面也可以
而在iOS6之後, 有NSAttributedString可用, 所以此方法適用在iOS6之前
以下是在這邊學到的方法, 自己練習一下並增加一些額外的property

建立一個新的Class, 命名為CustomLabel, 並繼承UILabel

CustomLabel.h
#import <UIKit/UIKit.h> 
@interface CustomLabel : UILabel 
@property (nonatomic) BOOL strikeThrough;
@property (nonatomic) float strikeThroughWidth;
@property (nonatomic) UIColor *strikeThroughColor; 
@end

CustomLabel.m
#import "CustomLabel.h"

@implementation CustomLabel

- (id)initWithFrame:(CGRect)frame{
 self = [super initWithFrame:frame];
 if (self) {
  // Initialization code
  self.strikeThrough = NO;
  self.strikeThroughWidth = 1;
  self.strikeThroughColor = [UIColor blackColor];
 }
 return self;
}

- (void)drawTextInRect:(CGRect)rect {
 [super drawTextInRect:rect];
 
 if (_strikeThrough) {
  [_strikeThroughColor set];
  CGContextRef context = UIGraphicsGetCurrentContext();
  CGSize textSize = [[self text] sizeWithFont:[self font]];
  CGFloat strikeWidth = textSize.width;  CGRect lineRect;
  
  if ([self textAlignment] == NSTextAlignmentRight) {
   lineRect = CGRectMake(rect.size.width - strikeWidth,
          (rect.size.height - _strikeThroughWidth) / 2,
          strikeWidth,
          _strikeThroughWidth);
  }  else if ([self textAlignment] == NSTextAlignmentCenter) {
   lineRect = CGRectMake(rect.size.width/2 - strikeWidth/2,
          (rect.size.height - _strikeThroughWidth) / 2,
          strikeWidth,
          _strikeThroughWidth);
  }  else {
   lineRect = CGRectMake(0,
          (rect.size.height - _strikeThroughWidth) / 2,
          strikeWidth,
          _strikeThroughWidth);
  }
  
  CGContextFillRect(context, lineRect);
 }
}

- (void)setStrikeThrough:(BOOL)strikeThrough {
 _strikeThrough = strikeThrough;
 NSString *tempText = [self.text copy];
 self.text = @"";
 self.text = tempText;
}

@end

原作者寫法是只有寬度為1的刪除線, 並且顏色是黑的
我增加了兩個針對刪除線的property(顏色, 寬度), 並且稍微修改一下程式內容
預設在initWithFrame時, 不顯示刪除線, 寬度為1, 顏色黑色
之後可以在自己修改property

若是刪除線已經顯示, 要改變設定strikeThroughWidth或着strikeThroughColor
要呼叫 [customLabel setNeedsDisplay]; 來重繪Label
例如下面程式, 在Action動作之前, CustomLabel已經顯示, 並且已經包含有刪除線
- (IBAction)btnAction:(id)sender {
 customLabel.strikeThroughWidth = 3;
 customLabel.strikeThroughColor = [UIColor redColor];
 [customLabel setNeedsDisplay];
}

實際使用就跟一般UILabel一樣, 在自己的class中 #import "CustomLabel.h"
CustomLabel *customLabel = [[CustomLabel alloc] initWithFrame:CGRectMake(20, 20, 280, 80)];
customLabel.backgroundColor = [UIColor whiteColor];
customLabel.textColor = [UIColor blackColor];
customLabel.font = [UIFont boldSystemFontOfSize:80];
customLabel.textAlignment = NSTextAlignmentCenter;
customLabel.text = @"Label中文123";
 
customLabel.strikeThrough = YES;
customLabel.strikeThroughWidth = 10;
customLabel.strikeThroughColor = [UIColor blueColor];
 
[self.view addSubview:customLabel];

已知的問題, 因為它是用整個Label Rect計算刪除線位置的
若是呼叫 adjustsFontSizeToFitWidth 以及 numberOfLines>1(文字實際顯示到兩行以上), 刪除線位置會出問題

沒有留言:

張貼留言