0

I have a CAShapeLayer (below) which is used to draw a bubble. Which all works fine, as per designs but when i start resizing it within a tableView with tableView.beginUpdates() and tableView.endUpdates(). I end up having the old layer in black momentarily. which is looks awful. I am really puzzled on how to solve this. It kinda feels that layers are black, and the fill paints over them like a mask. I have tried several things as to add/removing the layer in different places. etc. but result is always this.

video to describe it

override func draw(_ rect: CGRect) {
  self.layer.backgroundColor = UIColor.clear.cgColor
  let fillColor: UIColor = self.shapeColor

  let shapeLayer = CAShapeLayer()
  shapeLayer.contentsScale = UIScreen.main.scale

  let path = UIBezierPath()
  shapeLayer.fillColor = fillColor.cgColor

  let width = self.bounds.size.width
  let height = self.bounds.size.height

  path.move(to: CGPoint(x: 3.02, y: height * 0.5))
  path.move(to: CGPoint(x: 3.02, y: 24.9))
  path.addLine(to: CGPoint(x: 3.02, y: 14.62))
  path.addLine(to: CGPoint(x: 3.02, y: 14.62))
  path.addCurve(to: CGPoint(x: 17.64, y: -0), controlPoint1: CGPoint(x: 3.02, y: 6.55),controlPoint2: CGPoint(x: 9.57, y: -0))
  path.addLine(to: CGPoint(x: width - 15.85, y: 0))
  path.addLine(to: CGPoint(x: width - 15.85, y: 0))
  path.addCurve(to: CGPoint(x: width, y: 14.62), controlPoint1: CGPoint(x: width - 7.77, y: 0), controlPoint2: CGPoint(x: width, y: 6.55))
  path.addLine(to: CGPoint(x: width, y: height - 15.1))
  path.addLine(to: CGPoint(x: width, y: height - 15.1))
  path.addCurve(to: CGPoint(x: width - 15.85, y: height), controlPoint1: CGPoint(x: width, y: height - 7.03), controlPoint2: CGPoint(x: width - 7.77, y: height))
  path.addLine(to: CGPoint(x: 17.64, y: height))
  path.addLine(to: CGPoint(x: 17.64, y: height))
  path.addCurve(to: CGPoint(x: 8.69, y: height - 3.56), controlPoint1: CGPoint(x: 14.39, y: height),controlPoint2: CGPoint(x: 11.24, y: height - 1.57))
  path.addLine(to: CGPoint(x: 8.79, y: height - 3.46))
  path.addCurve(to: CGPoint(x: 0, y: height), controlPoint1: CGPoint(x: 7.27, y: height - 1.27), controlPoint2: CGPoint(x: 3.84, y: height + 0.51))
  path.addCurve(to: CGPoint(x: 3.02, y: height - 14.1), controlPoint1: CGPoint(x: 4.06, y: height - 4.22), controlPoint2: CGPoint(x: 3.02, y: height - 9.62))
  path.close()

  if self.reverted {
    let mirrorOverXOrigin: CGAffineTransform = CGAffineTransform(scaleX: -1.0, y: 1.0);
    let translate: CGAffineTransform = CGAffineTransform(translationX: width, y: 0);

    // Apply these transforms to the path
    path.apply(mirrorOverXOrigin)
    path.apply(translate)
  }

  path.fill()

  shapeLayer.path = path.cgPath
  shapeLayer.rasterizationScale = UIScreen.main.scale
  shapeLayer.shouldRasterize = true

  if let bubbleLayer = self.bubbleLayer {
    self.layer.replaceSublayer(bubbleLayer, with: shapeLayer)
  } else {
    self.layer.insertSublayer(shapeLayer, at: 0)
  }
  self.bubbleLayer = shapeLayer
 }

 shapeLayer.path = path.cgPath
 shapeLayer.rasterizationScale = UIScreen.main.scale
 shapeLayer.shouldRasterize = true

 self.layer.insertSublayer(shapeLayer, at: 0)
 self.bubbleLayer?.removeFromSuperlayer()
 self.bubbleLayer = shapeLayer
}
RicardoDuarte
  • 728
  • 7
  • 23

1 Answers1

0

your solution cannot work. Draw(_ :) is not called during animation block. It is draw after tableView.endUpdates(), after UITableView ends animation.

Draw(_ :) - I don't think you should use it for your needs at all.

If I can recommend you some solution:

1) In awakeFromNib:

override func awakeFromNib() {
    super.awakeFromNib()

    self.contentView.backgroundColor = self.shapeColor
    self.contentView.layer.cornerRadius = 15

    /** make  left view and attach it to the left bottom anchors with fixed size and draw into this view the shape of your left arrow***/
    self.leftArrowView.isHidden = self.isReverted
    /** make  right view and attach it to the right bottom anchors with fixed size and draw into this view the shape of your right arrow***/
    self.rightArrowView.isHidden = !self.isReverted
}

2) In prepareForReuse:

override func prepareForReuse() {
    super.prepareForReuse()
    self.leftArrowView.isHidden = self.isReverted
    self.rightArrowView.isHidden = !self.isReverted
}

And this should cause your cell will change size smoothly.

Lukáš Mareda
  • 331
  • 2
  • 7
  • Sorry only today i had a chance to test this. I just tried this and i am still having the same issue. its not the arrow that is a problem, is when the height of the cells changes. Its animating that, or getting rid of the black shape. (did you see the video as it hard to explain) – RicardoDuarte Feb 07 '20 at 13:36