2

UIScrollViewスクロールで簡単に調整できる長さで、かなり複雑な階層を持つ上にいくつかのフェードエッジを作成しようとしています。これは基本的に私が達成しようとしている効果です(フェードエッジに注意してください):

ここに画像の説明を入力

トリッキーな部分は次のとおりです。

  1. 背景が動的であるという事実
  2. ユーザーがスクロールするにつれて、フェードエッジが「成長」するようにします。つまり、スクロールが発生していないときは存在しませんが、スクロールが開始されると、フェード効果が増加するcontentOffsetにつれて増加します。
  3. いいえに似ています。2、スクロールが完了すると、フェードエッジがスムーズに縮小するはずです

CAGradientLayerビューのレイヤーとして使用されるカスタムを使用して、必要なもののほとんどを取得しましmaskたが、パフォーマンスが十分でないという問題があります。次に、オンデマンドでマスクを切り替えてみました。スクロールが始まるとマスクが設定され、スクロールが停止するとマスクが削除されます。この種の作業 (いくつかのバグがありました) が、Apple のドキュメントによると、オンザフライでマスクを変更すると未定義の動作をすることが後でわかりました。私はまだ CoreGraphics ベースのソリューションを決定していません。それが実現可能かどうか、またはパフォーマンスが向上するかどうかはわかりません。コンテンツと背景の両方が動的であるため、画像を使用してグラデーションをシミュレートすることもできません。

CAGradientLayerこれは、私が作成したカスタム サブクラスの実装です。

- (id) init {
    self = [super init];
    if (self) {
        self.anchorPoint = CGPointZero;

        self.startPoint = CGPointMake(0.0, 0.5);
        self.endPoint = CGPointMake(1.0, 0.5);

        CGColorRef transluscentColor = [UIColor colorWithWhite:1.0 alpha:0.0].CGColor;
        CGColorRef opaqueColor = [UIColor colorWithWhite:1.0 alpha:1.0].CGColor;

        self.colors = [NSArray arrayWithObjects:
                       (id)opaqueColor,
                       (id)transluscentColor, 
                       (id)opaqueColor, 
                       (id)opaqueColor,
                       (id)transluscentColor,
                       (id)opaqueColor, nil];
        self.locations = [NSArray arrayWithObjects:
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:1.0f],
                          [NSNumber numberWithFloat:1.0f],
                          [NSNumber numberWithFloat:1.0f], nil];
    }

    return self;
}

- (void) setAbsoluteStartPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    self.startPoint = CGPointMake(startPoint.x / self.bounds.size.width, startPoint.y / self.bounds.size.height);
    self.endPoint = CGPointMake(endPoint.x / self.bounds.size.width, endPoint.y / self.bounds.size.height);
    [CATransaction commit];
}

- (void) setGradientStartLength:(CGFloat)startLength endLength:(CGFloat)endLength animated:(BOOL)animated {
    CGFloat deltaX = (self.endPoint.x - self.startPoint.x);
    CGFloat deltaY = (self.endPoint.y - self.startPoint.y);

    // use the side whose change is largest as our base length
    CGFloat sideLength = (deltaX > deltaY ? self.bounds.size.width * deltaX : self.bounds.size.height * deltaY);

    CGFloat startRatio = MAX((startLength / sideLength), 0.0f);
    CGFloat endRatio = 1.0f - MAX((endLength / sideLength), 0.0f);

    NSArray *locations = [NSArray arrayWithObjects:
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:0.0f],
                          [NSNumber numberWithFloat:startRatio],
                          [NSNumber numberWithFloat:endRatio],
                          [NSNumber numberWithFloat:1.0f],
                          [NSNumber numberWithFloat:1.0f], nil];

    [CATransaction begin];
    if (animated) {
        [CATransaction setAnimationDuration:0.5];
        [CATransaction setAnimationTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn]];
    }
    else {
        [CATransaction setDisableActions:YES];
    }

    self.locations = locations;
    [CATransaction commit];
}

my で使用する場合UIScrollView、基本的にはレイヤーpositionを に合わせて調整し、アニメーションcontentOffsetを使用せずにサイズを調整しますsetGradientStartLength:endLength:animated:(ただし、アニメーションはそれほど遅くはありません)。

私が言ったように、これは私が望むことをしますが、私が必要とするパフォーマンスのレベルではありません(スクロールビューとして使用すると、フレームレートは60fpsから約30に低下しますmask)。maskそして、私はプロパティを使用せずにこれを行う良い方法を考え出していません.

私の推測では、これは上記と同様のコードを使用して達成可能ですが、ビューのmask. しかし、レイヤーがサブレイヤーとして使用されているときに、このようなフェード効果を追加する方法を決定していません。また、他の誰かが同じことを行った例も見たことがありません.

ここで誰かが私を正しい方向に向けることができますか? これらに関する Apple のドキュメントは非常に限られています。

4

0 に答える 0