7

我对我的问题进行了一些研究,不幸的是我的问题没有解决方案。最接近的是Fade UIImageView,因为它接近 UIScrollView 的边缘,但它仍然不适合我。

我希望我的桌子在顶部应用“隐形渐变”。如果单元格距离上边缘 50 像素,它就会开始消失。越靠近上边缘,零件越不可见。单元格高度约为 200 像素,因此单元格的下部需要 100% 可见。但没关系 - 我需要一个表格视图(或表格视图容器)来执行此任务,因为类似的表格可以显示其他单元格。

如果表格是纯色视图的子视图,我可以通过添加一个水平渐变的图像来实现这一点,我可以延伸到任何宽度。该图像的顶部像素以背景的确切颜色开始,向下相同颜色具有较少的 alpha。

但是......我们有一个透明颜色的 UITableView 。表格下方没有纯色,而是图案图像/纹理,在应用程序的其他屏幕上也可能不同。

你有什么想法我可以实现这种行为吗?

问候

4

4 回答 4

14

我学习了教程并进行了一些更改和添加:

  • 它现在适用于所有表格视图 - 即使它们是更大屏幕的一部分。
  • 无论背景或表格视图后面的内容如何,​​它都可以工作。
  • 掩码的变化取决于表格视图的位置 - 当滚动到顶部时只有底部褪色,当滚动到底部时只有顶部褪色......

1.首先在控制器中导入QuartzCore 和设置蒙版层

编辑:不需要CAGradientLayer在课堂上参考。

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>

@interface mViewController : UIViewController
.
.
@end

2.将此添加到:( 参阅@Darren对此的评论viewWillAppear viewDidLayoutSubviews

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    if (!self.tableView.layer.mask)
    {
        CAGradientLayer *maskLayer = [CAGradientLayer layer];

        maskLayer.locations = @[[NSNumber numberWithFloat:0.0], 
                                [NSNumber numberWithFloat:0.2], 
                                [NSNumber numberWithFloat:0.8], 
                                [NSNumber numberWithFloat:1.0]];

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

       self.tableView.layer.mask = maskLayer;
    }
    [self scrollViewDidScroll:self.tableView];
}

3.UIScrollViewDelegate通过将其添加到.h您的控制器中,确保您是代表:

@interface mViewController : UIViewController <UIScrollViewDelegate>

4.最后,scrollViewDidScroll在您的控制器中实现.m

#pragma mark - Scroll View Delegate Methods

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    CGColorRef outerColor = [UIColor colorWithWhite:1.0 alpha:0.0].CGColor;
    CGColorRef innerColor = [UIColor colorWithWhite:1.0 alpha:1.0].CGColor;
    NSArray *colors;

    if (scrollView.contentOffset.y + scrollView.contentInset.top <= 0) {
        //Top of scrollView
        colors = @[(__bridge id)innerColor, (__bridge id)innerColor,
                   (__bridge id)innerColor, (__bridge id)outerColor];
    } else if (scrollView.contentOffset.y + scrollView.frame.size.height
               >= scrollView.contentSize.height) {
        //Bottom of tableView
        colors = @[(__bridge id)outerColor, (__bridge id)innerColor,
                   (__bridge id)innerColor, (__bridge id)innerColor];
    } else {
        //Middle
        colors = @[(__bridge id)outerColor, (__bridge id)innerColor,
                   (__bridge id)innerColor, (__bridge id)outerColor];
    }
    ((CAGradientLayer *)scrollView.layer.mask).colors = colors;

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

再说一遍:大部分解决方案来自教程的 cocoanetics。

于 2014-01-21T15:22:43.167 回答
6

这是 Aviel Gross 对 Swift 的回答的翻译

import UIKit

class mViewController: UIViewController, UIScrollViewDelegate {

    //Emitted boilerplate code

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        if self.tableView.layer.mask == nil {

            //If you are using auto layout
            //self.view.layoutIfNeeded()

            let maskLayer: CAGradientLayer = CAGradientLayer()

            maskLayer.locations = [0.0, 0.2, 0.8, 1.0]
            let width = self.tableView.frame.size.width
            let height = self.tableView.frame.size.height
            maskLayer.bounds = CGRect(x: 0.0, y: 0.0, width: width, height: height)
            maskLayer.anchorPoint = CGPoint.zero

            self.tableView.layer.mask = maskLayer
        }

        scrollViewDidScroll(self.tableView)
    }

    func scrollViewDidScroll(_ scrollView: UIScrollView) {

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

        var colors = [CGColor]()

        if scrollView.contentOffset.y + scrollView.contentInset.top <= 0 {
            colors = [innerColor, innerColor, innerColor, outerColor]
        } else if scrollView.contentOffset.y + scrollView.frame.size.height >= scrollView.contentSize.height {
            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()
        }

    }

    //Emitted boilerplate code
}
于 2016-07-14T15:07:17.377 回答
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 回答