[Android] Layout2 — Linear Layout

dEpayse
dEpayse_publication
12 min readJan 22, 2021
  • 본 포스트는 Kotlin 언어로 Android studio 에서 작업할 수 있는 내용을 담고 있습니다.
  • 본 포스트는 Kotlin 언어에 관한 설명은 없습니다. Kotlin에 관한 내용은 저의 다른 포스트를 참고해주시면 감사하겠습니다.

Linear Layout

Linear Layout은 orientation(방향)과 gravity(중력)에 따라 포함하는 View를 차곡차곡 쌓는 레이아웃이다. Fig1는 orientation과 gravity에 따라 어떻게 View들이 배치되는지 나타낸 애니메이션이다.

Fig1. Linear Layout Animation

사용법

xml 에서 Linear Layout 사용하기

Fig2. xml에서 LinearLayout 사용

xml상에서 LinearLayout을 사용하는 방법은 간단하다. 가장 바깥의 레이아웃이 아니라면, LinearLayout은 Fig2처럼 필수 속성인 layout_width와 layout_height 값만 주고, <LinearLayout>과 </LinearLayout>사이에 View들을 배치하면 된다.

kotlin 파일에서 Linear Layout 사용하기

Fig3–1. Kotlin 파일에서 LinearLayout 추가
Fig3–2. Fig3–1실행 결과

Fig3–1은 코드에서 LinearLayout을 추가하는 방법이다. Activity를 생성했을 때 보이는 기본적인 코드에 관한 내용은 아래 링크된 포스트의 ‘생성된 Activity 살펴보기 파트’를 참고하자. 외곽 Linear Layout의 gravity값은 center이다.

코드는 linearLayout 을 화면에 추가하는 코드이고, 추가할 linearLayout은 가장 바깥의 linearLayout_outer라는 id를 갖는 Linear Layout에 들어간다. Layout 객체나 View객체를 생성한 후에는 addView()함수를 이용하여 추가해줘야한다. LayoutParams에 관련된 내용은 아래 포스트를 참조하자.

주요 속성

orientation(방향)

orientation은 Linear Layout에 View가 쌓이는 방향을 정해준다. 가능한 값으로는 vertical과 horizontal이 있으며, vertical은 수직 방향(항상 위->아래), horizontal은 수평 방향(항상 왼쪽->오른쪽)으로 View를 쌓는다. 기본값은 horizontal이다.

gravity(중력)

gravity는 Linear Layout 내의 View들이 어떤 방향으로 떨어지는지 정해준다. 기본값은 top|left이며, 왼쪽 위로 View들이 붙는다는 뜻이다. 이처럼 ‘|’ 기호를 통해 gravity의 값에 한 개 이상의 속성을 적용할 수 있다. 주의할 점은 ‘gravity’라는 속성도 있고 ‘layout_gravity’라는 속성도 있어서 차이를 알고 있어야 한다. gravity는 해당 View 내에 적용되는 중력이고, layout_gravity는 해당 View의 부모 ViewGroup(Layout) 내에서 해당 View에 적용되는 중력이다. 기본값은 GRAVITY_TOP이다.

layout_weight(가중치)

Linear Layout엔 layout_weight라는 속성이 있다. View에 layout_weight 값을 주면, View에 할당된 weight의 값대로 비율에 따라 크기가 할당된다. Layout내에 View의 크기를 비율로 할당할 수 있다는 것이다. 아래 Fig4을 보자. Fig4의 왼쪽 그림을 보면 세 개의 뷰에 linear_weight가 각각 1, 2, 3으로 주어진 걸 볼 수 있고, 오른쪽 그림을 보면 1:2:3의 비율로 크기가 나누어진 것을 볼 수 있다.

그러나 vertical Linear Layout는 height에만 적용되고, horizontal Linear Layout는 width에만 적용된다. 주의할 점은 height에 적용할 때는 layout_height값을 0dp, width에 적용할 때는 layout_width값을 0dp로 주어야 생각한 비율대로 나누어진다. layout_weight값은 다른 모든 layout_height 값(wrap_content, 숫자 + 단위)이나 layout_margin이 할당되고 남은 공간을 비율대로 나누기 때문이다.

Fig4. layout_weight example

Linear Layout의 여유 공간에 View들이 layout_weight에 따라 공간이 할당되는 방식은 다음과 같다. Fig4에서 첫 번째, 두 번째, 세 번째 뷰에 layout_weight이 각각 1, 2, 3이 주어졌다. 첫 번째 View에 할당되는 공간은 여유공간은 각각의 layout_weight값을 더한 값(1+2+3=6) 중에 첫 번째 View의 layout_weight의 값(1)이고, 두 번째, 세 번째도 첫 번째 View와 같은 방식으로 여유공간이 할당된다. 이 것을 도식화한 것이 Fig5 왼쪽 그림이다.

  • weightSum

여기서 각각의 View가 아닌 Linear Layout의 속성weightSum이라는 값을 주면, Fig5 왼쪽 그림의 각각의 분모가 각각의 layout_weight의 합이 아닌 weightSum이 된다. 예를 들어 LinearLayout의 weightSum을 10으로 준다면, 첫 번째 뷰, 두 번째 뷰, 세 번째 뷰가 갖는 공간은 각각 여유공간의 0.1, 0.2, 0.3이 된다. 나머지 0.4는 View와 margin을 제외한 나머지 공간에 할당된다. weightSum은 각각의 layout_weight 합보다 크거나 같아야 예상대로 동작할 것이다.

Fig5. weightSum 적용하기

주의할 점

View가 쌓이는 순서와 match_parent

LayoutParams에서 match_parent는 View를 감싸고 있는 ViewGroup의 남은 공간을 전부 차지한다고 했다. 그러나 vertical 방향 LinearLayout에서 세 개의 뷰를 배치한 후 코드의 위에서 첫 번째, 세 번째 뷰의 높이에 값을 주고 두 번째 뷰의 높이에 match_parent를 주면 화면에 뷰가 다 안나오는 것을 볼 수 있다.

Fig6. match_parent와 match_parent와 View가 쌓이는 순서

match_parent는 값을 주고 남은 공간을 차지하면 화면을 넘어가지 않을 것 같은데, 왜 Fig6 같은 결과가 나오는 걸까? 이유는 Linear Layout이 코드의 윗부분에 적힌 View부터 차례대로 공간을 할당하기 때문이다. 첫 번째 View에 wrap_content의 크기가 할당되고, 두 번째 View에 match_parent값을 주면 첫 번째 View를 할당하고 Linear Layout에 남은 공간을 전부 두 번째 View에 할당한다. 세 번째 View에 layout_margin이나 layout_height의 값을 주면, 이미 공간을 다 할당했기 때문에 Linear Layout의 크기를 벗어나게 되는 것이다. 화면의 위 아래가 각각 잘리는 이유는 LinearLayout의 gravity가 center이기 때문을 유추할 수 있다. Fig7Fig6의 코드에서 마지막(세 번째)View의 layout_height, layout_margin을 0dp으로 바꿨을 때와 비교한 그림이다.

Fig7. Fig6의 코드에서 마지막(세 번째)View의 layout_height, layout_margin을 0으로 바꿨을 때와 비교
  • view가 쌓이는 순서와 match_parent 정리 :

Linear Layout에서 match_parent 값을 준 View 이후에 width와 height가 1dp이상의 값을 갖는 View를 추가하면 vertical Linear Layout은 수직 방향으로 화면을 벗어나고, horizontal Linear Layout은 수평 방향으로 화면을 벗어난다.

gravity와 layout_gravity

gravity는 해당 View 내에 적용되는 중력이고, layout_gravity는 해당 View의 부모 ViewGroup(Layout) 내에서 해당 View에 적용되는 중력이다. Linear Layout을 활용하면서 gravity와 layout_gravity를 적용해보자.

Fig8–1. layout_gravity를 center 로 줬는데 왜??

Fig8을 보면 TextView에 layout_gravity에 center 값을 주어 부모 View에서 중앙에 위치하도록 작성한 xml인데, TextView가 수평으로만 중앙에 위치하고 수직으로는 변함이 없다. 그 이유는 LinearLayout의 방향(orientation) 때문이다. Linear Layout의 방향은 vertical이기 때문에 내부의 View들이 위 → 아래로 쌓는다는 규칙이 가장 우선시 된다. 따라서 이 Linear Layout 내의 View의 layout_gravity 값은 오로직 수평 방향으로만 작용한다. 그럼 어떻게 이 Layout의 내부의 View를 수직 중앙에 오게할 수 있을까? 바로 LinearLayout의 속성으로 중력값을 주는 것이다.

Fig8–2. gravity를 center로 줘야!!

만약 vertical 방향의 Linear Layout의 gravity를 center로 주고, 내부 View의 layout_gravity 속성을 left로 하면 어떤 결과가 나올까? 즉, 수평 방향으로 Linear Layout과 내부 View의 중력이 겹치면 어떤 결과가 선택될까? 답은 왼쪽으로 View가 치우친다. 이런 경우 범위가 더 작은 View의 속성이 선택된다.

Linear Layout이 horizontal 방향이어도, 같은 원리가 적용된다. 우선시되는 것은 orientation인 horizontal이고, 따라서 내부의 View는 layout_gravity가 수평 방향으로 적용되지 않는다. 그러나 수직 방향에 있어서 값이 겹칠 땐 내부 View 의 layout_gravity가 선택된다. 또한 만약 수평 방향으로 중력을 주고 싶다면 Linear Layout의 gravity 속성 값을 이용하면 된다.

Fig8–3. Layout의 gravity & 내부 View의 layout_gravity(출처: http://sandipchitale.blogspot.com/2010/05/linearlayout-gravity-and-layoutgravity.html)
  • gravity & layout_gravity 정리 :
  1. vertical Linear Layout의 경우 내부 View의 layout_gravity가 수직 방향으로 적용될 수 없고, horizontal Linear layout의 경우 내부 View의 layout_gravity가 수평 방향으로 적용될 수 없다.
  2. 만약 vertical Linear Layout의 수직 방향으로 중력을 주고 싶거나, horizontal Linear Layout의 수평 방향으로 중력을 주고 싶으면 Linear Layout 자체의 gravity 속성을 이용해야 한다.
  3. vertical Linear Layout의 경우 Layout의 수평 방향의 gravity 값과 내부 View의 layout_gravity값이 겹친다면 더 작은 범위인 layout_gravity 값이 적용된다. horizontal Linear Layout의 경우 수직 방향으로 똑같은 원리가 적용된다.

Reference

layout_weight part

  1. [개발자를 위한 레시피] ‘안드로이드 리니어레이아웃. (Android LinearLayout)’ — https://recipes4dev.tistory.com/89

--

--

dEpayse
dEpayse_publication

나뿐만 아니라 다른 사람들도 이해할 수 있도록 작성하는, 친절한 블로그를 목표로.