【问题标题】:Workaround for rounded corners of grouped UITableView, iOS7 [duplicate]分组UITableView,iOS7圆角的解决方法[重复]
【发布时间】:2013-10-11 03:42:01
【问题描述】:

自 iOS7 推出以来,UITableView 的分组样式单元格的圆角已被 Apple (confirmed here) 移除。不过,我相信肯定有聪明人为此制定了解决方法。

为了帮助我和许多其他 iOS 程序员,请在此线程中发布您的解决方法,以便为 iOS7 中的 UITableViewStyleGrouped 中的单元格获得圆角。将不胜感激!

【问题讨论】:

  • 您对这些答案有何看法?
  • @RobertoFerraz 我还没有时间尝试你的答案。我喜欢您的解决方案的想法,但我想在投票或将其标记为解决方案之前对其进行测试。很抱歉,但请理解我的好意。

标签: ios uitableview ios7


【解决方案1】:

您可以使用 UIImageView 并像这样设置圆角半径:

CALayer * l = [self.cellBackgroundImage layer];
[l setMasksToBounds:YES];
[l setCornerRadius:5.0];

要使用它,您应该导入 quarts core:

#import <QuartzCore/QuartzCore.h>

【讨论】:

  • 不适用于分组单元格。
【解决方案2】:

考虑到您的表格中可以有多个组,一些单元格在顶角是四舍五入的,其他的只是在底部,还有一些不是四舍五入的。所以我在这里用以下方法非常快地创建了一个 UITableViewCell 的子类(可以真正缩短):

一个你可以任意调用的属性,我称之为top和bottom:

@property(nonatomic,assign) BOOL top,bottom;

实现:

- (void)layoutSubviews
{
    [super layoutSubviews];

    if(self.top && self.bottom)
    {
        self.layer.cornerRadius = 10;
        self.layer.masksToBounds = YES;
        return;
    }

    if (self.top)
    {
        CAShapeLayer *shape = [[CAShapeLayer alloc] init];
        shape.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height) byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:CGSizeMake(10, 10)].CGPath;
        self.layer.mask = shape;
        self.layer.masksToBounds = YES;
        return;
    }

    if (self.bottom)
    {
        CAShapeLayer *shape = [[CAShapeLayer alloc] init];
        shape.path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height) byRoundingCorners:UIRectCornerBottomLeft|UIRectCornerBottomRight cornerRadii:CGSizeMake(10, 10)].CGPath;
        self.layer.mask = shape;
        self.layer.masksToBounds = YES;
    }
}

在 Swift 4.2 中:

class MyCell: UITableViewCell {

var top = false
var bottom = false

override func layoutSubviews() {
    super.layoutSubviews()

    if top && bottom {
        layer.cornerRadius = 10
        layer.masksToBounds = true
        return
    }

    let shape = CAShapeLayer()
    let rect = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.size.height)
    let corners: UIRectCorner = self.top ? [.topLeft, .topRight] : [.bottomRight, .bottomLeft]

    shape.path = UIBezierPath(roundedRect: rect, byRoundingCorners: corners, cornerRadii: CGSize(width: 10, height: 10)).cgPath
    layer.mask = shape
    layer.masksToBounds = true
  }
}

使用很简单,如果你的单元格是组中的第一个,则设置top = True,如果是最后一个单元格,则设置bottom = true,如果该单元格是组中唯一的单元格,则都设置为true

如果您想要或多或少四舍五入,只需将单选数从 10 更改为另一个值。

【讨论】:

    【解决方案3】:

    这是对 Roberto Ferraz 的略微改进的答案。

    它会为您计算出顶部和底部的单元格(假设单元格之间没有间隙)。

    它还使用了 remove borders from group 的技巧,适用于 iOS7

    @interface CustomTableViewCell : UITableViewCell
    

    覆盖消息:

    #define radius 10
    
    - (void)layoutSubviews {
        [super layoutSubviews];
    
        CGRect frame = self.frame;
        CGFloat top = frame.origin.y;
        CGFloat bottom = top + frame.size.height;
        UIRectCorner corners = UIRectCornerAllCorners;
        CAShapeLayer* mask = [CAShapeLayer layer];
    
        for (UIView* view in self.superview.subviews) {
            if (view.frame.origin.y + view.frame.size.height == top) {
                corners = corners & ~(UIRectCornerTopLeft|UIRectCornerTopRight);
            } else if (view.frame.origin.y == bottom) {
                corners = corners & ~(UIRectCornerBottomLeft|UIRectCornerBottomRight);
            }
        }
    
        mask.path = [UIBezierPath bezierPathWithRoundedRect:
                     CGRectMake(0, 0, frame.size.width, frame.size.height)
                                          byRoundingCorners:corners
                                cornerRadii:CGSizeMake(radius, radius)].CGPath;
    
        self.layer.mask = mask;
        self.layer.masksToBounds = YES;
    }
    
    /*
     iOS 7 workaround to get rid of top and bottom separators
    */
    - (void) addSubview:(UIView*)view {
        if (view.frame.origin.x > 0 || view.frame.size.width < self.frame.size.width) {
            [super addSubview:view];
        }
    }
    

    【讨论】:

      【解决方案4】:

      只需在您的代码中添加以下 UITableView 委托方法。对于 iOS7 中的表格视图,它确实帮助我解决了与您相同的问题。试试下面的代码taken from this answer by jvanmetre,也许它也解决了你的问题:

      - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
      {
          if ([cell respondsToSelector:@selector(tintColor)]) {
              if (tableView == tblProfileDetails) {    // self.tableview
                  CGFloat cornerRadius = 5.f;
                  cell.backgroundColor = UIColor.clearColor;
                  CAShapeLayer *layer = [[CAShapeLayer alloc] init];
                  CGMutablePathRef pathRef = CGPathCreateMutable();
                  CGRect bounds = CGRectInset(cell.bounds, 5, 0);
                  BOOL addLine = NO;
                  if (indexPath.row == 0 && indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1) {
                      CGPathAddRoundedRect(pathRef, nil, bounds, cornerRadius, cornerRadius);
                  } else if (indexPath.row == 0) {
                      CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds));
                      CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds), CGRectGetMidX(bounds), CGRectGetMinY(bounds), cornerRadius);
                      CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
                      CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds));
                          addLine = YES;
                  } else if (indexPath.row == [tableView numberOfRowsInSection:indexPath.section]-1) {
                      CGPathMoveToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMinY(bounds));
                      CGPathAddArcToPoint(pathRef, nil, CGRectGetMinX(bounds), CGRectGetMaxY(bounds), CGRectGetMidX(bounds), CGRectGetMaxY(bounds), cornerRadius);
                      CGPathAddArcToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMaxY(bounds), CGRectGetMaxX(bounds), CGRectGetMidY(bounds), cornerRadius);
                      CGPathAddLineToPoint(pathRef, nil, CGRectGetMaxX(bounds), CGRectGetMinY(bounds));
                  } else {
                      CGPathAddRect(pathRef, nil, bounds);
                      addLine = YES;
                  }
                  layer.path = pathRef;
                  CFRelease(pathRef);
                  layer.fillColor = [UIColor colorWithWhite:1.f alpha:0.8f].CGColor;
      
                  if (addLine == YES) {
                      CALayer *lineLayer = [[CALayer alloc] init];
                      CGFloat lineHeight = (1.f / [UIScreen mainScreen].scale);
                      lineLayer.frame = CGRectMake(CGRectGetMinX(bounds)+5, bounds.size.height-lineHeight, bounds.size.width-5, lineHeight);
                      lineLayer.backgroundColor = tableView.separatorColor.CGColor;
                      [layer addSublayer:lineLayer];
                  }
                  UIView *testView = [[UIView alloc] initWithFrame:bounds];
                  [testView.layer insertSublayer:layer atIndex:0];
                  testView.backgroundColor = UIColor.clearColor;
                  cell.backgroundView = testView;
              }
          }
      }
      

      【讨论】:

      • 如果您要复制并粘贴 [来自其他用户答案的​​代码](stackoverflow.com/a/18833311/41116) 到另一个问题 - 至少要注明它。
      • 它帮助我解决了我的应用程序中的问题,正是出于这个原因,我将这段代码粘贴在这里。它真的很有帮助。
      • 这段代码有效。我还添加了 self.tableView.separatorColor = [UIColor clearColor];这是让它看起来不错的必要条件。
      • 很好的解决方案。但需要修复表格分隔符。
      • 谢谢!但是单击单元格时如何自定义背景?只想突出分组样式...
      猜你喜欢
      • 2014-03-29
      • 2013-06-19
      • 1970-01-01
      • 2013-11-09
      • 1970-01-01
      • 2016-01-02
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多