在 UICollectionView 的单元格之间绘制虚线
Drawing dotted line between the cells of UICollectionView
我必须实现这样的目标(请查看随附的屏幕截图)。我想到的最佳解决方案是 UICollectionView
。我沿着单元格创建了圆形边框,并在单元格上放置了一个按钮。现在对于虚线直线,我使用 CAShapeLayer
和 BezierPath
并将图层添加到我的 collectionview background with background color set to clear color
。问题来了,我没有看到任何虚线。这是我试过的。现在我有几个问题。回答时请考虑我是初学者。
1) 为什么我的线条没有显示。
2)如何计算两个单元格之间的宽度,我现在设置一个随机数。
3)是否有任何其他方法可以更有效地解决这个用例。
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UIBezierPath *borderPath;
CGFloat borderWidth;
KKCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"testCell" forIndexPath:indexPath];
borderPath = [UIBezierPath bezierPath];
[borderPath moveToPoint:CGPointMake(cell.frame.origin.x + cell.frame.size.width -1 , cell.frame.origin.y + 2)];
[borderPath addLineToPoint:CGPointMake(cell.frame.origin.x + cell.frame.size.width + 50, cell.frame.origin.y +2)];
borderWidth = 1.0;
[self dottedLineWithPath:borderPath withborderWidth:borderWidth];
return cell;
}
/** creating dotted line **/
- (void)dottedLineWithPath:(UIBezierPath *)path withborderWidth:(CGFloat)lineWidth
{
CAShapeLayer *shapelayer = [CAShapeLayer layer];
shapelayer.strokeStart = 0.0;
shapelayer.strokeColor = [UIColor blackColor].CGColor;
shapelayer.lineWidth = borderWidth;
shapelayer.lineJoin = kCALineJoinRound;
shapelayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:2 ], nil];
shapelayer.path = path.CGPath;
[self.milestoneCollection.backgroundView.layer addSublayer:shapelayer];
}
这是我到目前为止所取得的成就。
Why my lines are not showing.
要让绘图可见,您必须将绘图代码直接添加到 UICollectionView
实例,而不是 backgroundView
属性.
[self.milestoneCollection.layer addSublayer:shapelayer];
这 100% 有效。使用 backgroundView
似乎是正确的做法,但他们可能将其用于完全不同的用途。我怀疑 backgroundView
目前不可见(使用默认配置)或完全忽略我们的更改请求。
How to calculate the width between the two cell, right now i am setting a random number.
-(void)getLineStartPoint:(CGPoint*)startPoint
andEndPoint:(CGPoint*)endPoint
fromCellAtIndexPath:(NSIndexPath*)fromIndexPath
toCellAtIndexPath:(NSIndexPath*)toIndexPath
{
UICollectionViewLayoutAttributes* fromAttributes =
[self.milestoneCollection layoutAttributesForItemAtIndexPath:fromIndexPath];
UICollectionViewLayoutAttributes* toAttributes =
[self.milestoneCollection layoutAttributesForItemAtIndexPath:toIndexPath];
*startPoint = fromAttributes.center;
*endPoint = toAttributes.center;
}
UICollectionViewLayoutAttributes
是在特定 indexPath
处 100% 富含关于 cells, headers, footers, decorationViews
的几何信息的特征。为简单起见,我现在使用 center
。我相信您需要将您的逻辑与 frame
属性.
一起使用
Is there any other approach, which can solve this use-case more efficiently.
是的,总有两种方法。
- 完成它。
- 完成正确。
当然RIGHT根据情况和可用时间不同
牢记
请注意 indexPath
可用性,否则您很容易崩溃。这是一个最简单的守卫形式-
NSInteger numberOfItems = [self collectionView:collectionView numberOfItemsInSection:indexPath.section];
if(indexPath.item < numberOfItems-1)
{
CGPoint startPoint, endPoint;
NSIndexPath* toIndexPath =
[NSIndexPath indexPathForItem:indexPath.item+1 inSection:indexPath.section];
[self getLineStartPoint:&startPoint
andEndPoint:&endPoint
fromCellAtIndexPath:indexPath
toCellAtIndexPath:toIndexPath];
[borderPath moveToPoint:startPoint];
[borderPath addLineToPoint:endPoint];
borderWidth = 1.0;
[self dottedLineWithPath:borderPath withborderWidth:borderWidth];
}
此外,当您尝试滚动它时(如果需要),添加 layers/paths
每次创建单元格时(由于
多次添加层级),你需要小心
重用细胞时的这一点。看看这个:-
这应该可以回答您的所有问题。祝你好运!!
您好,您使用 UICollectionViewLayout
和绘制函数完成了这项工作。
代码上传路径 https://github.com/arunpkumar92/OrderStatusCollectionView
- (void)reloadConnections{
for (CAShapeLayer *shapelayer in self.connectionLines) {
[shapelayer removeFromSuperlayer];
}
self.connectionLines = [NSMutableArray array];
for (int i = 0; i <= (self.total-2); i++){
NSArray *paths = [self pathForconnectionLineForIndexPath:i];
for (UIBezierPath *path in paths) {
UIColor *color = (self.currentLevel > i) ? [UIColor colorWithRed:0.078 green:0.557 blue:0.067 alpha:1.00] : [UIColor colorWithRed:0.957 green:0.659 blue:0.024 alpha:1.00];
CAShapeLayer *shapelayer = [self drawdottedLineWithPath:path withborderWidth:1.0f withColor:color];
[self.collectionView.layer addSublayer:shapelayer];
[self.connectionLines addObject:shapelayer];
}
}
}
- (NSArray *)pathForconnectionLineForIndexPath:(int)index{
NSMutableArray *paths = [NSMutableArray array];
int row = index%self.noOfItems;
int column = index/self.noOfItems;
CGFloat cellWidth = self.view.frame.size.width/self.noOfItems;
CGFloat cellHeight = self.view.frame.size.width/self.noOfItems;
CGFloat connectionLength = cellHeight/2;
CGFloat leftPadding;
CGFloat topPadding;
if (row != (self.noOfItems-1)) {
leftPadding = cellWidth/4;
topPadding = cellHeight/2;
UIBezierPath *borderPath = [UIBezierPath bezierPath];
CGFloat startX = (3*leftPadding)+(row*cellWidth);
CGFloat startY = topPadding+(column*cellHeight);
CGFloat endX = startX + connectionLength;
CGFloat endY = startY;
[borderPath moveToPoint:CGPointMake(startX , startY)];
[borderPath addLineToPoint:CGPointMake(endX, endY)];
[self drawDirectionAt:CGPointMake((startX+(connectionLength/2)) , startY) isEnabled:(self.currentLevel > index) isRight:YES];
[paths addObject:borderPath];
}
if ( (row == (self.noOfItems-1)) && (column%2 == 0) ) {
leftPadding = cellWidth/2;
topPadding = cellHeight/8;
UIBezierPath *borderPath = [UIBezierPath bezierPath];
CGFloat startX = leftPadding+(row*cellWidth);
CGFloat startY = (7*topPadding)+(column*cellHeight);
CGFloat endX = startX;
CGFloat endY = startY + (2*topPadding);
[borderPath moveToPoint:CGPointMake(startX , startY)];
[borderPath addLineToPoint:CGPointMake(endX, endY)];
[self drawDirectionAt:CGPointMake(startX , (startY+topPadding)) isEnabled:(self.currentLevel > index) isRight:NO];
[paths addObject:borderPath];
}
if ( (row == 0) && (column%2 != 0) ) {
leftPadding = cellWidth/2;
topPadding = cellHeight/8;
UIBezierPath *borderPath = [UIBezierPath bezierPath];
CGFloat startX = leftPadding+(row*cellWidth);
CGFloat startY = (7*topPadding)+(column*cellHeight);
CGFloat endX = startX;
CGFloat endY = startY + (2*topPadding);
[borderPath moveToPoint:CGPointMake(startX , startY)];
[borderPath addLineToPoint:CGPointMake(endX, endY)];
[self drawDirectionAt:CGPointMake(startX , (startY+topPadding)) isEnabled:(self.currentLevel > index) isRight:NO];
[paths addObject:borderPath];
}
return paths;
}
- (CAShapeLayer *)drawdottedLineWithPath:(UIBezierPath *)path withborderWidth:(CGFloat)lineWidth withColor: (UIColor *)color
{
CAShapeLayer *shapelayer = [CAShapeLayer layer];
shapelayer.strokeStart = 0.0;
shapelayer.strokeColor = color.CGColor;
shapelayer.lineWidth = lineWidth;
shapelayer.lineJoin = kCALineJoinRound;
shapelayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:15],[NSNumber numberWithInt:10 ], nil];
shapelayer.path = path.CGPath;
return shapelayer;
}
- (void)drawDirectionAt:(CGPoint)point isEnabled:(BOOL)enabled isRight:(BOOL)isRight{
NSString *imageName;
imageName = isRight ? @"right-arrow" : @"down-arrow";
imageName = [NSString stringWithFormat:@"%@-%@",imageName,(enabled ? @"enabled" : @"disabled")];
CAShapeLayer* direction = [CAShapeLayer layer];
direction.opacity = 1.0;
direction.frame = CGRectMake(0, 0, 16, 16);
direction.position = point;
[direction setContents:(id)[[UIImage imageNamed: imageName] CGImage]];
[self.connectionLines addObject:direction];
[self.collectionView.layer addSublayer: direction];
}
我必须实现这样的目标(请查看随附的屏幕截图)。我想到的最佳解决方案是 UICollectionView
。我沿着单元格创建了圆形边框,并在单元格上放置了一个按钮。现在对于虚线直线,我使用 CAShapeLayer
和 BezierPath
并将图层添加到我的 collectionview background with background color set to clear color
。问题来了,我没有看到任何虚线。这是我试过的。现在我有几个问题。回答时请考虑我是初学者。
1) 为什么我的线条没有显示。
2)如何计算两个单元格之间的宽度,我现在设置一个随机数。
3)是否有任何其他方法可以更有效地解决这个用例。
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
UIBezierPath *borderPath;
CGFloat borderWidth;
KKCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"testCell" forIndexPath:indexPath];
borderPath = [UIBezierPath bezierPath];
[borderPath moveToPoint:CGPointMake(cell.frame.origin.x + cell.frame.size.width -1 , cell.frame.origin.y + 2)];
[borderPath addLineToPoint:CGPointMake(cell.frame.origin.x + cell.frame.size.width + 50, cell.frame.origin.y +2)];
borderWidth = 1.0;
[self dottedLineWithPath:borderPath withborderWidth:borderWidth];
return cell;
}
/** creating dotted line **/
- (void)dottedLineWithPath:(UIBezierPath *)path withborderWidth:(CGFloat)lineWidth
{
CAShapeLayer *shapelayer = [CAShapeLayer layer];
shapelayer.strokeStart = 0.0;
shapelayer.strokeColor = [UIColor blackColor].CGColor;
shapelayer.lineWidth = borderWidth;
shapelayer.lineJoin = kCALineJoinRound;
shapelayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:1],[NSNumber numberWithInt:2 ], nil];
shapelayer.path = path.CGPath;
[self.milestoneCollection.backgroundView.layer addSublayer:shapelayer];
}
这是我到目前为止所取得的成就。
Why my lines are not showing.
要让绘图可见,您必须将绘图代码直接添加到 UICollectionView
实例,而不是 backgroundView
属性.
[self.milestoneCollection.layer addSublayer:shapelayer];
这 100% 有效。使用 backgroundView
似乎是正确的做法,但他们可能将其用于完全不同的用途。我怀疑 backgroundView
目前不可见(使用默认配置)或完全忽略我们的更改请求。
How to calculate the width between the two cell, right now i am setting a random number.
-(void)getLineStartPoint:(CGPoint*)startPoint
andEndPoint:(CGPoint*)endPoint
fromCellAtIndexPath:(NSIndexPath*)fromIndexPath
toCellAtIndexPath:(NSIndexPath*)toIndexPath
{
UICollectionViewLayoutAttributes* fromAttributes =
[self.milestoneCollection layoutAttributesForItemAtIndexPath:fromIndexPath];
UICollectionViewLayoutAttributes* toAttributes =
[self.milestoneCollection layoutAttributesForItemAtIndexPath:toIndexPath];
*startPoint = fromAttributes.center;
*endPoint = toAttributes.center;
}
UICollectionViewLayoutAttributes
是在特定 indexPath
处 100% 富含关于 cells, headers, footers, decorationViews
的几何信息的特征。为简单起见,我现在使用 center
。我相信您需要将您的逻辑与 frame
属性.
Is there any other approach, which can solve this use-case more efficiently.
是的,总有两种方法。
- 完成它。
- 完成正确。
当然RIGHT根据情况和可用时间不同
牢记
请注意
indexPath
可用性,否则您很容易崩溃。这是一个最简单的守卫形式-NSInteger numberOfItems = [self collectionView:collectionView numberOfItemsInSection:indexPath.section]; if(indexPath.item < numberOfItems-1) { CGPoint startPoint, endPoint; NSIndexPath* toIndexPath = [NSIndexPath indexPathForItem:indexPath.item+1 inSection:indexPath.section]; [self getLineStartPoint:&startPoint andEndPoint:&endPoint fromCellAtIndexPath:indexPath toCellAtIndexPath:toIndexPath]; [borderPath moveToPoint:startPoint]; [borderPath addLineToPoint:endPoint]; borderWidth = 1.0; [self dottedLineWithPath:borderPath withborderWidth:borderWidth]; }
此外,当您尝试滚动它时(如果需要),添加 layers/paths 每次创建单元格时(由于 多次添加层级),你需要小心 重用细胞时的这一点。看看这个:-
这应该可以回答您的所有问题。祝你好运!!
您好,您使用 UICollectionViewLayout
和绘制函数完成了这项工作。
代码上传路径 https://github.com/arunpkumar92/OrderStatusCollectionView
- (void)reloadConnections{
for (CAShapeLayer *shapelayer in self.connectionLines) {
[shapelayer removeFromSuperlayer];
}
self.connectionLines = [NSMutableArray array];
for (int i = 0; i <= (self.total-2); i++){
NSArray *paths = [self pathForconnectionLineForIndexPath:i];
for (UIBezierPath *path in paths) {
UIColor *color = (self.currentLevel > i) ? [UIColor colorWithRed:0.078 green:0.557 blue:0.067 alpha:1.00] : [UIColor colorWithRed:0.957 green:0.659 blue:0.024 alpha:1.00];
CAShapeLayer *shapelayer = [self drawdottedLineWithPath:path withborderWidth:1.0f withColor:color];
[self.collectionView.layer addSublayer:shapelayer];
[self.connectionLines addObject:shapelayer];
}
}
}
- (NSArray *)pathForconnectionLineForIndexPath:(int)index{
NSMutableArray *paths = [NSMutableArray array];
int row = index%self.noOfItems;
int column = index/self.noOfItems;
CGFloat cellWidth = self.view.frame.size.width/self.noOfItems;
CGFloat cellHeight = self.view.frame.size.width/self.noOfItems;
CGFloat connectionLength = cellHeight/2;
CGFloat leftPadding;
CGFloat topPadding;
if (row != (self.noOfItems-1)) {
leftPadding = cellWidth/4;
topPadding = cellHeight/2;
UIBezierPath *borderPath = [UIBezierPath bezierPath];
CGFloat startX = (3*leftPadding)+(row*cellWidth);
CGFloat startY = topPadding+(column*cellHeight);
CGFloat endX = startX + connectionLength;
CGFloat endY = startY;
[borderPath moveToPoint:CGPointMake(startX , startY)];
[borderPath addLineToPoint:CGPointMake(endX, endY)];
[self drawDirectionAt:CGPointMake((startX+(connectionLength/2)) , startY) isEnabled:(self.currentLevel > index) isRight:YES];
[paths addObject:borderPath];
}
if ( (row == (self.noOfItems-1)) && (column%2 == 0) ) {
leftPadding = cellWidth/2;
topPadding = cellHeight/8;
UIBezierPath *borderPath = [UIBezierPath bezierPath];
CGFloat startX = leftPadding+(row*cellWidth);
CGFloat startY = (7*topPadding)+(column*cellHeight);
CGFloat endX = startX;
CGFloat endY = startY + (2*topPadding);
[borderPath moveToPoint:CGPointMake(startX , startY)];
[borderPath addLineToPoint:CGPointMake(endX, endY)];
[self drawDirectionAt:CGPointMake(startX , (startY+topPadding)) isEnabled:(self.currentLevel > index) isRight:NO];
[paths addObject:borderPath];
}
if ( (row == 0) && (column%2 != 0) ) {
leftPadding = cellWidth/2;
topPadding = cellHeight/8;
UIBezierPath *borderPath = [UIBezierPath bezierPath];
CGFloat startX = leftPadding+(row*cellWidth);
CGFloat startY = (7*topPadding)+(column*cellHeight);
CGFloat endX = startX;
CGFloat endY = startY + (2*topPadding);
[borderPath moveToPoint:CGPointMake(startX , startY)];
[borderPath addLineToPoint:CGPointMake(endX, endY)];
[self drawDirectionAt:CGPointMake(startX , (startY+topPadding)) isEnabled:(self.currentLevel > index) isRight:NO];
[paths addObject:borderPath];
}
return paths;
}
- (CAShapeLayer *)drawdottedLineWithPath:(UIBezierPath *)path withborderWidth:(CGFloat)lineWidth withColor: (UIColor *)color
{
CAShapeLayer *shapelayer = [CAShapeLayer layer];
shapelayer.strokeStart = 0.0;
shapelayer.strokeColor = color.CGColor;
shapelayer.lineWidth = lineWidth;
shapelayer.lineJoin = kCALineJoinRound;
shapelayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:15],[NSNumber numberWithInt:10 ], nil];
shapelayer.path = path.CGPath;
return shapelayer;
}
- (void)drawDirectionAt:(CGPoint)point isEnabled:(BOOL)enabled isRight:(BOOL)isRight{
NSString *imageName;
imageName = isRight ? @"right-arrow" : @"down-arrow";
imageName = [NSString stringWithFormat:@"%@-%@",imageName,(enabled ? @"enabled" : @"disabled")];
CAShapeLayer* direction = [CAShapeLayer layer];
direction.opacity = 1.0;
direction.frame = CGRectMake(0, 0, 16, 16);
direction.position = point;
[direction setContents:(id)[[UIImage imageNamed: imageName] CGImage]];
[self.connectionLines addObject:direction];
[self.collectionView.layer addSublayer: direction];
}