Layout

레이아웃은 앱에서 사용자 인터페이스를 위한 구조(Activity 등)를 결정.

  • 레이아웃의 모든 요소는 View와 ViewGroup 객체의 계층 구조를 사용하여 빌드된다.
  • View 는 사용자가 보고 상호작용할 수 있는 것.
    ViewGroup은 View 및 기타 ViewGroup 객체의 레이아웃 구조를 정의하는 보이지 않는 컨테이너

레이아웃을 선언하는 방법

UI 요소를 XML로 선언.

Android는 위젯, 레이아웃과 같이 View 클래스와 서브클래스에 상응하는 간단한 XML 문법을 통해 선언한다. Android Studio의 Layout Editor를 사용해서 마우스로 드로그 앤 드롭으로도 빌드할 수 있지만 보통 키보드로 빌드한다.

런타임에 레이아웃 요소 인스턴스화

직접 프로그래밍하여 View 및 ViewGroup객체를 만들고 그 속성을 따로 선언, 조작할 수 있다.
XML에서 UI를 선언하면 동적제어 코드로 앱 표현을 분리할 수 있다. 또한 XML 파일을 사용하면 다양한 화면 크기와 방향에 여러가지 레이아웃을 쉽게 제공할 수 있다.

위 두가지를 모두 사용하여 앱의 UI를 빌드할 수 있다. 예를 들어 앱의 기본 레이아웃을 XML에서 선언한 다음, 런 타임에 레이아웃을 수정할 수 있다.

XML

XML 쓰기

XML 어휘를 사용하여 UI Layout과 화면 요소를 중첩된 요소를 사용하는 방식으로 디자인.
각 Layout 파일에는 반드시 단 하나의 루트 요소만 있어야 -> View OR ViewGroup 객체. 루트 요소를 정의하고 더 많은 레이아웃 객체 또는 위젯을 하위 요소로 계층적 레이아웃 정의하는 View 계층 구조를 빌드할 수 있다.

아래 코드는 수직 LinearLayout 을 사용해 하위 요소로 TextView와 Button을 사용한 XML 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>


XML 리소스 로드

앱을 컴파일할 때 각 XML 레이아웃 파일이 View 리소스 안에 컴파일된다. Activity.onCreate() 콜백 구현해서 레이아웃 리소스를 로드해야 한다. 이 떄 setContentView()를 호출하고 R.layout.main_layout 의 형태로 참조한다. (Resource에 있는 layout 중 main_layout을 참조한다는 의미. 이때 main_layout 자리에 해당 레아아웃의 이름이 들어간다.)

아래 코드에서는 Activity가 시작될 때 main_layout이 View로 보여진다는 의미.

fun onCreate(savedInstanceState: Bundle) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_layout)
}

속성

모든 View와 ViewGroup 객체는 고유한 여러가지 XML 속성을 지원.(예_ ID, 레이아웃 매개변수, 위치정보, 크기, padding, margin 등) 물론 어떤 속성은 View 객체에만 적용되고(textSize), 어떤 속성은 ViewGroup 객체에 적용된다(ID).

ID

모든 View 객체는 뷰를 고유하게 식별할 수 있는 Integer ID를 연결될 수 있다.
android:id="@+id/my_button" 와 같이 사용한다.
안드로이드 프레임워크는 다른 ID 리소스도 많이 제공한다. 안드로이드 리소스 ID를 참조할 때는 '+' 기호는 필요하지 않지만 adroid 패키지 라는 것을 반드시 알려주어야 한다.
android:id="@android:id/empty"

android 패키지 네임스페이스가 들어가면 로컬 리소스 클래스가 아니라 android.R리소스 클래스에서 ID를 참조한다.

일반적으로 뷰를 생성하고 이를 앱에서 참조할 때는 아래와 같은 패턴
1. 레이아웃 파일에서 뷰/위젯을 정의, ID 할당

<Button android:id="@+id/my_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/my_button_text"/>
  1. 그리고 뷰 객체의 인스턴스를 생성하고 이를 레이아웃에서 받아온다.
val myButton: Button = findViewById(R.id.my_button) 

id는 트리 전체를 통틀어 고유할 필요는 없지만 트리에서 검색하는 부분 내에서는 고유해야 한다. 트리 전체를 검색할 경우가 잦으므로 왠만하면 고유한 것 사용하자.

레이아웃 매개변수

Layout의 종류에 따라 View가 있는 ViewGroup에 적절한 View 레이아웃 매개변수를 정의할 수 있다.
즉, 상위 뷰 그룹이 각 하위 뷰의 레이아웃 매개변수를 정의한다. 물론 하위요소에 각기 다른 LayoutParams도 정의할 수 있다.

너비와 높이도 정확한 치수로 정할 수 있지만 보통 wrap_content나 match_parent로 설정한다.

레이아웃 위치

뷰는 직사각형이다. 위치는 한쌍의 왼쪽 및 상단 좌표, 두개의 치수가 너비와 높이를 나타내는 형식[pixel]

뷰의 위치는 getLeft() 및 getTop() 메서드로 검색할 수 있다. 만약 getLeft()가 20을 리턴한다면 뷰가 그 뷰의 부모의 왼쪽 가장자리에서 오른쪽으로 20pix 떨어진 곳에 있다는 의미.
그 외 getRight() (= getLeft() + getWidth() ) , getBottom() 계산

크기, padding, margin

  1. 크기 : 하나의 뷰는 두 쌍의 너비 및 높이 값을 갖는다.
  • 첫번째 쌍 : 측정된 너비 및 측정된 높이. 이는 뷰가 부모 내에서 얼마나 커지고나 하는지? getMeasuredWidth() 및 getMeasuredHeight()로 치수를 리턴할 수 있따.
  • 두번째 쌍 : 단순 너비 및 높이(= 그리기 너비 및 높이). 뷰가 화면에 표시되는 실제 크기이다. getWidth() 및 getHeight() 호출
  1. padding
  • 정해진 픽셀 수를 사용하여 뷰의 내용을 안쪽으로 밀어낼 수 있다. 예를 들어 왼쪽 패딩 2 이면 뷰의 내용을 왼쪽 가장자리에서 오른쪽으로 2픽셀 밀어낸다. setPadding(left:int, top:int, right:int, bottom:int)로 설정, getPaddingLeft(), (Top(), Right(), Bottom()) 로 리턴한다.
  1. 뷰에서는 margin은 직접 제공하지 않는다.

실제로 자주 사용하는 공통 속성

layout_height : 세로 길이
layout_width : 가로 길이
layout_margin : View와 상위 레이아웃 사이의 공간(바깥 쪽에 해당 크기만큼의 공간이 생김)
padding : View와 View 안의 내용 사이의 공간 (안쪽에 해당 크기만큼의 공간이 생김.)
layout_gravity : 상위 레이아웃에서의 위치 정렬 (or연산자('|')를 이용해서 혼합 사용가능)
gravity : 해당 속성에서의 하위 속성 위치 정렬

일반 Layout의 종류

UI 디자인을 달성하기 위해 하나 이상의 레이아웃을 다른 레이아웃 안에 중첩 가능, 하지만 최대한 중첩을 적게!! 얕을수록 레이아웃이 더 빠르게 그려진다. (가로로 넓은 것이 세로로 깊은 계층보다 좋다)

- linearLayout

Linear : "선형의" -> 말그대로 레이아웃 안의 요소들을 가로 OR 세로 방향으로 선형적으로 나열 할 수 있다.
1) orientation : 요소들이 나열되는 방향을 지정해준다. 지정할 수 있는 방향으로 horizontal(가로), vertical(세로)가 있다.
2) layout_weight : 가중치를 의미한다. 요소들을 나열할 때 화면의 크기에 비례해서 요소의 크기를 결정할 때 사용한다.
3) weightSum : 가중치의 합을 의미한다. 가중치를 주어서 요소를 나열할 때 공백을 구성하고 싶을 때 사용한다.
- RelativeLayout

Relative : "상대적인" -> 레이아웃의 요소들을 상대적으로 나열하고 싶을 때 유용하게 사용.
1) 뷰와 뷰 사이의 상대적인 위치를 결정할 때
2) 부모인 RelativeLayout 기준으로 상대적인 위치를 결정할 때
3) 맞춤 정렬을 하고자 할 때
- FrameLayout
Frame : "액자" -> 액자에 사진을 꽂아놓고 보관하는 것처럼 여러개의 뷰를 바꿔가면서 화면에 표시할 수 있다.
1) 안드로이드에서는 특정한 이유가 없는 한 FrameLayout이 오직 하나의 뷰만 표시학 만들도록 권고.
(FrameLayout 안에 크기가 다른 뷰들을 겹치지 않게 구성하는 것이 어렵다네요)
2) 가장 마지막에 추가된 뷰가 전면에 표시됨.
3) addView(), removeView(), LayoutInflater, visibility,setVisibility

- GridLayout
자식을 직사각형 그리드에 배치하는 레이아웃.
그리드는 보이는 연역을 셀로 구분하는 선 집합으로 구성됨.

- TableLayout
Table : "표" -> 표처럼 사용할 수 있으며 열(Coulmn), 행(Row)로 표현된다.
1) TableRow 라는 요소를 사용하여 행(Row)을 추가할 수 있다.
2) TableRow 안에 View를 선언하여 열(column)을 추가할 수 있다.
- DrawerLayout
Drawer : "서랍" -> 화면을 서랍처럼 열고 닫는 기능을 한다.
1) DrawerLayout을 사용하기 위해서는 사용할 요소(View,TextView)가 자식(child)으로 추가되어 있어야 한다.
2) 추가로 어느 방향에서 열릴지 layout_gravity값이 설정되어 있어야 한다.
2) xml 파일을 새로 생성하여 DrawerLayout을 구현하든 DrawLayout 안에 TextView를 생성하든 DrawerLayout에서 제공하는 함수의 원형을 보면 두 개가 같다는 것을 알 수 있다.
3) openDrawer(), closeDrawer()
- ConstraintLayout
Constraint : "제약" -> 여러가지 제약 조건들을 이용해서 뷰의 크기와 위치를 결정
RelativeLayout의 "상대적인 위치 관계", LinearLayout의 "가중치" , Chain의 "요소 그룹화" 의 특징을 가짐.
1) Relative positioning : 상대 위치 지정 관련 속성
2) Margins :( layout_margin외에 대상 View 가보이지 않는 View.gone 상태일 때 여백 속성.(goneMargin)
3) Centering positioning and bias : bias 는 치우침. 수평/수직 방향으로 사이드 제약을 걸 때 사이드간 위치 비율을 지정.
4) Circular positioning : 원형 위치 지정은 대상 뷰의 id 와 거리, 각도값을 입력하여 나타낼 수 있다.
5) Visibility behavior : Visibility ㅡ특성과 Margins의 goneMargin 특성을 포함
6) Dimension constraints : 위젯의 크기를 조정하는데 유용하게 사용된다.
7) Chains : 가로/세로축에 대해 view들을 그룹지울 수 있다. 인접한 view끼리 서로 쌍방향 constraint 정의되어있을 때 cahin 관계에 있다고 본다.
8) Virtual Helper objects : 안드로이드는 ConstraintLayout이 사용을 돕기 위해 특별한 객체 몇가지 제공
Guideline, Group, Barrier 등
9) Optimizer : 제약 카테고리에 대한 최적화 기능.

출처:
![안드로이드 레이아웃]https://recipes4dev.tistory.com/66?category=658689
![안드로이드 레이아웃 공통사항]https://recipes4dev.tistory.com/87?category=658689
https://developer.android.com/guide/topics/ui/declaring-layout

profile
안드로이드 개발 공부

0개의 댓글