淡化UITableView的边缘

时间:2012-05-13 08:13:13

标签: ios uitableview uiscrollview fade

我对我的问题进行了一些研究,遗憾的是我的问题没有解决方案。 最接近的是Fade UIImageView as it approaches the edges of a UIScrollView,但它仍然不适合我。

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

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

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

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

此致

4 个答案:

答案 0 :(得分:14)

我参加了this教程并进行了一些更改和补充:

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

1。首先导入QuartzCore 并在控制器中设置遮罩层

编辑:无需在课堂上引用CAGradientLayer

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

@interface mViewController : UIViewController
.
.
@end

2。将此添加到 viewWillAppear viewDidLayoutSubviews请参阅@ Darren对此内容的评论

- (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> 的代表:

scrollViewDidScroll

4. 要完成,请在您的控制器.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]; }

{{1}}

再次:大部分解决方案来自cocoanetics中的this教程。

答案 1 :(得分:5)

这是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 // Swift 3.0 update

            self.tableView.layer.mask = maskLayer
        }

        scrollViewDidScroll(self.tableView)
    }

    // Swift 3.0 update
    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 = [AnyObject]()

        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]
        }

        (scrollView.layer.mask as! CAGradientLayer).colors = colors


        CATransaction.begin()
        CATransaction.setDisableActions(true)
        scrollView.layer.mask?.position = CGPoint(x: 0.0, y: scrollView.contentOffset.y)
        CATransaction.commit()
    }

    //Emitted boilerplate code
}

答案 2 :(得分:4)

这是我继承UITableView的淡化表视图的版本。经过iOS 7&amp; S测试8。

  1. 无需实现scrollViewDidScroll,可以使用layoutSubviews。
  2. 通过观察边界变化,掩模是 旋转变化时始终正确放置。
  3. 您可以使用百分比参数来更改边缘所需的渐变量,I 在某些情况下找到一个看起来更好的小值。
  4. <强> 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
    

答案 3 :(得分:3)

Swift 3版@ victorfigol的出色解决方案:

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

  fileprivate let outerColor = UIColor(white: 1.0, alpha: 0.0).cgColor
  fileprivate 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 = [AnyObject]()

    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()
     }
  }
}