본문 바로가기
개발/ios

UIView에 동적으로 버튼을 넣을때 크기를 같게 맞출려면?

by 매몰 2017. 4. 25.

안드로이드에서는 layout_weight 로 쉽게 하위 뷰들의 크기를 맞출 수 있다

 

예를 들어 버튼을 넣는다면 버튼에 layout_weight=1 속성을 추가한 후 

LinearLayout에 넣기만 하면 된다

또한 버튼 사이 간격은 layout_margin 로 조절한다

 

그렇다면 iso의 swift에선 어떻게 하면 될까?

약간 손이 더 가긴 하지만 어렵지 않다

 

 

 

 

편하게 사용하기 위해 UIView를 커스텀해서 만들어 보았다

버튼 크기를 맞춰주는 동시에 사이 간격, 여백도 줄것이다

 

 

 

class ButtonsView: UIView {

    

    private var mGap: CGFloat!

    private var mPadding: (left: CGFloat, top: CGFloat, right: CGFloat, bottom: CGFloat)!

    

    var mDelegate: ButtonsViewDelegate?

    

    //버튼간의 공간과 여백을 설정한다

    func setPadding(gap: CGFloat?, left: CGFloat, top: CGFloat, right: CGFloat, bottom: CGFloat) {

        //버튼간의 공간

        mGap = gap

        

        //여백

        mPadding = (left, top, right, bottom)

    }

    

    //버튼을 추가한다

    func addButton(name: String, color: CGColor) {

        //버튼을 생성한다

        let view = UIButton()

        

        //Autoresize 끈다

        //왜냐하면 우리는 직접 Constraint 설정해주기 때문이다

        view.translatesAutoresizingMaskIntoConstraints = false

        view.setTitle(name, forState: .Normal)

        view.layer.backgroundColor = color

        view.layer.cornerRadius = 5

        

        let count = subviews.count

        let padding = mPadding

        

        if count == 0 {

            //첫번째 버튼은 부모뷰와 맞게하고 그저 여백만 준다

            

            //부모뷰에 버튼을 추가한다

            addSubview(view)

            

            //부모뷰와의 상위 여백을 만든다

            addConstraint(NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: padding!.top))

            

            //부모뷰와의 하위 여백을 만든다

            addConstraint(NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal, toItem: self, attribute: .Bottom, multiplier: 1, constant: -padding!.bottom))

            

            //부모뷰와의 왼쪽 여백을 만든다

            addConstraint(NSLayoutConstraint(item: view, attribute: .Leading, relatedBy: .Equal, toItem: self, attribute: .Leading, multiplier: 1, constant: padding!.left))

            

            //부모뷰와의 오른쪽 여백을 만든다

            addConstraint(NSLayoutConstraint(item: view, attribute: .Trailing, relatedBy: .Equal, toItem: self, attribute: .Trailing, multiplier: 1, constant: -padding!.right))

        }

        else {

            //두번째 버튼부터는 첫번째 버튼과 같은 크기로 하고, 사이를 설정해 값으로 띄운다

            

            //부모뷰에 버튼을 추가하기 전에 첫번째, 마지막 버튼과 마지막 constraint 가져온다

            let firstView = subviews.first

            let lastView = subviews.last

            let lastConstraint = constraints.last

            

            //부모뷰에 버튼을 추가한다

            addSubview(view)

            

            //첫번째 버튼과 같은 크기로 만든다

            //, 버튼들이 늘어난 버튼 갯수만큼 작아지면서 같아진다

            addConstraint(NSLayoutConstraint(item: view, attribute: .Width, relatedBy: .Equal, toItem: firstView, attribute: .Width, multiplier: 1, constant: 0))

            

            //첫번째 버튼과 상위를 맞춘다

            addConstraint(NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: firstView, attribute: .Top, multiplier: 1, constant: 0))

            

            //첫번째 버튼과 하위를 맞춘다

            addConstraint(NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal, toItem: firstView, attribute: .Bottom, multiplier: 1, constant: 0))

            

            //이전 버튼과 사이를 띄운다

            addConstraint(NSLayoutConstraint(item: view, attribute: .Leading, relatedBy: .Equal, toItem: lastView, attribute: .Trailing, multiplier: 1, constant: mGap!))

            

            //마지막 constraint , 이전 버튼의 오른쪽 여백을 제거한다

            removeConstraint(lastConstraint!)

            

            //현재 버튼으로 다시 오른쪽 여백을 만든다

            addConstraint(NSLayoutConstraint(item: view, attribute: .Trailing, relatedBy: .Equal, toItem: self, attribute: .Trailing, multiplier: 1, constant: -padding!.right))

        }

        

        //클릭 이벤트를 잡는다

        view.addTarget(self, action: "clickDetected:", forControlEvents: .TouchUpInside)

    }

    

    //모든 버튼을 제거한다

    func removeAllButtons() {

        for view in subviews {

            view.removeFromSuperview()

        }

    }

    

    //클릭 이벤트를 보낸다

    func clickDetected(sender: UIButton) {

        if mDelegate != nil {

            //클릭 이벤트의 전달 변수로 버튼 객체와 버튼 인덱스 번호를 보낸다

            mDelegate?.clickButtonsDetected(sender, position: subviews.indexOf(sender)!)

        }

    }

}

 

//클릭 이벤트를 보내기 위한 델리게이트

protocol ButtonsViewDelegate {

    func clickButtonsDetected(sender: UIButton, position: Int)

 

}

 

 

 

 

 

 

보통 이런 방식은 탭으로 많이 사용된다

탭 버튼으로 적용해 보자

 

먼저 스토리보드에서 화면을 다음과 같이 구성한다.

위의 푸른색 Add 와 clear 버튼은 각각 탭버튼 추가가 탭버튼 모두 삭제 기능을 갖는다

중간의 검정색 Name 과 Position 라벨은 탭버튼 이름과 번호를 표시한다.

끝으로 가장 아래의 회색 공간은 위에서 만든 buttonsView이다. 이곳에 탭버튼이 나타날것이다 

 

 

 

 

 

 

 

 

뷰컨트롤러이다

위에서 만든 프로토콜 델리게이션을 추가하고 처음에 탭버튼 3개를 만들어 놓는다

추가, 제거 버튼 및 탭버튼 클릭 함수도 등록한다

 

 

 

class ViewController: UIViewController, ButtonsViewDelegate {

 

    @IBOutlet var tabView: ButtonsView!

    @IBOutlet var buttonLabel: UILabel!

    @IBOutlet var positionLabel: UILabel!

    

    override func viewDidLoad() {

        super.viewDidLoad()

        

        //delegate 설정

        tabView.mDelegate = self

        

        //버튼 설정 생성

        tabView.setPadding(10, left: 10, top: 10, right: 10, bottom: 10)

        tabView.addButton("버튼1", color: UIColor.blueColor().CGColor)

        tabView.addButton("버튼2", color: UIColor.redColor().CGColor)

        tabView.addButton("버튼3", color: UIColor.greenColor().CGColor)

    }

 

    override func didReceiveMemoryWarning() {

        super.didReceiveMemoryWarning()

        

    }

 

    @IBAction func clickAddDetected(sender: AnyObject) {

        //버튼 추가

        tabView.addButton("new", color: UIColor.brownColor().CGColor)

    }

    

    @IBAction func clickClearDetected(sender: AnyObject) {

        //모든 버튼 제거

        tabView.removeAllButtons()

    }

    

    func clickButtonsDetected(sender: UIButton, position: Int) {

        //버튼 출력

        buttonLabel.text = sender.titleLabel?.text

        positionLabel.text = "p: \(position)"

    }

 

}

 

 

 

 

 

실행해 보자

 

 

 

 

 

 

 

 

 

 

 

도움이 되셨다면~ 정성으로 빚은 저희 앱!  많은 이용 바래요:)

 

https://meorimal.com/index.html?tab=spaceship

 

우주선 - 방치형 인공지능 투자 체험기

미리 맛보는 인공지능 투자!

(주)머리말 meorimal.com

 

https://meorimal.com/subway.html

 

지하철어디있니

더이상 고민하지 마세요. 뛸지 말지 딱 보면 알죠.

(주)머리말 meorimal.com

 

사업자 정보 표시
주식회사 머리말 | 고영진 | 서울특별시 송파구 중대로 135 서관 10층 (가락동, 아이티벤처타워) | 사업자 등록번호 : 524-88-00727 | TEL : 010-9990-3674 | Mail : gyjmeba@hanmail.net | 통신판매신고번호 : 2017-서울강남-03941호 | 사이버몰의 이용약관 바로가기