Android

안드로이드 레이아웃(Layout)

print("스테코더") 2021. 7. 16. 22:34
Layout 이란?

 

ViewGroup의 일종으로 다른 뷰들을 내부에 배치하는 역할을 수행한다.

Layout은 내부에 위젯이나 다른 Layout을 내부에 배치함으로써 다양한 화면을 구성한다.

일반적으로 Layout은 화면 상에 직접 보이지는 않는다.

 

주요 레이아웃으로는 LinearLayout, RelativeLayout, FrameLayout, GridLayout이 있으며, 추가적인 레이아웃으로 ConstraintLayout이 있다.

그럼 레이아웃에 대해 더욱 자세히 살펴보도록 하겠다.

 


LinearLayout

 

LinearLayout은 가장 간단한 레이아웃으로 가로 또는 세로의 순서대로, 즉, 한 방향으로만 항목을 배치한다.

주요 속성은 다음과 같다.

 

 

1. orientation 

orientation 속성으로 항목들의 나열 방식을 결정할 수 있다.

이는 vertical, horizontal 속성 값을 가질 수 있다.

 

먼저, vertical은 항목을 세로 (수직)으로 배치하도록 한다.

 

vertical 

 

그와 반대로 horizontal은 항목을 가로 (수평)으로 배치하도록 한다.

 

horizontal

 

2. gravity

gravity는 내부 항목의 수직/수평 방향의 배치를 결정한다.

예를 들어, TextView 내부의 글자 배치와 같은 내부에 담고 있는 항목의 정렬을 결정하는 속성이다.

 

3. layout_gravity

gravity와 반대로 layout_gravity는 레이아웃에 항목 자신의 수직/수평 방향 배치를 결정한다.

즉, 담겨져 있는 레이아웃 상에서의 정렬을 의미한다.

 

gravity / layout_gravity 예시

 

※ 주의 사항

gravity와 layout_gravity를 사용할 때 주의해야할 점은 orientation의 vertical & horizontal 속성이 설정되었을 경우, 이것이 더욱 우선시 되기 때문에 layout_gravity를 사용하여도 적용이 되지 않는다.

이럴 경우에는 레이아웃 안에 담겨져 있는 속성이 아닌, 레이아웃을 선택한 후 gravity로 배치를 설정할 수 있다.

 

layout_margin / padding 예시

4. baselineAligned

레이아웃에 배치한 뷰들의 아래 부분 맞춤 활성화 여부를 결정한다.

 

5. layout_weight

레이아웃의 공간을 어느 정도 비중으로 차지하느냐를 결정한다.

0일 경우에는 본래의 크기, 1 이상이면 다른 뷰와의  비율에 따라 레이아웃에 배치한다.

 

6. layout_margin

레이아웃과 뷰 사이의 간격을 나타낸다.

 

7. padding

뷰와 내부 내용물 사이의 간격을 나타낸다.

 

 

 

RelativeLayout

 

RelativeLayout은 뷰와 뷰를 담고 있는 레이아웃 (부모 뷰), 그리고 다른 뷰들과의 상대적인 관계로 배치하는 레이아웃이다.

'상대적인 관계'로 배치하기 때문에 각각의 뷰들의 id가 필수적으로 요구된다.

 

FrameLayout

 

FrameLayout은 레이아웃의 좌측 상단에 모든 뷰들을 겹쳐서 배열하는 레이아웃이다.

앱 실행 중 addView / removeView 메소드를 사용하여 뷰들을 추가 및 삭제한다.

FrameLayout은 뷰의 visibility 속성을 사용하여 한 화면에서 여러 화면을 번갈아 보여주고 싶을 때 사용한다.

 

그 밖의 레이아웃

 

1. AbsoluteLayout : 배치하는 View의 좌표를 절대값으로 지정하여 배치한다. 일반적으로 사용하지 않는 레이아웃에 속한다.

2. TableLayout

표 형식으로 View를 내부에 배치한다.

가로는 TableRow의 개수만큼 행을 생성하고, 세로는 TableRow에 포함한 View의 개수만큼 열을 생성한다.

3. GridLayout

4. ConstraintLayout : 뷰들을 상대적으로 배치한다. 

 


실행 중 레이아웃 속성 변경

 

XML로 지정한 레이아웃 속성은 소스코드 실행 중 변경이 가능하다.

변경 과정은 다음과 같다.

 

1. XML로 지정한 뷰 객체를 찾은 후 변경 메소드를 호출한다. 

아래 예시를 살펴보자.

LinearLayout layout = (LinearLayout)findViewById(R.id.LinearLayout1);

 

예시는 XML에서 지정한 id가 LinearLayout1 인 레이아웃을 객체화하고 있다.

 

여기서 findViewById() 메소드는 XML로 정의하여 자동 변환된 뷰 요소를 찾기 위한 메소드이다.

◎ Activity.findViewById() : Activity 내부의 모든 뷰에서 검색

◎ View.findViewById() : 특정 뷰 내부에서만 검색

이 메소드는 객체 형태로 반환하므로 타입캐스팅이 필요하지만, 안드로이드 스튜디오의 버전이 올라가며 필요가 없어졌다.

 

2. 객체화 한 뷰 객체에서 속성에 해당하는 메소드를 호출한다.

 

대부분의 경우 속성에 해당하는 getter/setter 가 존재한다. 

이를 이용하여 속성 값을 임의의 값이나 정해진 상수값으로 지정할 수 있다.

 

예를 들어, LinearLayout의 orientation 을 수평으로 바꾸고 싶을 때는 다음과 같은 코드를 통해 해결할 수 있다.

layout.setOrientation(LinearLayout.HORIZONTAL);

 

또한, 다음과 같이 getter을 사용하여 LinearLayout의 현재 orientation을 확인할 수 있다.

int o = layout.getOrientation();

 

레이아웃 전개 (Inflation)

 

XML로 지정한 뷰는 aapt (android asset packaging tool)에 의해 컴파일되고, 이를 통해 이진 형태의 자바 객체로 변환된다.

 

Inflation 이란?

Inflation은 XML 문서의 텍스트 형태의 뷰를 실제 자바 객체화 하는 것을 말한다.

 

XML로 정의하면 뷰의 id가 R 폴더에 등록되며 자동으로 자바 객체로 변환된다.

이렇게 변환된 자바 객체는 Inflation 진행 후 findViewById() 메소드를 이용하여 해당 객체를 참조한다.

즉, R.java 에 자동 기록된 정수형 상수 아이디로 객체를 참조한다.

 

inflation 과정

 

setContentView() 메소드

setContentView() 메소드는 View를 전달받아 Activity에 등록하는 역할을 수행한다.

setContentView() 메소드는 아래와 같이 재정의 되어있는데, 각각 Activity에 등록하는 과정이 다르게 이루어 진다.

void Activity.setContentView (int layoutResourceID); // xml 파일명
void Activity.setContentView (View view [, ViewGroup.LayoutParams params] ); // view 객체

 

 

1. Layout의 resource id를 매개변수로 전달받을 경우

내부에서 inflation 수행 후 setContentView() 메소드를 통해 Activity에 등록한다.

setContentView(R.layout.activity_main);

2. View 객체 (및 params 객체)를 전달받을 경우

View를 params 정보에 따라 Activity에 등록한다. 

LinearLayout linear = new LinearLayout(this);
// ...
setContentView(linear);

 

Inflation 직접 실행

Inflation을 직접 실행해야하는 경우도 있다.

예를 들어, 앱 실행 중 화면의 구성을 바꾸어야 할 경우, 상황에 따라 서로 다른 화면 구성이 교체되어야 할 때 등 필요할 경우 앱 실행 중 직접 Inflation을 수행한다.

 

Inflation 관련 메소드는 다음과 같다.

LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);

// LayoutInflater = LayoutInflater.from(this);
// 여기서 this는 context 객체인 Activity 자기 자신을 의미

LinearLayout linear = (LinearLayout)inflater.inflate(R.layout.activity_main, null);

// LinearLayout linear = (LinearLayout)View.inflate(this, R.layout.activity_main, null);
// View가 갖고 있는 정적 메소드 inflate 사용

setContentView(linear);

 


Layout Parameter

 

뷰는 Layout Parameter를 통해 레이아웃 상에 배치되는 정보를 저장한다.

각 레이아웃마다 사용하는 정보가 다르므로 레이아웃에 배치할 때 뷰와 함께 매개변수로 전달한다.

LinearLayout linear = new LinearLayout(this);
linear.setOrientation(LinearLayout.VERTICAL); // orientation 속성 변경

TextView text = new TextView(this);
text.setText("TextView");

// Layout Parameter
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
	LinearLayout.LayoutParams.WRAP_CONTENT,
    LinearLayout.LayoutParams.WRAP_CONTENT);
    
linear.addView(text, params); 

setContentView(linear);