在UITextView上滚动内部阴影 [英] Scrolling inner shadow on UITextView

查看:51
本文介绍了在UITextView上滚动内部阴影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望对UITextView进行子类化,以便能够使用自定义边框加上顶部和左侧内部阴影绘制圆形矩形.

I would like to subclass UITextView to be able to draw round rect with custom border plus top+left inner shadow.

我在创建这种效果方面取得了巨大的成功(通过阅读帖子)(对于任意(静态边界)视图),但在滚动视图时遇到问题.

I had big success in creating this effect (by reading this post) for any (static bounds) view but had problems with scrolling views.

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

This effect I'm doing in -setFrame instance method of my custom class:

- (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:是一个定义为的类方法:

formatAsRoundRectWithShadowOn: is a class method defined as:

+(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方法来更新阴影层框架:

To handle correct shadow+border display when the text view is scrolling i'm using my custom class -setBounds method to update the shadow layer frame:

-(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];}

我遇到的问题是向下滚动(插入新行文本时)在底部或顶部(向上滚动到文本开头时)在底部的阴影+边框绘制错误.

The issue I'm experiencing is a incorrect shadow+frame drawing at the bottom when scrolling down (when inserting new lines of text) or at the top (when scrolling up to the beginning of the text).

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

After the new line is inserted or scroll completes (the view is again static) the view is drawn correct.

任何对此问题的见解都将受到欢迎.

Any insight on the issue is more than welcome.

推荐答案

我花了一些时间来研究问题并找到了我想分享的解决方案.

I had some time to dig into the problem and found a solution I want to share.

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

At first I realise that it's better to setup the shadow layer in -awakeFromNib instead in -setFrame.

要在文本视图滚动时处理正确的阴影+边框显示,我已更改了如下方法:要更新阴影层,我现在在自定义类中使用-layoutSubviews覆盖. 在-layoutSubviews覆盖中,我将重新创建阴影层以尊重新边界,然后调用[super layoutSubviews].

To handle correct shadow+border display when the text view is scrolling I've changed the approach like this: to update the shadow layer I'm now using -layoutSubviews override in my custom class. In -layoutSubviews override I'm recreating the shadow layer to respect new bounds then calling [super layoutSubviews].

滚动,改变方向-就像一个吊饰!

Scrolling, changing orientation - it works like a charm!

- (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现在正在将层引用返回到视图的层层次结构中已添加的层(重做很简单):

Note that +(NSUInteger)formatAsRoundRectWithShadowOn:(UIView*)view withBackgroundColor:(UIColor *)backgroundColor andBorderColor:(UIColor *)borderColor is now returning layer reference to the already added layer in the view's layer hierarchy (the rework is simple):

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

任何证据/评论都表明这种方法是正确的,而不仅仅是行之有效.

Any evidence/comments that this approach is correct and not just working would be highly appreciated.

这篇关于在UITextView上滚动内部阴影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆