Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: NedОтветов: 1

Я создаю подкласс 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

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

iphoneobjective-cuiscrollviewcalayer

Ответы

Ответ 1 · рейтинг 1 · Ben Zotto

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

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы