본문 바로가기

프로그래밍/iOS,macOS

오토레이아웃 이것저것 / Constraint / UITextView

코드에서 제약 사항추가

view.translatesAutoResizingMaskIntoConstraints = NO


NSArray *array = [NSLayoutConstraint

constraintsWithVisualFormat:NSString*

options:NSLayoutFormatOptions

metrics:NSDictionary*

views:NSDictionary*


오브젝티브씨의 경우 NSDictionaryFromVariableBindings() 매크로를 사용하면 뷰들의 키와 값을 설정해준다.

옵션에 정렬등이 있어 사용시 유용하다. NSLayoutFormatAlignAllCenterX 등~



비주얼포맷 기본

| : 슈퍼뷰

[view1]-[view2] : 기본간격 8

[view1]-10-[view2] : 간격은 10

[view1][view2] : 붙임 ( [view1]-0-[view2] 와 동일 )

[view1(>=50)] : 너비가 50보다 크다

[view1(100@20)] : 너비는 100인데,  우선순위는 20

[view1(==view2)] : 너비가 같다

[view1(>=70,<=100)] : 최소, 최대 크기 지정





제약사항 업데이트

setNeetsUpdateConstraints 

updateConstraints

bottom-up 방식으로 서브뷰로부터 슈퍼뷰로 제약사항들이 계산된다.

커스텀뷰의 경우 updateConstraints 를 오버라이드해 제약을 추가/수정하고, setNeedsUpdateConstraints 를 호출해 업데이트 플래그를 활성화(?) 시켜야 한다.

이미 존재하는 제약의 변경은 업데이트 플래그가 내부적으로 설정되므로 추가로 호출할 필요는 없다.


레이아웃 처리

setNeedsLayout

레이아웃은 top-down 방식으로 실제 프레임사이즈와 바운드 사이즈 등을 결정하게 된다.

setNeedsLayout은 레이아웃 계산을 다시 하기위한 플래그를 설정하고, 즉시가 아닌 다음 루프에 처리하게 된다.


layoutIfNeeded

레이아웃을 즉시 계산해야 하는 경우 호출한다.


layoutSubviews

레이아웃 계산이 완료된 후 호출된다.



intrinsicContentSize

컨텐트의 사이즈 변경을 위해서는 intrinsicContentSize 메쏘드를 오버라이드 해야한다.


-(CGSize) intrinsicContentSize {

return CGSizeMake(100,100)

}


사이즈가 변경시 invalidateIntrinsicContentSize 메쏘드를 호출해주면 내부적으로 intrinsicContentSize 메쏘드가 호출된다.




match_parent

subview 가 있고, mainview 에 add 할때 부모크기에 맞춤(match parent)


[mainview addSubview:subview];

subview.translatesAutoresizingMaskIntoConstraints = NO;

NSDictionary *views = @{@"subview":subview};

[mainview addConstraints:

[NSLayoutConstraint

constraintsWithVisualFormat:@"H:|-0-[subview]-0-|"

options:NSLayoutFormatDirectionLeadingToTrailing

metrics:nil

views:views]];


[mainview addConstraints:

[NSLayoutConstraint

constraintsWithVisualFormat:@"V:|-0-[subview]-0-|"

options:NSLayoutFormatDirectionLeadingToTrailing

metrics:nil

views:views]];




애니메이션

일반 값을 변경하는 것처럼 constraint.constant 값을 변경해 주면 된다. 단, 애니메이션 블럭에서 view.layoutIfNeeded 를 호출해 주어야 한다.

[UIView animateWithDuration:0.3 animations:^{

[self.view layoutIfNeeded];

}





Update constraints

setNeedsUpdateConstraints : 제약사항의 추가/삭제 등으로 업데이트가 필요함을 설정한다.

이를 설정하면 updateConstraintsIfNeed 에서 updateConstraints를 호출하게 된다.

단순한 제약 값의 변경등은 호출할 필요가 없는듯(-_-;;)




UIScrollView with autolayout

UIScrollView 내부에 UIView 추가해 이를 Contents View로 사용

스크롤뷰의 상하좌우 제약 설정.

컨텐츠뷰의 상하좌우 제약 설정.

컨텐츠뷰의 width 제약은 스크롤뷰가 아닌 스크롤뷰의 상위뷰 width로 설정

컨텐츠뷰의 height 제약도 스크롤뷰의 상위뷰 height로 설정하고, 우선순위를 낮게 설정


높이를 스크롤뷰가 아닌 최상위 뷰와 맞추는게 포인트이다. 

단 제약사항의 우선운위를 낮음으로 해서 내부의 뷰 길이가 길어질 경우 제약을 무시하고 높이가 늘어나게 된다.


이후 루트뷰의 크기를 길게해서 컨텐츠뷰에 아이템들 추가하고, 아이템들 제약설정한다.



UITextView 동적 높이 변환과 스크롤

오토레이아웃으로 uitextview는 라인에 따라 동적으로 높이가 변화된다.

헌데, 특정 크기까지 늘어나다가 스크롤되는 형태는 지원하지 않는다. 

결론적으로 스크롤되는 uitextview는 오토레이아웃을 못 쓴다... 아마도~


일단 오토레이아웃 환경에서 스크롤이 가능한 uitextview는 intrinsicContentSize 가 의미가 

없으므로, 높이제약을 크거나 같게해서 최소 크기를 지정해 준다.


일단 기본 크기로는 나오는데, 특정 크기까지 늘어나는 코드는 아래에 넣는다.

-(void)textViewDidChange:(UITextView *)textView

{

CGFloat fixedWidth = textView.frame.size.width;

CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];

if( newSize.height < 100 )

{

CGRect newFrame = textView.frame;

newFrame.size = CGSizeMake( fixedWidth, newSize.height);

textView.frame = newFrame;

}


// 혹은 높이 제약을 IBOutlet으로 인스턴스해서 해당 제약을 조절해도 된다

if( newSize.height < 100 )

{

textViewHeightConstraint.constant = newSize.height;

}

}


이러면 100까지는 크기가 늘어나고, 이후는 스크롤이 적용된다.








UITableViewCell내의 UITextView셀프 리사이징(iOS 8)

UITextView 에 상하좌우 제약을 걸어주고, 높이 제약은 지정하지 않는다.

attribute inspector 에서 User Interaction Enabled, Scrolling Enabled 는 해제


셀프 리사이징을 사용하기 위해서는 테이블뷰에 셀의 높이가 자동으로 변화한다고 알려야 한다.


// 컨트롤러 viewDidLoad

_tableView.estimatedRowHeight = 50;

_tableView.rowHeight = UITableViewAutomaticDimension;




UICollectionView

UICollectionViewFlowLayout  그리드와 같은 선형으로 표시하는 레이아웃

scrollDirection 스크롤방향 : UICollectionViewScrollDirectionVertical / UICollectionViewScrollDirectionHorizontal


itemSize : 고정된 크기는 테이블뷰와 마찬가지로 아래 메쏘드를 오버라이딩해 넘겨준다.

-(CGSize)collectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout*)collectionViewLayout

sizeForItemAtIndexPath:(NSIndexPath *)indexPath

{

return CGSizeMake( 10.0f, 10.0f);

}


minimumLineSpacing / minimumInteritemSpacing / sectionInset / headerReferenceSize / footerReferenceSize



오토레이아웃 및 오토 리사이징을 지원하기 위해서는 기본 사이즈를 정해준다

_collectionView.collectionViewLayout.estimatedItemSize = CGSizeMake(100, 100);








오브젝트 숨기기

오브젝트를 숨기면서 이에 영향받는 오브젝트의 위치나 사이즈등으로 조절할 때 사용


A오브젝트와 B오브젝트가 화면에 있고, B오브젝트의 top은 A의 bottom으로 부터 n의 spacing이 제약사항으로

등록되어 있다면, A오브젝트의 높이제약(height)을 0으로 만들면 A오브젝트는 화면에서 보이지 않고, B 오브젝트는

자연스럽게 올라오게 된다.


A오브젝트의 높이제약을 일반 변수처럼 IBOutlet으로 연결시킨다.

@property IBOutlet NSLayoutConstraint *myViewHeight;



특정 이벤트 등으로 해당 제약값 변경

_myViewHeight.constant = 0;



뷰에서 제약 이름으로 찾기

IB에서 제약에 identifier 이름을 지정해둔다

NSLayoutConstraint *item;

for( item in [_myView constraints] ) {

if( [item.identifier isEqualToString:@"이름" ] == YES ) {

item.constant = 0;

}

}








'프로그래밍 > iOS,macOS' 카테고리의 다른 글

NSString 문자열 관련/정규식/텍스트뷰 등...  (0) 2016.11.07
이것저것 Objective-C 관련 노트~  (0) 2016.11.01
아이폰 시뮬레이터 로그 터미널로 보기  (0) 2016.11.01
모달 뷰  (0) 2016.10.28
ChildViewController  (0) 2016.10.27
커스텀객체와 인터페이스빌더  (0) 2016.10.23
스토리보드 / XIB  (0) 2016.10.22
싱글톤  (0) 2016.10.19
코어 데이터 정리  (0) 2016.10.18
슬라이드메뉴  (0) 2016.10.16