본문 바로가기

iPhone

UILabel에 중앙선(취소선) 표시하기. (UIStrikeLabel)

UILabel 에 Text 를 입력하고, 중앙선(취소선)을 표시하고 싶지 않으세요? ^^;


UILabel 레퍼런스를 샅샅이 뒤져봤지만,  Strike를 표시하는 속성이나 메소드가 없더라고요.
게다가, IB에서 폰트 설정에 Strike 를 설정하는 부분이 있지만, 적용이 되지 않고요..

결국, 고민 끝에 UILabel 을 상속받은 새로운 클래스를 정의해서 구현하기로 했습니다.
뭐.. 그냥, Frame 사이즈에서 중앙선 위치를 구한 뒤에 라인을 하나 그어주면 되겠다 싶었죠.

헌데! 한 가지 생각지 못한 결과가 나오더라고요. 
바로.. Frame 사이즈대로 중앙선의 With를 결정하니, UILabel 의 전체 사이즈. 즉, 입력 된 Text 부분을 제외한 나머지 여백에도 중앙선이 생기는 겁니다. 

그래서, Font 사이즈가 고려 된 Text의 총 With를 알아내야만 되겠더라고요~

UILabel 에 set 된 Text의 Size 알기.

CGSize textSize = [[UILabel text] sizeWithFont:[UILabel font]];

이렇게 하면, UILabel 내 set 된 Text의 Size를 알 수 있습니다. 

그럼, Size를 구하고 중앙선(취소선)은 언제 그려줘야 할까요?
UILabel 의 레퍼런스를 보면,  다음과 같은 메소드가 있더라고요. 

drawTextInRect:

Draws the receiver’s text (or its shadow) in the specified rectangle.

해서, 저는 메서드를 오버라이드 했습니다.

#define strikeHeight 1.0


@implementation UIStrikeLabel


- (void)drawTextInRect:(CGRect)rect {

[super drawTextInRect:rect];

CGContextRef context = UIGraphicsGetCurrentContext();

CGSize textSize = [[self text] sizeWithFont:[self font]];

CGFloat strikeWidth = textSize.width;

CGContextFillRect(context, CGRectMake(0, rect.size.height/2, strikeWidth, strikeHeight));

}



@end


여기에 BOOL값으로 Strike 를 사용자가 선택 할 수 있게 하고,

if([self strike]) {

CGSize textSize = [[self text] sizeWithFont:[self font]];

CGFloat strikeWidth = textSize.width;

CGContextFillRect(context, [self getStrikeRect:strikeWidth]);

}


중앙선(취소선)의 위치를 텍스트 정렬에 따라 맞춰준다면 쓸만한 컨트롤이 될 수 있겠네요 :)

switch ([self textAlignment]) {

default:

case UITextAlignmentLeft:

x = 0;

break;

case UITextAlignmentCenter:

x = (self.frame.size.width - strikeWidth) / 2.0;

break;

case UITextAlignmentRight:

x = self.frame.size.width - strikeWidth;

break;

}


간단하게 샘플을 추가 해 봤습니다. x 축 정렬만 적용 된 버전입니다. :)


  • 2010.09.29 11:50

    비밀댓글입니다

    • Favicon of https://mingu.kr Min-gu, Kim 2010.09.29 12:41 신고

      A 뷰에서 B 뷰로 넘기는데, 스트링 값이 하나 넘어가는 거군요.

      B 뷰에 스트링 값의 변수를 만드시고, 변수를 셋팅하는 메서드를 구현하신 뒤에 스트링 값을 셋팅 한 뒤 [UITableView reloadData] 해 주시면 되겠네요.

      헌데, UITableView 의 경우 리스트 형태의 데이터를 표시하기 위한 UI 인데.. 단일 값(스트링 값-텍스트필드에서 입력 된)을 왜 UITableView 로 보여주시는건지 의문이네요 :)

  • 2010.09.29 13:25

    비밀댓글입니다

    • Favicon of https://mingu.kr Min-gu, Kim 2010.09.29 15:44 신고

      저는, 뷰A, 뷰B가 각각의 뷰 컨트롤러가 따로 있는 경우를 말씀 드린거에요 :)

      음 뷰A, 뷰B 하나의 뷰 컨트롤러로 화면 전환을 관리하신 거라면, B 뷰가 로드 됐을때 [UITableView reloadData] 만 하시면 됩니다.

      혹, UITableView 에 데이터 바인드 하시는 방법을 모르시는 거라면, http://mingu.kr/49 에 첨부 된 샘플을 한 번 체크 해 보세요~

  • 2010.09.29 18:12

    비밀댓글입니다

    • Favicon of https://mingu.kr Min-gu, Kim 2010.09.30 09:11 신고

      UITableViewDataSource 를 전혀 구현하시지 않았네요.

      UITableView 에 데이터를 바인딩 하시려면 UITaleViewDataSource 내 데이터를 구현 하셔야 합니다.

      http://mingu.kr/49 샘플 소스를 받으셔서 UITableView에 데이터를 바인딩 하는 방법을 먼저 체크 해 보세요 :)

  • comkid 2010.10.12 11:53

    마침 필요한 기능이었는데 좋은 자료 감사합니다. :)

  • Favicon of http://blog.jidolstar.com 지돌스타 2010.11.16 20:37

    좋은 정보 감사해요. 꼭 필요한 정보였습니다. ^^

  • 전영식 2010.12.14 20:18

    안녕하세요.. 여기 소스를 참고하여 UITextField로 변경하였습니다. 변경한 이유는 텍스트 수직 정렬을 사용하기 위해서 변경하였습니다.

    @interface UIStrikeTextField : UITextField {
    BOOL strike;
    CGFloat strikeHeight;
    }
    @property BOOL strike;
    @property CGFloat strikeHeight;

    - (CGRect) getStrikeRect:(CGFloat)strikeWidth;

    @end


    그리고 스트라이크 선이 아니고 UnderLine을 구현하기 위해 getStrikeRect 함수 안의
    CGFloat y = (self.frame.size.height - strikeHeight) / 2.0f;
    CGFloat y = self.frame.size.height - strikeHeight;
    로 변경하였습니다.

    그리고 UIView 안에 drawRect 함수에서 아래와 같이 코드를 작성하였습니다.

    UIStrikeTextField* pTextField = [[UIStrikeTextField alloc] initWithFrame:CGRectMake(0, 0, 80, 50)];
    pTextField.enabled = NO;
    pTextField.opaque = NO;

    // 크기 및 스타일
    UIFont* pFont = [UIFont boldSystemFontOfSize:20.0f];
    pTextField.font = pFont;

    pTextField.text = @"ON";

    [pTextField setStrikeHeight:1.0f];
    [pTextField setStrike:YES];

    // 수평 정렬
    pTextField.textAlignment = UITextAlignmentCenter;

    // 수직 정렬
    pTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;

    // 색 지정
    pTextField.textColor = [UIColor blackColor];
    pTextField.backgroundColor = [UIColor whiteColor];

    [self addSubview:pTextField];
    [pTextField release];

    근데 선이 나오질 않습니다... 아무래도 UILabel에서 UITextField로 변경해서 그런거 같습니다.
    위 코드 그대로(수직정렬부분은빼고..) UIStrikeLabel에서 수행해보면 UnderLine이 잘 나옵니다..
    제가 뭐 간과한게 있나요?? 아주 돌아버리겠습니다. ㅜㅜ

    • Favicon of https://mingu.kr Min-gu, Kim 2010.12.15 11:03 신고

      아마도
      CGFloat y = self.frame.size.hight - strikeHeight;
      이렇게 수정하신 부분 때문에 안보이는 것 같습니다.

      y 계산 부분을 달리 계산 해 보세요 :)

    • 전영식 2010.12.17 08:59

      해결했습니다.
      CGFloat y=self.frame.size.height - strikeHeight; 가 아니였습니다.
      x 좌표 구할때처럼 하면 돼는 줄 알았는데..
      vertical 인자가 UITextField 클래스의 멤버가 아니라 UIControl 멤버라서 그런지
      top이든 center이든 bottom이든 항상
      y=[[[self text] sizeWithFont:[self font]] height] - strikeHeight; 이렇게 해줘야 하더군요;;;;;;
      텍스트의 높이를 대입하는건데, 수직정렬은 계산할 필요가 없었나 봅니다^^

    • Favicon of https://mingu.kr Min-gu, Kim 2010.12.17 14:28 신고

      해결하셨다니 다행이네요 ^^

  • Favicon of http://likebnb.tistory.com likebnb 2013.02.18 11:19

    UITextAlignment* 가 iOS 6.0부터 deprecated되어 NSTextAlignment*를 써야 합니다.
    첨부하신 예제에서 해당 부분 고쳐서 실행해봤는데 잘 됩니다. ^^