带圆角的翻转UIView

4

我尝试翻转一个带有圆角(边框)的视图。

Rounded Corners

视图的圆角实现方式如下:
  private extension UIView {

  func round(corners: UIRectCorner, radius: CGFloat, borderColor: UIColor, borderWidth: CGFloat) {
    let mask = _round(corners: corners, radius: radius)
    addBorder(mask: mask, borderColor: borderColor, borderWidth: borderWidth)
}

        @discardableResult func _round(corners: UIRectCorner, radius: CGFloat) -> CAShapeLayer {
            let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            self.layer.mask = mask
            return mask
        }

        func addBorder(mask: CAShapeLayer, borderColor: UIColor, borderWidth: CGFloat) {
            let borderLayer = CAShapeLayer()
            borderLayer.path = mask.path
            borderLayer.fillColor = UIColor.clear.cgColor
            borderLayer.strokeColor = borderColor.cgColor
            borderLayer.lineWidth = borderWidth
            borderLayer.frame = bounds
            layer.addSublayer(borderLayer)
        }

    }

翻转效果由以下代码实现:

UIView.transition(with: self, duration: 0.5, options: [.transitionFlipFromRight], animations: {}, completion: {_ in })

在翻转过程中,当转换正在运行时,边框不再呈圆角状态。

enter image description here

请问有人知道如何实现翻转效果,而不会失去圆角呢?

更新

如果我采用this的方法,我会遇到几个问题。

现在翻转是这样实现的:

  let flipAnimation = CABasicAnimation(keyPath: "transform")
        flipAnimation.fromValue = NSValue(caTransform3D: CATransform3DIdentity)
        flipAnimation.toValue = NSValue(caTransform3D: CATransform3DMakeRotation(.pi, 0,1,0))
        flipAnimation.fillMode = kCAFillModeBoth

        self.layer.add(flipAnimation, forKey: "flip")
        self.layer.zPosition = -1000

        CATransaction.commit()

问题

  • 动画不如UIView.transition流畅
  • 效果会镜像视图上的内容——我不需要这个(见下图)
  • 旋转结束后不够精确,有时视图位置会错位(见下图)

Mirrored 7 on the view position of the view after rotation

更新:解决方案 我在有圆角的彩色视图周围添加了一个容器视图,并翻转了容器,而不是彩色视图。然后一切都正常工作了!


1
可能是如何在具有圆角的父视图中翻转非全屏UIView?的重复问题。 - agibson007
我更新了问题,谢谢你的提示。 - sialcasa
旋转后,您希望视图看起来如何? - agibson007
当动画正在运行时,我更改标签的内容和背景颜色,这样看起来元素的背面有另一种颜色和标签的另一种内容。但从技术上讲,翻转后你看到的仍然是同一面和同一标签。 - sialcasa
如果你能等一下,我有东西给你。当绿色视图旋转时,你是在更新标签还是在它旋转时产生新值? - agibson007
在 UIView.transition / CATransaction.commit() 之后直接使用,但是当视图为90度线时,它看起来像是值发生了变化。 - sialcasa
2个回答

4

我的建议是将要翻转的视图添加到一个清晰的视图中,然后翻转它的父视图。我认为这与层被重新渲染有关,但不确定。这里有一个使用CATransition的工作示例,但我猜其他方法也可以。

import UIKit

class ViewController: UIViewController {

    var label = UILabel()
    var flipper = UIView()
    var flipperContainer = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        flipperContainer = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
        flipperContainer.backgroundColor = .clear
        flipperContainer.center = self.view.center
        self.view.addSubview(flipperContainer)

        flipper = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
        flipper.backgroundColor = UIColor.green
        flipper.round(corners: [UIRectCorner.topLeft,UIRectCorner.topRight], radius: 6, borderColor: .white, borderWidth: 1)
        self.flipperContainer.addSubview(flipper)



        //add a label
        label = UILabel(frame: CGRect(x: 0, y: 0, width: flipper.bounds.width, height: flipper.bounds.height))
        label.textAlignment = .center
        label.center = flipper.center
        label.textColor = UIColor.white
        label.text = "7"

        flipper.addSubview(label)

        self.view.backgroundColor = UIColor.black


        let flipButton = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width - 20, height: 50))
        flipButton.center = flipperContainer.center
        flipButton.center.y = flipperContainer.center.y + flipperContainer.bounds.height/2 + 20
        flipButton.addTarget(self, action: #selector(ViewController.pressed(sender:)), for: .touchUpInside)
        flipButton.setTitle("Flip", for: .normal)
        flipButton.setTitleColor(.white, for: .normal)

        self.view.addSubview(flipButton)
    }

    func pressed(sender:UIButton) {

        let trans = CATransition()
        trans.duration = 1.0
        trans.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
        trans.type = "flip"
        trans.subtype = kCATransitionFromRight
        //perform flip but on container
        flipperContainer.layer.add(trans, forKey: nil)

        if flipper.backgroundColor == UIColor.green{
            flipper.backgroundColor = .blue
            label.text = "20"
        }else{
            flipper.backgroundColor = .green
            label.text = "7"
        }
    }

}

我正在使用您的扩展程序来实现圆角效果。我尝试复制您想要做的内容。


谢谢您指引我正确的方向!在彩色和圆角视图周围添加一个翻转容器就解决了问题。非常感谢! - sialcasa
@sialcasa 很高兴能帮到你。干杯! - agibson007
很棒的解决方案。我添加了父视图,现在它可以很好地工作。我确认这是正确的解决方案。 - Ariel Bogdziewicz

0
最简单的方法是将视图的背景设置为带有所需颜色、圆角的图像,而不是在代码中设置背景颜色并对其进行圆角处理。

这不是一个选项,因为元素的颜色必须随机生成。 - sialcasa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接