2018년 12월 19일 수요일

Create a Horizontal Paging UIScrollView with UIStackView

앱의 사용가이등의 화면을 통일되지않은 형태의 여러페이지로 보여주고자할때 UICollectionView보다는 UIStackView를 통해서Layout을 구성하면 보다 쉽게 원하는 UI를 구현할 수 있다.





STEP1.

IB에서 UIViewController의 Size를 1875*667로 설정한다. (iPhone8 Width * 5개페이지  = 1875)


STEP2.

IB에서 UIViewController에 UIScrollView 추가한다.

STEP3.

IB에서 UIScrollView에 UIStackView 추가. 다음과 같이 프라퍼티 설정 :
Axis = Horizontal
Distribution = Fill Equally
Spacing = 0

Constraints 설정 :
Trailing Space = Leading Space = Bottom Space = Top Space = 0
Align Center Y to Superview


STEP4.

UIView 5개를 UIStackView에 추가.
첫번째  UIView의 Width = 375로 설정, 나머지 UIView들의 Width를 첫번재 UIView의 Width와 같게 설정한다.



구조는 다음과 같이 보인다:





STEP5.

첫번째  UIView의 Width를 NSLayoutConstraint 멤버변수로 연결. 나중에 UIViewController:ViewDidLoad 함수에서 view의 Width로 설정. 이렇게 하는 이유는 UIView의 Width가 단말기의 Width와 안맞는 문제가 존재하기 때문에, 실제 단말기의 Width로 설정해 주기 위해서다.

override func viewDidLoad() {
        super.viewDidLoad()

        firstViewWidth.constant = self.view.frame.size.width
        


2018년 12월 3일 월요일

#pragma in Swift

// TODO : "to-do item"
// FIXME : "bug fix reminder"
// MARK : "comment"




- 추가하면 세퍼레이터로 나뉘어진다.

// TODO : - "to-do item"
// FIXME : - "bug fix reminder"
// MARK : - "comment"




2018년 11월 25일 일요일

재사용가능한 그룹뷰 만들기



PassGroupView.xib 생성하고 레이아웃 구성




PassGroupView.swift 생성

class PassGroupView: UIView {
    
    var height: CGFloat? {
        didSet {
            UIView.animate(withDuration: 0.2) {
                self.invalidateIntrinsicContentSize()
            }
        }
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.xibSetup()
    }
    
    public override var intrinsicContentSize: CGSize {
        if let height = height {
            return CGSize(width: frame.width, height: height)
        } else {
            return CGSize(width: frame.width, height: frame.height)
        }
    }
    
    private func xibSetup(){
        guard let xibName = NSStringFromClass(self.classForCoder).components(separatedBy: ".").last else { return }
        let view = Bundle.main.loadNibNamed(xibName, owner: self, options: nil)?.first as! UIView
        view.frame = self.bounds
        self.addSubview(view)
    }


}


PassGroupView.xib 에서 File's Owner를 PassGroupView로 지정





PassGroupView를 사용하고싶은 ViewController에 배치.




PassGroupView의 높이를 지정하지않고 Placeholder로 설정함.





뷰컨트롤러에서 PassGroupView의 intrinsicContentSize 수정.

class ViewController: UIViewController {

    @IBOutlet weak var passGroupView: PassGroupView!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }

    @IBAction func actionFold(_ sender: Any) {
        passGroupView.height = 41
    }
    
    @IBAction func actionUnfold(_ sender: Any) {
        passGroupView.height = 82
    }

}



실행결과 :

     






https://medium.com/zenchef-tech-and-product/how-to-visualize-reusable-xibs-in-storyboards-using-ibdesignable-c0488c7f525d



서브뷰들을 비율대로 배치하는 방법

1. UIView 안에서





서브뷰의 넓이를 부모뷰의 넓이로 지정하고 multiplier로 비율을 조정한면된다.


2. UIStackView 안에서











2018년 11월 22일 목요일

ScrollView의 컨텐츠에따라 동적으로 늘어나면서, 불필요할때는 안보이도록


<조건>
1.  스크롤뷰 안의 컨텐츠는 [답변영역]과 [문의영역]으로 나뉘어져있고, 각각의 영역은 Label 사이즈에 따라 자동으로 늘어난다.  
2. 답변이없는 경우에는 [답변영역]이 사라지고, [문의영역]이 위로 올라간다


                      





<솔루션>
1. 스크롤뷰에서 컨텐츠의 높이에 따라 컨테이너뷰들이 자동으로 늘어날 수 있도록 Constraints를 지정한다.




2. Source 코드에서 [답변영역]의 height constraint를 0으로하여 constraint를 추가한다.

override func viewDidLoad() {
        super.viewDidLoad()

        ...
        
        if questionItem?.status != "완료" {
            answerContainerView.heightAnchor.constraint(equalToConstant: 0).isActive = true
        }
    }


2018년 11월 18일 일요일

Two UIViews 사이, 및 앞, 뒤의 공백을 화면사이즈를 따라 Flexible하게 (두 뷰는 고정된사이즈) 하는 방법


두 뷰 사이의 공간 및  leading, tailing 공간이 화면사이즈에따라 늘어나고, 두 뷰는 고정된 사이즈를 유지하는 방법  :

<- flexible -> [view] <- flexible -> [view] <- flexible ->


1.  IB에서 레이아웃만 잡아주는것으로도 가능 함.





여기에서 핵심은  space 역활을 하는 뷰들을 같은 사이즈로 한다는것임.



2018년 11월 7일 수요일

Rounded Corner View

// define

extension UIView {
    func roundCorners(corners:UIRectCorner, radius: CGFloat) {
        DispatchQueue.main.async {
            let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            self.layer.mask = mask
        }

    }
}





// using


bubbleView.roundCorners(corners: [.topLeft, .bottomRight, .topRight], radius: 21)




https://www.appcoda.com/bezier-paths-introduction/