2017-03-03 15 views
3

흥미로운 문제가 있지만 해결 방법을 모르겠습니다. @IBInspectable로 UIView를 확장하려고합니다. 그러나이 방법을 사용하면 모서리 반경은 뷰의 실제 크기가 아닌 기본 파일면에서 설정되는 것처럼 보입니다.원형 UIView 전체 원형이 아님

IB에서 "View as"를 iPhoneSE로 설정하고 iPhoneSE 용으로 빌드하면보기가 원입니다. 그러나 iPhone7 용으로 제작하면 모서리가 완전히 둥글어지지 않습니다. 반대로, iPhone7에 "보기 모드"를 설정하고 iPhone7 용으로 빌드하면 뷰는 원입니다. 그러나 iPhoneSE 용으로 빌드하면 모서리가 둥글게됩니다.

사진 아래 코드 :

확장

extension UIView { 

    @IBInspectable var cornerRadius:Double { 
     get { 
      return Double(layer.cornerRadius) 
     } 
     set { 
      layer.cornerRadius = CGFloat(newValue) 
      layer.masksToBounds = newValue > 0 
     } 
    } 

    @IBInspectable var circleView:Bool { 
     get { 
      return layer.cornerRadius == min(self.frame.width, self.frame.height)/CGFloat(2.0) ? true : false 
     } 
     set { 
      if newValue { 
       layer.cornerRadius = min(self.frame.width, self.frame.height)/CGFloat(2.0) 
       layer.masksToBounds = true 
      } 
      else{ 
       layer.cornerRadius = 0.0 
       layer.masksToBounds = false 
      } 
     } 
    } 

} 

"보기로"IB

에 iPhoneSE로 아이폰 7 iPhoneSE

enter image description here

구축을위한 설계

설정

enter image description here

"보기로"iPhone7로 설정

빌드 아이폰 7

enter image description here

IB 설정 아이폰 SE

enter image description here

빌드에 대한 enter image description here enter image description here

+0

원형 UIView가 IB로 선택된 경우 자동 레이아웃 설정과 스크린 샷을 캡쳐 할 수 있습니까? –

+0

@SamuelTulach 위의 내용을 추가했습니다. – steventnorris

답변

2

보기가 정사각형 인 경우에만 전체 원이 생깁니다.

보기가 직사각형이고 가장 작은 치수의 절반보다 작은 값으로 cornerRadius을 설정하면 두 번째보기가 표시되고 그 값보다 큰 경우 다이아몬드 모양의 값이 표시됩니다.

제약 조건을 확인하고 viewDidLayout에보기 완료 레이아웃을 작성한 후 cornerRadius을 계산하여 정확한 크기를 얻으십시오. 여기

이를 보여주는 놀이터입니다 (더 나은 문제를 보여주는 애니메이션 추가 한) : 당신은 185.5로 폭과 높이를 언급

import UIKit 
import PlaygroundSupport 

extension UIView 
{ 
    func addCornerRadiusAnimation(from: CGFloat, to: CGFloat, duration: CFTimeInterval) 
    { 
    let animation = CABasicAnimation(keyPath:"cornerRadius") 
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 
    animation.fromValue = from 
    animation.toValue = to 
    animation.duration = duration 
    self.layer.add(animation, forKey: "cornerRadius") 
    self.layer.cornerRadius = to 
    } 
} 

let v = UIView(frame: CGRect(x: 0, y: 0, width: 350, height: 450)) 
PlaygroundPage.current.liveView = v 

let squareView = UIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100)) 
squareView.backgroundColor = .red 
squareView.layer.masksToBounds = true 
v.addSubview(squareView) 
var cornerRadius = CGFloat(0.5*min(squareView.frame.width, 
            squareView.frame.height)) 
squareView.addCornerRadiusAnimation(from: 0, to: cornerRadius, duration: 5) 

let rectangleView = UIView(frame: CGRect(x: 10, y: 200, width: 100, height: 200)) 
rectangleView.backgroundColor = .blue 
rectangleView.layer.masksToBounds = true 
v.addSubview(rectangleView) 
cornerRadius = CGFloat(0.5*min(rectangleView.frame.width, 
            rectangleView.frame.height)) 
rectangleView.addCornerRadiusAnimation(from: 0, to: cornerRadius, duration: 5) 

let diamondView = UIView(frame: CGRect(x: 200, y: 200, width: 100, height: 200)) 
diamondView.backgroundColor = .green 
diamondView.layer.masksToBounds = true 
v.addSubview(diamondView) 
cornerRadius = CGFloat(0.5*max(diamondView.frame.width, 
           diamondView.frame.height)) 
diamondView.addCornerRadiusAnimation(from: 0, to: cornerRadius, duration: 5) 

Playground output

+0

보기가 사각형입니다. 이 문제는 직각 성으로 보이지 않습니다.이 문제를 반올림하는 코드가 라이프 사이클에서 실행되는 것 같습니다. 보기를 완전히 배치하는 제약 조건보다 먼저 실행되므로 원형이 잘못되었습니다. – steventnorris

+0

@steventnorris 뷰가 완성 된 후 'cornerRadius' *를 계산해야하기 때문에 (내 대답에 있습니다). 빠른 해결책은'UIView'를 서브 클래스 화하고 그 메소드를 구현하는 것입니다. – FranMowinckel

+0

예. 그것이 내가해야 할 일이다. 모든 UIView에 적용 할 수있는 방식으로이 작업을 수행하려고했습니다. 하위 클래스를 만들면 하위 클래스를 다시 만들 수 없습니다. 예를 들어, UIView를 MyRoundView로 서브 클래 싱한다고 해봅시다. 자, UILabel을 원한다면 UILabel을 서브 클래스 화하고 그 코드를 복사할지 또는 MyRoundView를 서브 클래 싱할지 여부를 결정해야하며 UILabel과 함께 제공되는 메서드와 매개 변수가 없습니다. – steventnorris

0

을하지만 당신은 (350)로 너비 제약 조건을 유지

+0

문제는 제약 사항이 아닙니다. 이것은 정적이 아닌 폭/높이 제약 조건에서 작동해야하며, 생각하기 시작한 라이프 사이클에서 실행되는 위치를 기반으로하지 않습니다. – steventnorris

0

viewDidLayout으로 이동하지 않으려면 .layoutIfNeeded()를 추가하여 코너 반경을 설정하기 전에 간단히 트릭을 만들 수 있습니다.

yourCircleView.layoutIfNeeded() 
yourCircleView.layer.cornerRadius = yourCircleView.frame.size.width/2