2014년 5월 4일 일요일

[iOS] TextView의 InnerShadow를 만들어 봅니다.

TextView의 배경에 안쪽 그림자를 만들어봅니다.

Inner Shadow가 적용된 화면

위의 그림처럼 TextView에서 InnerShadow를 이미지를 사용하지 않고 넣도록 합니다.

구현 방법은?

일단 배경이미지를 사용해서, 넣을 수도 있는데, 그렇게 되면, 메인 뷰의 배경이 변경이 되면 그것을 따라가지 못하고, 이미지의 색이 배경과 다르게 흰색 태두리가 생길 수 있습니다.
 그래서, CALayer를 이용해서, 그림자 효과로 만들어 봅니다.

- UIView에 대한 그림자 설정.

일단 일반적인 UIView의 CALayer에 그림자 설정과, 태두리를 둥글게 만들어 봅니다.
source code
    UIView *view;
    UIView *view;
    view = self.testView; //코드를 설명을 위해서 대입함.
    view.backgroundColor = [UIColor clearColor]; //배경을 투명하게 설정
    view.layer.cornerRadius = 10.0f;      //테두리 곡선이 되도록 설정 10.0f는 임의의 수
    view.layer.borderColor = [UIColor whiteColor].CGColor; //테두리 색상 흰색
    view.layer.borderWidth = 2.0f;                         //테두리 두께 2포인트
    view.layer.shadowColor = [UIColor blackColor].CGColor; //그림자 검은색
    view.layer.shadowOffset = CGSizeZero;   //그림자 위치는 뷰의 위치와 동일
    view.layer.shadowOpacity = 1.0f;        //그림자 투명도
    view.layer.shadowRadius = 3.0f;         //그림자의 퍼지는 범위 클수록 넓게 그림자 생김.

Storyboard에서 지정한 UITextField에 대해서 위와 같이 설정을 하면, 아래와 같이 표시가 됩니다.
위에서 코드를 추가합니다.
source code
    view.layer.masksToBounds = YES; //바운드 외부로 나가는 것을 Mask처리함
이렇게 하면 외부로 그림자가 나가는 것은 지워집니다.

이제 내부 테두리 비슷한 것이 설정이 되었습니다.
이것을 UITextView에 적용을 하면 아래와 같아집니다.
source code
    self.textView.backgroundColor = [UIColor clearColor];
    view = self.textView; //UITextView로 변경하고 설정함.
    view.backgroundColor = [UIColor clearColor];
    view.layer.cornerRadius = 10.0f;
    view.layer.borderColor = [UIColor whiteColor].CGColor;
    view.layer.shadowColor = [UIColor blackColor].CGColor;
    view.layer.borderWidth = 2.0f;
    view.layer.shadowOffset = CGSizeZero;
    view.layer.shadowOpacity = 1.0f;
    view.layer.shadowRadius = 3.0f;
    view.layer.masksToBounds = YES;

설정은 UIView에 했던것과 동일하고, 이 설정을 TextView에 한 것입니다.
테두리에 그림자가 생기기는 했지만, 내부의 글자에도 그림자가 표시되는 문제가 발생합니다.
이것을 어떻게 처리할 수가 없어서,
TextView의 자리 배경에 UIView를 두어서 TextView의 주변에 inner shadow가 있는 것처럼 설정을 합니다.

source code
-(void)drawInnerShadowOnViewForTextView:(UIView *)view color:(UIColor *)backgroundColor;
{
    UIEdgeInsets insets = {-10, -15, +20, +30};
    CGFloat cornerRadius = 18.5f;
    CGFloat borderWidth = 2.0f;
    CGFloat shadowRadius = 3.5f;
    CGFloat shadowOpacity = 1.0f;
    
    //그림자가 되는 View를 설정합니다.
    UIView *innerShadowView = [[UIView alloc] initWithFrame:CGRectMake(view.frame.origin.x+insets.top, view.frame.origin.y+insets.left, view.frame.size.width + insets.bottom, view.frame.size.height+ insets.right)];
    [innerShadowView setContentMode:UIViewContentModeScaleToFill];
    [innerShadowView setAutoresizingMask : UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
    [innerShadowView.layer setCornerRadius:cornerRadius]; //그림자의 가장자리 곡선
    [innerShadowView.layer setMasksToBounds:YES];
    [innerShadowView.layer setBorderColor: backgroundColor.CGColor]; //외부 배경을 테두리 색으로
    [innerShadowView.layer setShadowColor:[UIColor blackColor].CGColor]; //그림자 색
    [innerShadowView.layer setBorderWidth:borderWidth];
    [innerShadowView.layer setShadowOffset:CGSizeMake(0, 0)];
    [innerShadowView.layer setShadowOpacity:shadowOpacity];
    [innerShadowView.layer setShadowRadius:shadowRadius];
    
    [view.superview insertSubview:innerShadowView belowSubview:view];
}

위와 같이 inner shadow 역할을 하는 UIView를 만들어서, TextView의 바로 아래에 설정을 합니다.
얼추 비슷하게 나왔습니다.
헌데, View의 배경을 변경해 보면, 이상한 현상이 발생합니다.

inner shadow로 추가된 이미지 뒤에 같은 크기의 흰색 배경의 UIView를 추가해 줍니다.
source code
-(void)drawInnerShadowOnViewForTextView:(UIView *)view color:(UIColor *)backgroundColor;
{
    ...위와 동일...
    [innerShadowView.layer setShadowRadius:shadowRadius];

    //추가 시작
    UIView *innerBackgroundView = [[UIView alloc] initWithFrame:innerShadowView.frame];
    [innerBackgroundView setBackgroundColor:[UIColor whiteColor]];
    [innerBackgroundView.layer setCornerRadius:cornerRadius];
    [innerBackgroundView.layer setBorderWidth:borderWidth];
    [innerBackgroundView.layer setBorderColor:backgroundColor.CGColor];
    [innerBackgroundView setAlpha:0.8f];
    
    [view.superview insertSubview:innerBackgroundView belowSubview:view];
    //추가 끝.
    [view.superview insertSubview:innerShadowView belowSubview:view];

}
뷰의 추가 위치가 textView 밑에 innerShadow, 그 밑에 innerBackView가 추가되어야 합니다.
위와 같이 표시가 됩니다.
이제 배경색에 구애 받지 않고, 흰색으로 유지할 수 있습니다.

그리고, 배경화면이 있을 경우에는, TextView와 innerBackView의 alpha를 변경해서, 아래와 같이 표시할 수도 있습니다.


참고되시길 바랍니다.


[참고]
- StackOverflow: UIView create a inner shadow