在UITextView上滚动内部阴影

我想inheritanceUITextView能够用自定义边框加顶部+左边的内部阴影绘制圆形矩形。

对于任何(静态边界)视图,我都在创build这个效果方面取得了巨大的成功(阅读这篇文章),但是在滚动视图时遇到了问题。

这个效果我在我的自定义类的-setFrame实例方法中做:

- (void)setFrame:(CGRect)frame { [super setFrame:frame]; UIColor *borderColor = [UIColor colorWithRed:BORDER_COLOR_RED green:BORDER_COLOR_GREEN blue:BORDER_COLOR_BLUE alpha:BORDER_COLOR_ALPHA]; // Store index of the shadow sublayer for future use [self setShadowLayerIndex:[LayerFormatter formatAsRoundRectWithShadowOn:self withBackgroundColor:[UIColor whiteColor] andBorderColor:borderColor]];} 

formatAsRoundRectWithShadowOn:是一个类方法定义为:

 +(NSUInteger)formatAsRoundRectWithShadowOn:(UIView*)view withBackgroundColor:(UIColor *)backgroundColor andBorderColor:(UIColor *)borderColor { if([view isKindOfClass:[UITextField class]]) ((UITextField*)view).borderStyle = UITextBorderStyleNone; view.backgroundColor = backgroundColor; view.layer.borderWidth = 1.0; view.layer.borderColor = [borderColor CGColor]; view.layer.cornerRadius = CORNER_RADIUS; view.layer.masksToBounds = YES; //Add some insets to the text: https://stackoverflow.com/a/4423805 UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 5, 20)]; if([view isKindOfClass:[UITextField class]]) { ((UITextField*)view).leftView = paddingView; ((UITextField*)view).leftViewMode = UITextFieldViewModeAlways; } // Create and apply a shadow layer. Help here: https://stackoverflow.com/questions/4431292/inner-shadow-effect-on-uiview-layer CAShapeLayer* shadowLayer = [CAShapeLayer layer]; [shadowLayer setFrame:view.bounds]; [shadowLayer setShadowColor:[[UIColor blackColor] CGColor]]; [shadowLayer setShadowRadius:3.0f]; [shadowLayer setShadowOpacity:0.35f]; [shadowLayer setShadowOffset:CGSizeMake(2.0f, 2.0f)]; [shadowLayer setFillColor:[backgroundColor CGColor]]; // Causes the inner region in this example to NOT be filled. [shadowLayer setFillRule:kCAFillRuleEvenOdd]; // Create inner and outer rectangle paths. CGMutablePathRef path = CGPathCreateMutable(); // Outer path should be bigger than the field UIBezierPath *bpOuter = [UIBezierPath bezierPathWithRect:CGRectInset(shadowLayer.bounds, -10, -10)]; // Inner path is the visible part of the view UIBezierPath *bpInner = [UIBezierPath bezierPathWithRoundedRect:shadowLayer.bounds cornerRadius:CORNER_RADIUS]; // Add outer path and then add the inner path so it's subtracted from the outer path. CGPathAddPath(path, NULL, bpOuter.CGPath); CGPathAddPath(path, NULL, bpInner.CGPath); CGPathCloseSubpath(path); [shadowLayer setPath:path]; CGPathRelease(path); [[view layer] addSublayer:shadowLayer]; NSUInteger addedAtIndex = [[[view layer] sublayers] indexOfObject:shadowLayer]; return addedAtIndex;} 

要处理正确的阴影+边框显示滚动文本视图时我使用我的自定义类-setBounds方法来更新阴影层框架:

 -(void)setBounds:(CGRect)bounds{ [super setBounds:bounds]; // Change the frame of the shadow layer to reflect new bounds [[[[self layer] sublayers] objectAtIndex:self.shadowLayerIndex] setFrame:bounds];} 

我遇到的问题是在向下滚动(当插入新的文本行时)或在顶部(滚动到文本的开始处)时,在底部绘制不正确的阴影+框架。

插入新行或滚动完成后(视图再次为静态),视图绘制正确。

任何有关这个问题的见解都是值得欢迎的。

我有一些时间来深入研究这个问题,并find了一个我想分享的解决scheme。

起初我意识到最好在-awakeFromNib设置阴影层,而不是在-setFrame

当文本视图滚动时处理正确的阴影+边框显示我改变了这样的方法:更新阴影层我现在使用-layoutSubviews覆盖在我的自定义类。 在-layoutSubviews重写我重新创build阴影层尊重新的界限,然后调用[super layoutSubviews]

滚动,改变方向 – 它就像一个魅力!

 - (void)layoutSubviews { [self updateShadow]; [super layoutSubviews]; } - (void)updateShadow { if (shadowLayer) [shadowLayer removeFromSuperlayer]; shadowLayer = [LayerFormatter addInnerShadowLayerOn:self withShadowColor:[UIColor blackColor]]; } 

请注意+(NSUInteger)formatAsRoundRectWithShadowOn:(UIView*)view withBackgroundColor:(UIColor *)backgroundColor andBorderColor:(UIColor *)borderColor现在返回图层的层次结构中已经添加的图层的图层引用(返工很简单):

 +(CAShapeLayer *)addInnerShadowLayerOn:(UIView *)view withShadowColor:(UIColor *)shadowColor; 

任何证据/意见,这种方法是正确的,不只是工作将不胜感激。