7

私は自分の問題について少し調査しましたが、残念ながら私の問題に対する解決策はありませんでした。最も近いのは、UIScrollView の端に近づくにつれて Fade UIImageView でしたが、それでも私には適していません。

テーブルの上部に「非表示グラデーション」を適用したい。セルが上端から 50px の距離にある場合、セルは消え始めます。上端に近づくほど、パーツは見えなくなります。セルの高さは約 200 ピクセルなので、セルの下部が 100% 表示される必要があります。ただし、このタスクを実行するにはテーブル ビュー (またはテーブル ビュー コンテナー) が必要です。同様のテーブルに他のセルを表示できるからです。

テーブルが無地のビューのサブビューである場合、任意の幅に伸ばすことができる水平方向のグラデーションである画像を追加することで、それを実現できます。その画像の一番上のピクセルは背景の正確な色で始まり、同じ色を下に行くとアルファが少なくなります。

しかし...透明な色の UITableView があります。表の下には単色はありませんが、アプリの他の画面でも異なる可能性のあるパターン画像/テクスチャがあります.

どうすればこの動作を達成できるか考えていますか?

よろしく

4

4 に答える 4

5

@victorfigol の優れたソリューションの Swift バージョン:

class FadingTableView : UITableView {
  var percent = Float(0.05)

  private let outerColor = UIColor(white: 1.0, alpha: 0.0).cgColor
  private let innerColor = UIColor(white: 1.0, alpha: 1.0).cgColor

  override func awakeFromNib() {
    super.awakeFromNib()
    addObserver(self, forKeyPath: "bounds", options: NSKeyValueObservingOptions(rawValue: 0), context: nil)
  }

  override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if object is FadingTableView && keyPath == "bounds" {
        initMask()
    }
  }

  deinit {
    removeObserver(self, forKeyPath:"bounds")
  }

  override func layoutSubviews() {
    super.layoutSubviews()
    updateMask()
  }

  func initMask() {
    let maskLayer = CAGradientLayer()
    maskLayer.locations = [0.0, NSNumber(value: percent), NSNumber(value:1 - percent), 1.0]
    maskLayer.bounds = CGRect(x:0, y:0, width:frame.size.width, height:frame.size.height)
    maskLayer.anchorPoint = CGPoint.zero
    self.layer.mask = maskLayer

    updateMask()
  }

  func updateMask() {
    let scrollView : UIScrollView = self

    var colors = [CGColor]()

    if scrollView.contentOffset.y <= -scrollView.contentInset.top { // top
        colors = [innerColor, innerColor, innerColor, outerColor]
    }
    else if (scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height { // bottom
        colors = [outerColor, innerColor, innerColor, innerColor]
    }
    else {
        colors = [outerColor, innerColor, innerColor, outerColor]
    }

    if let mask = scrollView.layer.mask as? CAGradientLayer {
        mask.colors = colors

        CATransaction.begin()
        CATransaction.setDisableActions(true)
        mask.position = CGPoint(x: 0.0, y: scrollView.contentOffset.y)
        CATransaction.commit()
     }
  }
}
于 2016-12-28T19:05:23.737 に答える
4

これは、UITableView を継承してフェード テーブル ビューの私のバージョンです。iOS 7 & 8 でテスト済み。

  1. scrollViewDidScroll を実装する必要はありません。代わりに layoutSubviews を使用できます。
  2. 境界の変化を観察することで、回転が変化したときにマスクが常に適切に配置されます。
  3. パーセント パラメータを使用して、エッジで必要なフェードの量を変更できます。場合によっては、小さな値の方が見栄えが良いことがわかります。

CEFadingTableView.m

#import "CEFadingTableView.h"

@interface CEFadingTableView()

@property (nonatomic) float percent; // 1 - 100%

@end

@implementation CEFadingTableView

- (void)awakeFromNib
{
    [super awakeFromNib];

    self.percent = 5.0f;

    [self addObserver:self forKeyPath:@"bounds" options:0 context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if(object == self && [keyPath isEqualToString:@"bounds"])
    {
        [self initMask];
    }
}

- (void)dealloc
{
    [self removeObserver:self forKeyPath:@"bounds"];
}

- (void)layoutSubviews
{
    [super layoutSubviews];

    [self updateMask];
}

- (void)initMask
{
    CAGradientLayer *maskLayer = [CAGradientLayer layer];

    maskLayer.locations = @[@(0.0f), @(_percent / 100), @(1 - _percent / 100), @(1.0f)];

    maskLayer.bounds = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);

    maskLayer.anchorPoint = CGPointZero;

    self.layer.mask = maskLayer;

    [self updateMask];
}

- (void)updateMask
{
    UIScrollView *scrollView = self;

    CGColorRef outer = [UIColor colorWithWhite:1.0 alpha:0.0].CGColor;
    CGColorRef inner = [UIColor colorWithWhite:1.0 alpha:1.0].CGColor;

    NSArray *colors = @[(__bridge id)outer, (__bridge id)inner, (__bridge id)inner, (__bridge id)outer];

    if(scrollView.contentOffset.y <= 0) // top
    {
        colors = @[(__bridge id)inner, (__bridge id)inner, (__bridge id)inner, (__bridge id)outer];
    }
    else if((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height) // bottom
    {
        colors = @[(__bridge id)outer, (__bridge id)inner, (__bridge id)inner, (__bridge id)inner];
    }

    ((CAGradientLayer *)scrollView.layer.mask).colors = colors;

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    scrollView.layer.mask.position = CGPointMake(0, scrollView.contentOffset.y);
    [CATransaction commit];
}

@end
于 2014-10-05T00:01:09.110 に答える