2

UITextView をサブクラス化して、カスタム境界線と左上の内側の影で丸い四角形を描画できるようにしたいと思います。

任意の (静的境界) ビューに対してこの効果を (この投稿を読んで) 作成することに大きな成功を収めましたが、ビューのスクロールに問題がありました。

カスタム クラスの -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];}

私が経験している問題は、下にスクロールするとき (新しいテキスト行を挿入するとき) または上 (テキストの先頭までスクロールするとき) に、下部に誤った影とフレームが描画されることです。

新しい行が挿入されるか、スクロールが完了すると (ビューは再び静的になります)、ビューは正しく描画されます。

この問題に関する洞察は大歓迎です。

4

1 に答える 1

1

問題を掘り下げて、共有したい解決策を見つける時間がありました。

-awakeFromNib最初は、代わりにでシャドウレイヤーを設定する方が良いことに気付きました-setFrame

テキストビューがスクロールしているときに正しいシャドウ+ボーダー表示を処理するために、次のようにアプローチを変更しました。シャドウレイヤーを更新するため-layoutSubviewsに、カスタムクラスでオーバーライドを使用しています。オーバーライドでは-layoutSubviews、新しい境界を尊重するようにシャドウレイヤーを再作成してから、を呼び出し[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;

このアプローチが正しく、機能しているだけではないという証拠/コメントをいただければ幸いです。

于 2013-01-29T15:24:36.123 に答える