Исправление CALayer вверху и внизу UIScrollView

Я создаю подкласс UIScrollView и добавляю некоторые визуальные элементы. Вверху должен быть градиент, идущий от черного к прозрачному, а внизу есть маска, которая исчезает к низу. У меня есть эти слои, добавленные и выглядящие правильно, но когда я прокручиваю, они остаются в координатах, в которые я их вставил (относительно представления прокрутки), а не «фиксируются» внизу и вверху представления. Этот вид прокрутки прокручивается только по вертикали.

Вот код для SettingsScrollView.m:

#import "SettingsScrollView.h"
#import <QuartzCore/QuartzCore.h>

#define SHADOW_HEIGHT 20.0
#define SHADOW_INVERSE_HEIGHT 10.0
#define SHADOW_RATIO (SHADOW_INVERSE_HEIGHT / SHADOW_HEIGHT)

@implementation SettingsScrollView


- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];

    [self setUpShadow];

    return self;
}

- (CAGradientLayer *)shadowAsInverse:(BOOL)inverse
{
    CAGradientLayer *newShadow = [[[CAGradientLayer alloc] init] autorelease];
    CGRect newShadowFrame = CGRectMake(0, 0, self.frame.size.width, inverse ? SHADOW_INVERSE_HEIGHT : SHADOW_HEIGHT);
    newShadow.frame = newShadowFrame;
    CGColorRef darkColor =[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:inverse ? (SHADOW_INVERSE_HEIGHT / SHADOW_HEIGHT) * 0.5 : 0.5].CGColor;
    CGColorRef lightColor = [self.backgroundColor colorWithAlphaComponent:0.0].CGColor;

    newShadow.colors = [NSArray arrayWithObjects: (id)(inverse ? lightColor : darkColor), (id)(inverse ? darkColor : lightColor), nil];
    return newShadow;
}

- (CAGradientLayer *)gradientMask
{
    CAGradientLayer *mask = [[[CAGradientLayer alloc] init] autorelease];
    CGRect maskFrame =  CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
    mask.frame = maskFrame;
    CGColorRef darkColor =[UIColor clearColor].CGColor;
    CGColorRef lightColor =[UIColor blackColor].CGColor;

    mask.colors = [NSArray arrayWithObjects: (id)lightColor, (id)lightColor, (id)darkColor, nil];
    mask.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.9], [NSNumber numberWithFloat:1.0], nil]; 
    return mask;
}

- (void)setUpShadow
{
    CAGradientLayer *topShadowLayer = [self shadowAsInverse:NO];
    CAGradientLayer *bottomShadowLayer = [self gradientMask];

    [self.layer insertSublayer:topShadowLayer atIndex:0];

    [self.layer setMask:bottomShadowLayer];

    [CATransaction begin];
    [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

    CGRect topShadowLayerFrame = topShadowLayer.frame;
    topShadowLayerFrame.size.width = self.frame.size.width;
    topShadowLayerFrame.origin.y = 0;
    topShadowLayer.frame = topShadowLayerFrame;

    CGRect bottomShadowLayerFrame = bottomShadowLayer.frame;
    bottomShadowLayerFrame.size.width = self.frame.size.width;
    bottomShadowLayerFrame.origin.y = self.frame.size.height - bottomShadowLayer.frame.size.height;
    bottomShadowLayer.frame = bottomShadowLayerFrame;

    [CATransaction commit];
}

@end

Я знаю, что одним из решений для верхней части может быть просто добавление отдельного представления, содержащего градиент, но для нижней части, я считаю, мне нужно использовать маску, чтобы она делала то, что я хочу (исчезать на фоне в самом конце). Нижний). Фон — это изображение, поэтому я не могу просто перейти к белому или другому цвету, он должен исчезнуть, чтобы очиститься. Я искал метод, который вызывается при перемещении прокрутки и использует его для изменения положения маски, но пока ничего не нашел. Какие-либо предложения?


person Ned    schedule 16.12.2010    source источник


Ответы (1)


Вероятно, вы могли бы добиться этого, переопределив -layoutSubviews в UIScrollView, который вызывается при изменении его границ.

Другой метод, который я видел в представлениях, подобных этому, заключается в том, что вместо того, чтобы выполнять это управление слоями из представления, подкласс CALayer, используйте свой подкласс в качестве слоя представления прокрутки, а затем в своем слое -layoutSublayers проделайте ту же работу, когда он перемещается. . Я упомянул этот последний метод, потому что для слоя кажется несколько более естественным управлять своими подслоями, чем представление, управляющее своими слоями напрямую.

person Ben Zotto    schedule 16.12.2010
comment
Ах, layoutSubviews был методом, который я искал. Спасибо! - person Ned; 16.12.2010